<commit_before>// TwistyPuzzle.cpp

#include "TwistyPuzzle.h"
#include <Surface.h>
#include <ListFunctions.h>

//---------------------------------------------------------------------------------
//                                  TwistyPuzzle
//---------------------------------------------------------------------------------

wxIMPLEMENT_ABSTRACT_CLASS( TwistyPuzzle, wxObject )

TwistyPuzzle::TwistyPuzzle( void )
{
}

/*virtual*/ TwistyPuzzle::~TwistyPuzzle( void )
{
	Clear();
}

void TwistyPuzzle::Clear( void )
{
	_3DMath::FreeList< Face >( faceList );
	_3DMath::FreeList< CutShape >( cutShapeList );
	_3DMath::FreeList< Rotation >( rotationQueue );
}

void TwistyPuzzle::EnqueueRotation( Rotation* rotation )
{
	rotationQueue.push_back( rotation );
}

bool TwistyPuzzle::ProcessRotationQueue( const _3DMath::TimeKeeper& timeKeeper )
{
	bool motion = false;

	for( FaceList::iterator iter = faceList.begin(); iter != faceList.end(); iter++ )
	{
		Face* face = *iter;
		if( face->rotationAngleForAnimation != 0.0 )
		{
			double rotationRateRadiansPerSecond = -face->rotationAngleForAnimation * 10.0;
			double thresholdAngle = 0.01;

			if( fabs( face->rotationAngleForAnimation ) < thresholdAngle )
				face->rotationAngleForAnimation = 0.0;
			else
				face->rotationAngleForAnimation += rotationRateRadiansPerSecond * timeKeeper.GetDeltaTimeSeconds();

			motion = true;
		}
	}

	if( !motion )
	{
		if( rotationQueue.size() == 0 )
			return false;

		RotationList::iterator iter = rotationQueue.begin();
		Rotation* rotation = *iter;
		rotationQueue.erase( iter );

		CutShape* cutShape = ( CutShape* )_3DMath::HandleObject::Dereference( rotation->cutShapeHandle );
		if( cutShape )
		{
			FaceList capturedFaceList;
			cutShape->CutAndCapture( faceList, capturedFaceList );

			double rotationAngle = rotation->turnCount * cutShape->rotationAngleForSingleTurn;
			if( rotation->direction == Rotation::DIR_CW )
				rotationAngle = -rotationAngle;
			rotationAngle = fmod( rotationAngle, 2.0 * M_PI );

			_3DMath::AffineTransform transform;
			transform.SetRotation( cutShape->axisOfRotation, rotationAngle );

			for( FaceList::iterator iter = capturedFaceList.begin(); iter != capturedFaceList.end(); iter++ )
			{
				Face* face = *iter;
				face->polygon->Transform( transform );
				face->axisOfRotation = cutShape->axisOfRotation;
				face->rotationAngleForAnimation = -rotationAngle;
			}
		}

		delete rotation;
	}

	return true;
}

void TwistyPuzzle::MakeBox( double width, double height, double depth )
{
	Face* face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, depth / 2.0 ) );
	face->color.Set( 1.0, 1.0, 1.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->color.Set( 1.0, 1.0, 0.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, depth / 2.0 ) );
	face->color.Set( 1.0, 0.0, 0.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->color.Set( 1.0, 0.5, 0.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->color.Set( 0.0, 0.0, 1.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->color.Set( 0.0, 1.0, 0.0 );
	faceList.push_back( face );
}

/*virtual*/ void TwistyPuzzle::IncrementallySolve( RotationList& rotationList ) const
{
}

/*virtual*/ void TwistyPuzzle::Render( _3DMath::Renderer& renderer, const _3DMath::AffineTransform& transform, GLenum renderMode, int selectedObjectHandle )
{
	_3DMath::LinearTransform normalTransform;
	transform.linearTransform.GetNormalTransform( normalTransform );

	for( FaceList::iterator iter = faceList.begin(); iter != faceList.end(); iter++ )
	{
		Face* face = *iter;
		face->UpdateTessellationIfNeeded();
		face->Render( renderer, renderMode, transform, normalTransform );
	}

	if( renderMode == GL_RENDER )
	{
		for( CutShapeList::iterator iter = cutShapeList.begin(); iter != cutShapeList.end(); iter++ )
		{
			CutShape* cutShape = *iter;
			if( cutShape->GetHandle() == selectedObjectHandle )
			{
				_3DMath::Vector color( 0.5, 0.5, 0.5 );
				glDepthMask( GL_FALSE );
				renderer.DrawSurface( *cutShape->surface, color, 0.2, &transform );
				glDepthMask( GL_TRUE );
			}
		}
	}

	for( CutShapeList::iterator iter = cutShapeList.begin(); iter != cutShapeList.end(); iter++ )
	{
		CutShape* cutShape = *iter;

		_3DMath::Vector vector, position, color;

		transform.Transform( cutShape->axisOfRotation.center, position );
		normalTransform.Transform( cutShape->axisOfRotation.normal, vector );

		vector.Scale( 10.0 );

		if( cutShape->GetHandle() == selectedObjectHandle )
			color.Set( 0.8, 0.8, 0.8 );
		else
			color.Set( 0.5, 0.5, 0.5 );

		if( renderMode == GL_SELECT )
			glLoadName( cutShape->GetHandle() );

		renderer.DrawVector( vector, position, color, 0.5, 0.5 );
	}
}

//---------------------------------------------------------------------------------
//                               TwistyPuzzle::Face
//---------------------------------------------------------------------------------

TwistyPuzzle::Face::Face( _3DMath::Polygon* polygon )
{
	this->polygon = polygon;
	tessellationNeeded = true;
	rotationAngleForAnimation = 0.0;
}

TwistyPuzzle::Face::~Face( void )
{
	delete polygon;
}

void TwistyPuzzle::Face::UpdateTessellationIfNeeded( void )
{
	if( tessellationNeeded )
	{
		polygon->Tessellate();
		tessellationNeeded = false;
	}
}

void TwistyPuzzle::Face::Render( _3DMath::Renderer& renderer, GLenum renderMode, const _3DMath::AffineTransform& transform, const _3DMath::LinearTransform& normalTransform ) const
{
	// TODO: We might select faces, but until then bail if we're not in render mode.
	if( renderMode != GL_RENDER )
		return;

	glLineWidth( 2.5f );

	_3DMath::AffineTransform renderTransform;

	_3DMath::AffineTransform animationTransform;
	animationTransform.SetRotation( axisOfRotation, rotationAngleForAnimation );
	renderTransform.Concatinate( animationTransform, transform );

	renderer.Color( color );
	renderer.DrawPolygon( *polygon, &renderTransform );

	if( renderer.drawStyle == _3DMath::Renderer::DRAW_STYLE_SOLID )
	{
		renderer.drawStyle = _3DMath::Renderer::DRAW_STYLE_WIRE_FRAME;

		_3DMath::AffineTransform scaleTransform;
		scaleTransform.linearTransform.SetScale( 1.01 );

		_3DMath::AffineTransform silhouetteTransform;
		silhouetteTransform.Concatinate( scaleTransform, renderTransform );

		renderer.Color( _3DMath::Vector( 0.0, 0.0, 0.0 ), 1.0 );
		renderer.DrawPolygon( *polygon, &silhouetteTransform );

		renderer.drawStyle = _3DMath::Renderer::DRAW_STYLE_SOLID;
	}
}

//---------------------------------------------------------------------------------
//                               TwistyPuzzle::CutShape
//---------------------------------------------------------------------------------

TwistyPuzzle::CutShape::CutShape( void )
{
	axisOfRotation.center.Set( 0.0, 0.0, 0.0 );
	axisOfRotation.normal.Set( 0.0, 0.0, 1.0 );
	captureSide = _3DMath::Surface::OUTSIDE;
	rotationAngleForSingleTurn = 0.0;
	surface = nullptr;
}

TwistyPuzzle::CutShape::~CutShape( void )
{
	delete surface;
}

void TwistyPuzzle::CutShape::CutAndCapture( FaceList& faceList, FaceList& capturedFaceList )
{
	capturedFaceList.clear();

	FaceList::iterator iter = faceList.begin();
	while( iter != faceList.end() )
	{
		FaceList::iterator nextIter = iter;
		nextIter++;

		Face* face = *iter;

		_3DMath::PolygonList polygonList;
		if( face->polygon->SplitAgainstSurface( surface, polygonList, 1.0 ) )
		{
			while( polygonList.size() > 0 )
			{
				_3DMath::PolygonList::iterator polyIter = polygonList.begin();
				_3DMath::Polygon* polygon = *polyIter;
				polygonList.erase( polyIter );
				Face* newFace = new Face( polygon );
				newFace->color = face->color;
				faceList.push_front( newFace );
			}

			delete face;
			faceList.erase( iter );
		}

		iter = nextIter;
	}

	iter = faceList.begin();
	while( iter != faceList.end() )
	{
		Face* face = *iter;
		face->UpdateTessellationIfNeeded();

		// TODO: For every center of every triangle in the tessellation,
		//       which side is it on?  Favor the side most found on.

		_3DMath::Vector center;
		face->polygon->GetTriangleAverageCenter( center );

		_3DMath::Surface::Side side = surface->GetSide( center );
		if( side == captureSide )
			capturedFaceList.push_back( face );

		iter++;
	}
}

//---------------------------------------------------------------------------------
//                              TwistyPuzzle::Rotation
//---------------------------------------------------------------------------------

TwistyPuzzle::Rotation::Rotation( int cutShapeHandle, Direction direction, double turnCount )
{
	this->cutShapeHandle = cutShapeHandle;
	this->direction = direction;
	this->turnCount = turnCount;
}

TwistyPuzzle::Rotation::~Rotation( void )
{
}

// TwistyPuzzle.cpp<commit_msg>hopefully this is the most reliable way to do this to-date<commit_after>// TwistyPuzzle.cpp

#include "TwistyPuzzle.h"
#include <Surface.h>
#include <ListFunctions.h>

//---------------------------------------------------------------------------------
//                                  TwistyPuzzle
//---------------------------------------------------------------------------------

wxIMPLEMENT_ABSTRACT_CLASS( TwistyPuzzle, wxObject )

TwistyPuzzle::TwistyPuzzle( void )
{
}

/*virtual*/ TwistyPuzzle::~TwistyPuzzle( void )
{
	Clear();
}

void TwistyPuzzle::Clear( void )
{
	_3DMath::FreeList< Face >( faceList );
	_3DMath::FreeList< CutShape >( cutShapeList );
	_3DMath::FreeList< Rotation >( rotationQueue );
}

void TwistyPuzzle::EnqueueRotation( Rotation* rotation )
{
	rotationQueue.push_back( rotation );
}

bool TwistyPuzzle::ProcessRotationQueue( const _3DMath::TimeKeeper& timeKeeper )
{
	bool motion = false;

	for( FaceList::iterator iter = faceList.begin(); iter != faceList.end(); iter++ )
	{
		Face* face = *iter;
		if( face->rotationAngleForAnimation != 0.0 )
		{
			double rotationRateRadiansPerSecond = -face->rotationAngleForAnimation * 10.0;
			double thresholdAngle = 0.01;

			if( fabs( face->rotationAngleForAnimation ) < thresholdAngle )
				face->rotationAngleForAnimation = 0.0;
			else
				face->rotationAngleForAnimation += rotationRateRadiansPerSecond * timeKeeper.GetDeltaTimeSeconds();

			motion = true;
		}
	}

	if( !motion )
	{
		if( rotationQueue.size() == 0 )
			return false;

		RotationList::iterator iter = rotationQueue.begin();
		Rotation* rotation = *iter;
		rotationQueue.erase( iter );

		CutShape* cutShape = ( CutShape* )_3DMath::HandleObject::Dereference( rotation->cutShapeHandle );
		if( cutShape )
		{
			FaceList capturedFaceList;
			cutShape->CutAndCapture( faceList, capturedFaceList );

			double rotationAngle = rotation->turnCount * cutShape->rotationAngleForSingleTurn;
			if( rotation->direction == Rotation::DIR_CW )
				rotationAngle = -rotationAngle;
			rotationAngle = fmod( rotationAngle, 2.0 * M_PI );

			_3DMath::AffineTransform transform;
			transform.SetRotation( cutShape->axisOfRotation, rotationAngle );

			for( FaceList::iterator iter = capturedFaceList.begin(); iter != capturedFaceList.end(); iter++ )
			{
				Face* face = *iter;
				face->polygon->Transform( transform );
				face->axisOfRotation = cutShape->axisOfRotation;
				face->rotationAngleForAnimation = -rotationAngle;
			}
		}

		delete rotation;
	}

	return true;
}

void TwistyPuzzle::MakeBox( double width, double height, double depth )
{
	Face* face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, depth / 2.0 ) );
	face->color.Set( 1.0, 1.0, 1.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->color.Set( 1.0, 1.0, 0.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, depth / 2.0 ) );
	face->color.Set( 1.0, 0.0, 0.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->color.Set( 1.0, 0.5, 0.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, height / 2.0, -depth / 2.0 ) );
	face->color.Set( 0.0, 0.0, 1.0 );
	faceList.push_back( face );

	face = new Face( new _3DMath::Polygon() );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( -width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, -depth / 2.0 ) );
	face->polygon->vertexArray->push_back( _3DMath::Vector( width / 2.0, -height / 2.0, depth / 2.0 ) );
	face->color.Set( 0.0, 1.0, 0.0 );
	faceList.push_back( face );
}

/*virtual*/ void TwistyPuzzle::IncrementallySolve( RotationList& rotationList ) const
{
}

/*virtual*/ void TwistyPuzzle::Render( _3DMath::Renderer& renderer, const _3DMath::AffineTransform& transform, GLenum renderMode, int selectedObjectHandle )
{
	_3DMath::LinearTransform normalTransform;
	transform.linearTransform.GetNormalTransform( normalTransform );

	for( FaceList::iterator iter = faceList.begin(); iter != faceList.end(); iter++ )
	{
		Face* face = *iter;
		face->UpdateTessellationIfNeeded();
		face->Render( renderer, renderMode, transform, normalTransform );
	}

	if( renderMode == GL_RENDER )
	{
		for( CutShapeList::iterator iter = cutShapeList.begin(); iter != cutShapeList.end(); iter++ )
		{
			CutShape* cutShape = *iter;
			if( cutShape->GetHandle() == selectedObjectHandle )
			{
				_3DMath::Vector color( 0.5, 0.5, 0.5 );
				glDepthMask( GL_FALSE );
				renderer.DrawSurface( *cutShape->surface, color, 0.2, &transform );
				glDepthMask( GL_TRUE );
			}
		}
	}

	for( CutShapeList::iterator iter = cutShapeList.begin(); iter != cutShapeList.end(); iter++ )
	{
		CutShape* cutShape = *iter;

		_3DMath::Vector vector, position, color;

		transform.Transform( cutShape->axisOfRotation.center, position );
		normalTransform.Transform( cutShape->axisOfRotation.normal, vector );

		vector.Scale( 10.0 );

		if( cutShape->GetHandle() == selectedObjectHandle )
			color.Set( 0.8, 0.8, 0.8 );
		else
			color.Set( 0.5, 0.5, 0.5 );

		if( renderMode == GL_SELECT )
			glLoadName( cutShape->GetHandle() );

		renderer.DrawVector( vector, position, color, 0.5, 0.5 );
	}
}

//---------------------------------------------------------------------------------
//                               TwistyPuzzle::Face
//---------------------------------------------------------------------------------

TwistyPuzzle::Face::Face( _3DMath::Polygon* polygon )
{
	this->polygon = polygon;
	tessellationNeeded = true;
	rotationAngleForAnimation = 0.0;
}

TwistyPuzzle::Face::~Face( void )
{
	delete polygon;
}

void TwistyPuzzle::Face::UpdateTessellationIfNeeded( void )
{
	if( tessellationNeeded )
	{
		polygon->Tessellate();
		tessellationNeeded = false;
	}
}

void TwistyPuzzle::Face::Render( _3DMath::Renderer& renderer, GLenum renderMode, const _3DMath::AffineTransform& transform, const _3DMath::LinearTransform& normalTransform ) const
{
	// TODO: We might select faces, but until then bail if we're not in render mode.
	if( renderMode != GL_RENDER )
		return;

	glLineWidth( 2.5f );

	_3DMath::AffineTransform renderTransform;

	_3DMath::AffineTransform animationTransform;
	animationTransform.SetRotation( axisOfRotation, rotationAngleForAnimation );
	renderTransform.Concatinate( animationTransform, transform );

	renderer.Color( color );
	renderer.DrawPolygon( *polygon, &renderTransform );

	if( renderer.drawStyle == _3DMath::Renderer::DRAW_STYLE_SOLID )
	{
		renderer.drawStyle = _3DMath::Renderer::DRAW_STYLE_WIRE_FRAME;

		_3DMath::AffineTransform scaleTransform;
		scaleTransform.linearTransform.SetScale( 1.01 );

		_3DMath::AffineTransform silhouetteTransform;
		silhouetteTransform.Concatinate( scaleTransform, renderTransform );

		renderer.Color( _3DMath::Vector( 0.0, 0.0, 0.0 ), 1.0 );
		renderer.DrawPolygon( *polygon, &silhouetteTransform );

		renderer.drawStyle = _3DMath::Renderer::DRAW_STYLE_SOLID;
	}
}

//---------------------------------------------------------------------------------
//                               TwistyPuzzle::CutShape
//---------------------------------------------------------------------------------

TwistyPuzzle::CutShape::CutShape( void )
{
	axisOfRotation.center.Set( 0.0, 0.0, 0.0 );
	axisOfRotation.normal.Set( 0.0, 0.0, 1.0 );
	captureSide = _3DMath::Surface::OUTSIDE;
	rotationAngleForSingleTurn = 0.0;
	surface = nullptr;
}

TwistyPuzzle::CutShape::~CutShape( void )
{
	delete surface;
}

void TwistyPuzzle::CutShape::CutAndCapture( FaceList& faceList, FaceList& capturedFaceList )
{
	capturedFaceList.clear();

	FaceList::iterator iter = faceList.begin();
	while( iter != faceList.end() )
	{
		FaceList::iterator nextIter = iter;
		nextIter++;

		Face* face = *iter;

		_3DMath::PolygonList polygonList;
		if( face->polygon->SplitAgainstSurface( surface, polygonList, 1.0 ) )
		{
			while( polygonList.size() > 0 )
			{
				_3DMath::PolygonList::iterator polyIter = polygonList.begin();
				_3DMath::Polygon* polygon = *polyIter;
				polygonList.erase( polyIter );
				Face* newFace = new Face( polygon );
				newFace->color = face->color;
				faceList.push_front( newFace );
			}

			delete face;
			faceList.erase( iter );
		}

		iter = nextIter;
	}

	iter = faceList.begin();
	while( iter != faceList.end() )
	{
		Face* face = *iter;
		face->UpdateTessellationIfNeeded();

		int insideCount = 0;
		int outsideCount = 0;

		_3DMath::IndexTriangleList::const_iterator triangleIter = face->polygon->indexTriangleList->cbegin();
		while( triangleIter != face->polygon->indexTriangleList->cend() )
		{
			const _3DMath::IndexTriangle& indexTriangle = *triangleIter;

			_3DMath::Triangle triangle;
			indexTriangle.GetTriangle( triangle, face->polygon->vertexArray );

			_3DMath::Vector triangleCenter;
			triangle.GetCenter( triangleCenter );

			_3DMath::Surface::Side side = surface->GetSide( triangleCenter );
			if( side == _3DMath::Surface::INSIDE )
				insideCount++;
			else if( side == _3DMath::Surface::OUTSIDE )
				outsideCount++;

			triangleIter++;
		}

		_3DMath::Surface::Side dominantSide = _3DMath::Surface::OUTSIDE;
		if( insideCount > outsideCount )
			dominantSide = _3DMath::Surface::INSIDE;

		if( dominantSide == captureSide )
			capturedFaceList.push_back( face );

		iter++;
	}
}

//---------------------------------------------------------------------------------
//                              TwistyPuzzle::Rotation
//---------------------------------------------------------------------------------

TwistyPuzzle::Rotation::Rotation( int cutShapeHandle, Direction direction, double turnCount )
{
	this->cutShapeHandle = cutShapeHandle;
	this->direction = direction;
	this->turnCount = turnCount;
}

TwistyPuzzle::Rotation::~Rotation( void )
{
}

// TwistyPuzzle.cpp<|endoftext|>


<commit_before>/*

*/

#include "lineFollowing.h"
#include "../control.h"

using namespace std;
using namespace cv;

void compress_lines(vector<Vec2f> &condensed, const vector<Vec2f> &tmp_list);

void draw_lines(Mat &image, const vector<Vec2f> &lines);

vector<Vec2f> condense_lines(vector<Vec2f> lines);

double deg2rad(double deg);

vector<Point> to_points(float theta, float rho);

bool parametricIntersect(float r1, float t1, float r2, float t2, int &x, int &y);

void LineFollowing::detect_lines(Mat &original_frame) {

  Mat hsv;
  Mat mask;
  width = original_frame.cols;
  height = original_frame.rows;

  cvtColor(original_frame, hsv, CV_BGR2HSV); // Image is now HSV

  Scalar lower(minH, minS, minV);
  Scalar upper(maxH, maxS, maxV);
  inRange(hsv, lower, upper, mask); // Create a mask of only the desired color
  Canny(mask, mask, 50, 200, 3);

  vector<Vec2f> lines;
  HoughLines(mask, lines, 1, CV_PI / 180, 100, 0, 0);

  // printf("Adding in %d lines\n", (int) lines.size());

  vector<Vec2f> tmp = condense_lines(lines);
  sort(tmp.begin(), tmp.end(),
       [](const Vec2f &a, const Vec2f &b) {
         return a[0] < b[0];
       });
  if (tmp.size() > 0) {
    found_lines = tmp;
  }

  draw_lines(original_frame, found_lines);

}

vector<Vec2f> condense_lines(vector<Vec2f> lines) {
  vector<Vec2f> condensed;
  vector<Vec2f> tmp_list;
  double diff;
  for (int i = 0; i < (int) lines.size(); i++) {
//    if (lines[i][1] > CV_PI / 2) {
//      lines[i][1] -= CV_PI;
//      lines[i][0] *= -1;
//    }
//    else if (lines[i][1] < ((CV_PI / 2) * -1)) {
//      lines[i][1] += CV_PI;
//      lines[i][0] *= -1;
//    }

    lines[i][1] -= deg2rad(360);

    while (lines[i][1] < 0) {
      lines[i][1] += deg2rad(360);
    }
	/*
    if (lines[i][1] >= deg2rad(90)) {
      lines[i][1] -= deg2rad(180);
      lines[i][0] *= -1;
    }
	*/

    //put in order of theta, rho
    swap(lines[i][0], lines[i][1]);
  }

  //Order from least to greatest theta
  sort(lines.begin(), lines.end(),
       [](const Vec2f &a, const Vec2f &b) {
         return a[0] < b[0];
       });

  while (!lines.empty()) {
    Vec2f to_manipulate = lines.front();
    lines.erase(lines.begin());

    if (tmp_list.empty()) {
      tmp_list.push_back(to_manipulate);
      continue;
    } else {
	  diff = abs(to_manipulate[0] - tmp_list.front()[0]);
	  if(diff > deg2rad(180)){
		diff = deg2rad(360)-diff;
	  }
      if (diff < deg2rad(20)) {
        //The angles are similar
        if (abs(to_manipulate[1] - tmp_list.front()[1]) < 50) {
          //the distances are similar
          tmp_list.push_back(to_manipulate);
          continue;
        }
      } else {
        //Need to clear out the tmp_list
        compress_lines(condensed, tmp_list);

        tmp_list.clear();
        tmp_list.push_back(to_manipulate);

      }
    }
  }
  if (!tmp_list.empty()) {
    compress_lines(condensed, tmp_list);
  }
  return condensed;
}

double deg2rad(double deg) {
  return deg * (CV_PI / 180.0);
}

double rad2deg(double rad) {
  return rad * (180.0 / CV_PI);
}

void draw_lines(Mat &image, const vector<Vec2f> &lines) {
  for (size_t i = 0; i < lines.size(); i++) {
    float theta = lines[i][0], rho = lines[i][1];
    // float rho = lines[i][0], theta = lines[i][1];Point pt1;
    vector<Point> p = to_points(theta, rho);
    line(image, p[0], p[1], Scalar(255*(i==0), 255*(i==1), 255*(i==2)), 3, CV_AA);
  }
}

vector<Point> to_points(float theta, float rho) {
  vector<Point> rv = {Point(), Point()};
  double a = cos(theta), b = sin(theta);
  double x0 = a * rho, y0 = b * rho;
  rv[0].x = cvRound(x0 + 1000 * (-b));
  rv[0].y = cvRound(y0 + 1000 * (a));
  rv[1].x = cvRound(x0 - 1000 * (-b));
  rv[1].y = cvRound(y0 - 1000 * (a));
  return rv;
}

void compress_lines(vector<Vec2f> &condensed, const vector<Vec2f> &tmp_list) {
  Vec2f new_point;
  float angle_sum = 0;
  float rho_sum = 0;
  for (int j = 0; j < (int) tmp_list.size(); ++j) {
    angle_sum += tmp_list[j][0];
    rho_sum += tmp_list[j][1];
  }
  angle_sum /= tmp_list.size();
  rho_sum /= tmp_list.size();

  new_point[0] = angle_sum;
  new_point[1] = rho_sum;

  condensed.push_back(new_point);
}

LineFollowing::LineFollowing(Control *control) {
  namedWindow("line_window", CV_WINDOW_NORMAL);
  control_ptr = control;
  minH = 50;
  minS = 20;
  minV = 150;
  maxH = 125;
  maxS = 100;
  maxV = 255;
  return;
}

void LineFollowing::close() {
  return;
}

void LineFollowing::fly() {
  // cout << "line following\n";
  detect_lines(control_ptr->image);

  control_ptr->velocities.vx = 0;
  control_ptr->velocities.vy = 0;
  control_ptr->velocities.vz = 0;
  control_ptr->velocities.vr = 0;

  if (found_lines.size() < 1) {
    //I found no lines
    // printf("Found nothing\n");
    return;
  }
  double calculated_distance = distance_from_center(found_lines[0][1], found_lines[0][0], control_ptr->image.cols,
                                                    control_ptr->image.rows);

  // printf("calc dist of %f ", calculated_distance);
  int origin_x = 0 + (control_ptr->image.cols / 2);
  int origin_y = 0 + (control_ptr->image.rows / 2);
  Point pt1 = cvPoint(origin_x, origin_y);
  Point pt2 = cvPoint(origin_x + cvRound(calculated_distance), origin_y);
  line(control_ptr->image, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA);

  if (found_lines.size() > 1) {
    // I need to turn
    //TODO: move until line is centered
    //TODO: look for symbol, and turn
    origin_x = 0;
    origin_y = 0;
    Vec2i point = find_intersection(found_lines[0], found_lines[1]);
    //printf("My coords are x: %3d y %3d\n", point[0], point[1]);
    line(control_ptr->image, cvPoint(origin_x + point[0] + 10, origin_y + point[1]),
         cvPoint(origin_x + point[0] - 10, origin_y + point[1]), Scalar(0, 255, 0), 3, CV_AA);
    line(control_ptr->image, cvPoint(origin_x + point[0], origin_y + point[1] + 10),
         cvPoint(origin_x + point[0], origin_y + point[1] - 10), Scalar(0, 255, 0), 3, CV_AA);
	if(found_lines.size() >= 4){
		for(int j = 0; j < (int) found_lines.size(); j++){
		  printf("theta: %.1f rho: %.0f  ", found_lines[j][0]*(180/CV_PI), found_lines[j][1]);
		}
		printf("\n");
	}
    return;
  }

  else {
    // I need to snap myself to the line
    if (found_lines[0][0] >= deg2rad(5)) {
      control_ptr->velocities.vr = -.2;
      printf("Turning Right\n");
    }
    else if (found_lines[0][0] <= deg2rad(-1 * 5)) {
      control_ptr->velocities.vr = .2;
      printf("Turning Left\n");
    } else {
      printf("Checking Distance\n");

      double offset = calculated_distance;
      // printf("Offset is: %5.2f with a distance of %5.2f and width of %5.2f halved to %5.2f\n", offset,
      // found_lines[0][1],
      // (double) control_ptr->image.cols, (control_ptr->image.cols / 2.0));
      if (-100 <= offset && offset <= 100) {
        printf("No need to move\n");
      } else if (offset < 0) {
        //we are to the right of the line
        //we need to move left
        control_ptr->velocities.vy = 1;
        printf("Move left\n");
      } else {
        //we need to move right
        control_ptr->velocities.vy = -1;
        printf("Move right\n");
      }
    }
  }

  return;
}

double LineFollowing::distance_from_center(float rho, float theta, double width, double height) {
  // printf("width: %f height: %f\n", width, height);
  theta = -1 * (theta);
  double rh = rho * cos(theta);
  double rv = rho * sin(theta);
  // rh = abs(rh);
  // rv *= -1;
  double excess = (width / 2.0) - rh;
  // excess *=-1;
  double lv = rv + (height / 2.0);
  double lh = lv * tan(theta);
  // lh = abs(lh);
  double x = lh - excess;

  // printf("ro: %4f th: %4f rh: %4f rv: %4f ex: %4f lv: %4f lh: %4f x: %4f\n", rho, theta ,rh, rv, excess, lv,lh,x);

  return x;
}

cv::Point LineFollowing::find_intersection(Vec2f a, Vec2f b) {
  Point rv;
  bool do_intersect = parametricIntersect(a[1], a[0], b[1], b[0], rv.x, rv.y);
  if (!do_intersect) {
    printf("No intersection!\n");
  }

  return rv;
}

bool parametricIntersect(float r1, float t1, float r2, float t2, int &x, int &y) {
  float ct1 = cosf(t1);     //matrix element a
  float st1 = sinf(t1);     //b
  float ct2 = cosf(t2);     //c
  float st2 = sinf(t2);     //d
  float d = ct1 * st2 - st1 * ct2;        //determinative (rearranged matrix for inverse)
  if (d != 0.0f) {
    x = (int) ((st2 * r1 - st1 * r2) / d);
    y = (int) ((-ct2 * r1 + ct1 * r2) / d);
    return (true);
  } else { //lines are parallel and will NEVER intersect!
    return (false);
  }
}
<commit_msg>maybe doing the right condensing<commit_after>/*

*/

#include "lineFollowing.h"
#include "../control.h"

using namespace std;
using namespace cv;

void compress_lines(vector<Vec2f> &condensed, const vector<Vec2f> &tmp_list);

void draw_lines(Mat &image, const vector<Vec2f> &lines);

vector<Vec2f> condense_lines(vector<Vec2f> lines, bool keep_going);

double deg2rad(double deg);

vector<Point> to_points(float theta, float rho);

bool parametricIntersect(float r1, float t1, float r2, float t2, int &x, int &y);

void LineFollowing::detect_lines(Mat &original_frame) {

  Mat hsv;
  Mat mask;
  width = original_frame.cols;
  height = original_frame.rows;

  cvtColor(original_frame, hsv, CV_BGR2HSV); // Image is now HSV

  Scalar lower(minH, minS, minV);
  Scalar upper(maxH, maxS, maxV);
  inRange(hsv, lower, upper, mask); // Create a mask of only the desired color
  Canny(mask, mask, 50, 200, 3);

  vector<Vec2f> lines;
  HoughLines(mask, lines, 1, CV_PI / 180, 100, 0, 0);

  // printf("Adding in %d lines\n", (int) lines.size());

  vector<Vec2f> tmp = condense_lines(lines, true);
  sort(tmp.begin(), tmp.end(),
       [](const Vec2f &a, const Vec2f &b) {
         return a[0] < b[0];
       });
  if (tmp.size() > 0) {
    found_lines = tmp;
  }

  draw_lines(original_frame, found_lines);

}

vector<Vec2f> condense_lines(vector<Vec2f> lines, bool keep_going) {
  vector<Vec2f> condensed;
  vector<Vec2f> tmp_list;
  double diff;
  for (int i = 0; i < (int) lines.size(); i++) {
    /*    if (lines[i][1] > CV_PI / 2) {
        lines[i][1] -= CV_PI;
        lines[i][0] *= -1;
      }
      else if (lines[i][1] < ((CV_PI / 2) * -1)) {
        lines[i][1] += CV_PI;
        lines[i][0] *= -1;
      }*/

    lines[i][1] -= deg2rad(360);

    while (lines[i][1] < 0) {
      lines[i][1] += deg2rad(360);
    }
    /*
      if (lines[i][1] >= deg2rad(90)) {
        lines[i][1] -= deg2rad(180);
        lines[i][0] *= -1;
      }
    */

    //put in order of theta, rho
    swap(lines[i][0], lines[i][1]);
  }

  //Order from least to greatest theta
  sort(lines.begin(), lines.end(),
       [](const Vec2f &a, const Vec2f &b) {
         return a[0] < b[0];
       });

  while (!lines.empty()) {
    Vec2f to_manipulate = lines.front();
    lines.erase(lines.begin());

    if (tmp_list.empty()) {
      tmp_list.push_back(to_manipulate);
      continue;
    } else {
      diff = abs(to_manipulate[0] - tmp_list.front()[0]);
      if (diff > deg2rad(180)) {
        diff = deg2rad(360) - diff;
      }
      if (diff < deg2rad(20)) {
        //The angles are similar
        if (abs(to_manipulate[1] - tmp_list.front()[1]) < 50) {
          //the distances are similar
          tmp_list.push_back(to_manipulate);
          continue;
        }
      } else {
        //Need to clear out the tmp_list
        compress_lines(condensed, tmp_list);

        tmp_list.clear();
        tmp_list.push_back(to_manipulate);

      }
    }
  }
  if (!tmp_list.empty()) {
    compress_lines(condensed, tmp_list);
  }

  condensed.back()[0] -= 360;
  if (keep_going) {
    condensed = condense_lines(condensed, false);
  }
  return condensed;
}

double deg2rad(double deg) {
  return deg * (CV_PI / 180.0);
}

double rad2deg(double rad) {
  return rad * (180.0 / CV_PI);
}

void draw_lines(Mat &image, const vector<Vec2f> &lines) {
  for (size_t i = 0; i < lines.size(); i++) {
    float theta = lines[i][0], rho = lines[i][1];
    // float rho = lines[i][0], theta = lines[i][1];Point pt1;
    vector<Point> p = to_points(theta, rho);
    line(image, p[0], p[1], Scalar(255 * (i == 0), 255 * (i == 1), 255 * (i == 2)), 3, CV_AA);
  }
}

vector<Point> to_points(float theta, float rho) {
  vector<Point> rv = {Point(), Point()};
  double a = cos(theta), b = sin(theta);
  double x0 = a * rho, y0 = b * rho;
  rv[0].x = cvRound(x0 + 1000 * (-b));
  rv[0].y = cvRound(y0 + 1000 * (a));
  rv[1].x = cvRound(x0 - 1000 * (-b));
  rv[1].y = cvRound(y0 - 1000 * (a));
  return rv;
}

void compress_lines(vector<Vec2f> &condensed, const vector<Vec2f> &tmp_list) {
  Vec2f new_point;
  float angle_sum = 0;
  float rho_sum = 0;
  for (int j = 0; j < (int) tmp_list.size(); ++j) {
    angle_sum += tmp_list[j][0];
    rho_sum += tmp_list[j][1];
  }
  angle_sum /= tmp_list.size();
  rho_sum /= tmp_list.size();

  new_point[0] = angle_sum;
  new_point[1] = rho_sum;

  condensed.push_back(new_point);
}

LineFollowing::LineFollowing(Control *control) {
  namedWindow("line_window", CV_WINDOW_NORMAL);
  control_ptr = control;
  minH = 50;
  minS = 20;
  minV = 150;
  maxH = 125;
  maxS = 100;
  maxV = 255;
  return;
}

void LineFollowing::close() {
  return;
}

void LineFollowing::fly() {
  // cout << "line following\n";
  detect_lines(control_ptr->image);

  control_ptr->velocities.vx = 0;
  control_ptr->velocities.vy = 0;
  control_ptr->velocities.vz = 0;
  control_ptr->velocities.vr = 0;

  if (found_lines.size() < 1) {
    //I found no lines
    // printf("Found nothing\n");
    return;
  }
  double calculated_distance = distance_from_center(found_lines[0][1], found_lines[0][0], control_ptr->image.cols,
                                                    control_ptr->image.rows);

  // printf("calc dist of %f ", calculated_distance);
  int origin_x = 0 + (control_ptr->image.cols / 2);
  int origin_y = 0 + (control_ptr->image.rows / 2);
  Point pt1 = cvPoint(origin_x, origin_y);
  Point pt2 = cvPoint(origin_x + cvRound(calculated_distance), origin_y);
  line(control_ptr->image, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA);

  if (found_lines.size() > 1) {
    // I need to turn
    //TODO: move until line is centered
    //TODO: look for symbol, and turn
    origin_x = 0;
    origin_y = 0;
    Vec2i point = find_intersection(found_lines[0], found_lines[1]);
    //printf("My coords are x: %3d y %3d\n", point[0], point[1]);
    line(control_ptr->image, cvPoint(origin_x + point[0] + 10, origin_y + point[1]),
         cvPoint(origin_x + point[0] - 10, origin_y + point[1]), Scalar(0, 255, 0), 3, CV_AA);
    line(control_ptr->image, cvPoint(origin_x + point[0], origin_y + point[1] + 10),
         cvPoint(origin_x + point[0], origin_y + point[1] - 10), Scalar(0, 255, 0), 3, CV_AA);
    if (found_lines.size() >= 4) {
      for (int j = 0; j < (int) found_lines.size(); j++) {
        printf("theta: %.1f rho: %.0f  ", found_lines[j][0] * (180 / CV_PI), found_lines[j][1]);
      }
      printf("\n");
    }
    return;
  }

  else {
    // I need to snap myself to the line
    if (found_lines[0][0] >= deg2rad(5)) {
      control_ptr->velocities.vr = -.2;
      printf("Turning Right\n");
    }
    else if (found_lines[0][0] <= deg2rad(-1 * 5)) {
      control_ptr->velocities.vr = .2;
      printf("Turning Left\n");
    } else {
      printf("Checking Distance\n");

      double offset = calculated_distance;
      // printf("Offset is: %5.2f with a distance of %5.2f and width of %5.2f halved to %5.2f\n", offset,
      // found_lines[0][1],
      // (double) control_ptr->image.cols, (control_ptr->image.cols / 2.0));
      if (-100 <= offset && offset <= 100) {
        printf("No need to move\n");
      } else if (offset < 0) {
        //we are to the right of the line
        //we need to move left
        control_ptr->velocities.vy = 1;
        printf("Move left\n");
      } else {
        //we need to move right
        control_ptr->velocities.vy = -1;
        printf("Move right\n");
      }
    }
  }

  return;
}

double LineFollowing::distance_from_center(float rho, float theta, double width, double height) {
  // printf("width: %f height: %f\n", width, height);
  theta = -1 * (theta);
  double rh = rho * cos(theta);
  double rv = rho * sin(theta);
  // rh = abs(rh);
  // rv *= -1;
  double excess = (width / 2.0) - rh;
  // excess *=-1;
  double lv = rv + (height / 2.0);
  double lh = lv * tan(theta);
  // lh = abs(lh);
  double x = lh - excess;

  // printf("ro: %4f th: %4f rh: %4f rv: %4f ex: %4f lv: %4f lh: %4f x: %4f\n", rho, theta ,rh, rv, excess, lv,lh,x);

  return x;
}

cv::Point LineFollowing::find_intersection(Vec2f a, Vec2f b) {
  Point rv;
  bool do_intersect = parametricIntersect(a[1], a[0], b[1], b[0], rv.x, rv.y);
  if (!do_intersect) {
    printf("No intersection!\n");
  }

  return rv;
}

bool parametricIntersect(float r1, float t1, float r2, float t2, int &x, int &y) {
  float ct1 = cosf(t1);     //matrix element a
  float st1 = sinf(t1);     //b
  float ct2 = cosf(t2);     //c
  float st2 = sinf(t2);     //d
  float d = ct1 * st2 - st1 * ct2;        //determinative (rearranged matrix for inverse)
  if (d != 0.0f) {
    x = (int) ((st2 * r1 - st1 * r2) / d);
    y = (int) ((-ct2 * r1 + ct1 * r2) / d);
    return (true);
  } else { //lines are parallel and will NEVER intersect!
    return (false);
  }
}
<|endoftext|>


<commit_before>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
//  printf("Hello, this is Caleb\n");

  VideoCapture cap("../../tests/videos/top_down_4.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

  namedWindow("edges", CV_WINDOW_NORMAL);
//  Mat edges;
  for (; ;) {
    Mat mask, hsv_mask;
    Mat frame, hsv;
    cap >> frame; // get a new frame from camera
    cvtColor(frame, hsv, CV_BGR2HSV);

    //    low = Scalar(30, 0, 240);
//    high = Scalar(80, 70, 255);

    inRange(hsv, Scalar(30, 0, 0), Scalar(255, 255, 255), mask);

    bitwise_and(frame, frame, frame, mask);

//    cvtColor(mask, hsv_mask, CV_HS);
    hsv_mask = mask;
    vector <Vec4i> lines;
//    HoughLinesP(mask, lines, 1, CV_PI / 180, 100, 100, 10);

    printf("Adding in %d lines\n", (int) lines.size());
    for (size_t i = 0; i < lines.size(); i++) {
      Vec4i l = lines[i];
      line(hsv_mask, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
    }

    imshow("edges", frame);
    if (waitKey(30) >= 0) break;
  }
  // the camera will be deinitialized automatically in VideoCapture destructor
  return;
}
<commit_msg>debug mask<commit_after>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
//  printf("Hello, this is Caleb\n");

  VideoCapture cap("../../tests/videos/top_down_4.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

  namedWindow("edges", CV_WINDOW_NORMAL);
//  Mat edges;
  for (; ;) {
    Mat mask, hsv_mask;
    Mat frame, hsv;
    cap >> frame; // get a new frame from camera
    cvtColor(frame, hsv, CV_BGR2HSV);

    //    low = Scalar(30, 0, 240);
//    high = Scalar(80, 70, 255);

    inRange(hsv, Scalar(50, 0, 0), Scalar(255, 255, 255), mask);

    bitwise_and(frame, frame, frame, mask);

//    cvtColor(mask, hsv_mask, CV_HS);
    hsv_mask = mask;
    vector <Vec4i> lines;
//    HoughLinesP(mask, lines, 1, CV_PI / 180, 100, 100, 10);

    printf("Adding in %d lines\n", (int) lines.size());
    for (size_t i = 0; i < lines.size(); i++) {
      Vec4i l = lines[i];
      line(hsv_mask, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
    }

    imshow("edges", frame);
    if (waitKey(30) >= 0) break;
  }
  // the camera will be deinitialized automatically in VideoCapture destructor
  return;
}
<|endoftext|>


<commit_before>/*
 * File:   BackpropeagationLearner.cpp
 * Author: janvojt
 *
 * Created on July 13, 2014, 12:10 AM
 */

#include "BackpropagationLearner.h"
#include "Network.h"
#include "LabeledDataset.h"
#include <cstring>
#include <string>
#include <stdexcept>

#include "log/LoggerFactory.h"
#include "log4cpp/Category.hh"

BackpropagationLearner::BackpropagationLearner(Network *network) {
    this->network = network;
    learningRate = 1;
    epochCounter = 0;
    epochLimit = 1000000;
    targetMse = .0001;
    errorTotal = std::numeric_limits<double>::infinity();
    allocateCache();
}

BackpropagationLearner::BackpropagationLearner(const BackpropagationLearner &orig) {
}

BackpropagationLearner::~BackpropagationLearner() {

}

void BackpropagationLearner::allocateCache() {
    weightDiffs = new double[network->getWeightsOffset(network->getConfiguration()->getLayers())];
    localGradients = new double[network->getAllNeurons()];

    useBias = network->getConfiguration()->getBias();
    biasDiff = useBias ? new double[network->getAllNeurons()] : NULL;
}

void BackpropagationLearner::train(LabeledDataset *dataset) {
    double mse;
    LOG()->info("Started training with limits of %d epochs and target MSE of %f.", epochLimit, targetMse);
    do {
        epochCounter++;
        LOG()->debug("Starting epoch %d.", epochCounter);
        dataset->reset();
        int datasetSize = 0;
        mse = 0;
        while (dataset->hasNext()) {
            datasetSize++;
            double *pattern = dataset->next();
            double *expOutput = pattern + dataset->getInputDimension();
            LOG()->debug("Learning pattern [%f, %f] -> [%f].", pattern[0], pattern[1], expOutput[0]);
            doForwardPhase(pattern);
            doBackwardPhase(expOutput);
            mse += errorComputer->compute(network, expOutput);
        }
        mse = mse / datasetSize;
        LOG()->debug("Finished epoch %d with MSE: %f.", epochCounter, mse);
    } while (mse > targetMse && epochCounter < epochLimit);

    if (mse <= targetMse) {
        LOG()->info("Training successful after %d epochs with MSE of %f.", epochCounter, mse);
    } else {
        LOG()->info("Training interrupted after %d epochs with MSE of %f.", epochCounter, mse);
    }
}

void BackpropagationLearner::doForwardPhase(double *input) {
    network->setInput(input);
    network->run();
}

void BackpropagationLearner::doBackwardPhase(double *expectedOutput) {
    computeOutputGradients(expectedOutput);
    computeWeightDifferentials();
    adjustWeights();
    if (network->getConfiguration()->getBias()) {
        adjustBias();
    }
}

void BackpropagationLearner::computeOutputGradients(double *expectedOutput) {
    int on = network->getOutputNeurons();
    int noLayers = network->getConfiguration()->getLayers();
    double *localGradient = localGradients + network->getInputOffset(noLayers-1);
    double *output = network->getOutput();
    void (*daf) (double*,double*,int) = network->getConfiguration()->dActivationFnc;

    // compute local gradients
    double *dv = new double[network->getOutputNeurons()];
    daf(network->getInput() + network->getInputOffset(noLayers-1), dv, on);
    for (int i = 0; i<on; i++) {
        localGradient[i] = (output[i] - expectedOutput[i]) * dv[i];
        LOG()->debug("Local gradient for neuron [%d, %d] : %f.", noLayers, i, localGradient[i]);
    }
}

void BackpropagationLearner::computeWeightDifferentials() {
    int noLayers = network->getConfiguration()->getLayers();
    void (*daf) (double*,double*,int) = network->getConfiguration()->dActivationFnc;

    for (int l = noLayers-1; l>0; l--) {

        // INITIALIZE HELPER VARIABLES
        int thisInputIdx = network->getInputOffset(l-1);
        double *thisLocalGradient = localGradients + thisInputIdx;
        int nextInputIdx = network->getInputOffset(l);
        double *nextLocalGradient = localGradients + nextInputIdx;
        int thisNeurons = network->getConfiguration()->getNeurons(l-1);
        int nextNeurons = network->getConfiguration()->getNeurons(l);
        double *thisInput = network->getInput() + thisInputIdx;
        double *weights = network->getWeights() + network->getWeightsOffset(l);

        // COMPUTE TOTAL DERIVATIVES for weights between layer l and l+1
        int wc = network->getWeightsOffset(l+1) - network->getWeightsOffset(l);
        double *wdiff = weightDiffs + network->getWeightsOffset(l);
        for (int i = 0; i<wc; i++) {
            wdiff[i] = -learningRate * nextLocalGradient[i%nextNeurons] * thisInput[i/nextNeurons];
        }

        // COMPUTE BIAS DERIVATIVES for layer l+1
        if (useBias) {
            for (int i = 0; i<nextNeurons; i++) {
                biasDiff[nextInputIdx + i] = -learningRate * nextLocalGradient[i];
            }
        }

        // COMPUTE LOCAL GRADIENTS for layer l

        // compute derivatives of neuron inputs in layer l
        double *thisInputDerivatives = new double[thisNeurons];
        daf(thisInput, thisInputDerivatives, thisNeurons);

        // compute local gradients for layer l
        for (int i = 0; i<thisNeurons; i++) {
            double sumNextGradient = 0;
            for (int j = 0; j<nextNeurons; j++) {
                sumNextGradient += nextLocalGradient[j] * weights[i * nextNeurons + j];
            }
            thisLocalGradient[i] = sumNextGradient * thisInputDerivatives[i];
            LOG()->debug("Local gradient for neuron [%d, %d] : %f.", l, i, thisLocalGradient[i]);
        }
    }
}

void BackpropagationLearner::adjustWeights() {
    int wc = network->getWeightsOffset(network->getConfiguration()->getLayers());
    double *weights = network->getWeights();
    LOG()->debug("Adjusting weights by: [[%f, %f], [%f, %f]], [[%f, %f]].",
            weightDiffs[2], weightDiffs[3],
            weightDiffs[4], weightDiffs[5],
            weightDiffs[6], weightDiffs[7]);

    // we should skip the garbage in zero-layer weights
    for(int i = network->getWeightsOffset(1); i<wc; i++) {
        weights[i] += weightDiffs[i];
    }
}

void BackpropagationLearner::adjustBias() {
    double *bias = network->getBiasValues();
    int noNeurons = network->getAllNeurons();
    LOG()->debug("Adjusting bias by: [%f, %f], [%f, %f], [%f].",
            biasDiff[0], biasDiff[1],
            biasDiff[2], biasDiff[3],
            biasDiff[4]);
    for (int i = 0; i<noNeurons; i++) {
        bias[i] += biasDiff[i];
    }
}

void BackpropagationLearner::clearLayer(double *inputPtr, int layerSize) {
    std::fill_n(inputPtr, layerSize, 0);
}

void BackpropagationLearner::validate(LabeledDataset *dataset) {
    if (dataset->getInputDimension() != network->getInputNeurons()) {
        throw new std::invalid_argument("Provided dataset must have the same input dimension as the number of input neurons!");
    }
    if (dataset->getOutputDimension() != network->getOutputNeurons()) {
        throw new std::invalid_argument("Provided dataset must have the same output dimension as the number of output neurons!");
    }
}

void BackpropagationLearner::setEpochLimit(int limit) {
    epochLimit = limit;
}

void BackpropagationLearner::setErrorComputer(ErrorComputer* errorComputer) {
    this->errorComputer = errorComputer;
}

void BackpropagationLearner::setTargetMse(double mse) {
    targetMse = mse;
}
<commit_msg>Rewritten weight differential computation to be clearer.<commit_after>/*
 * File:   BackpropeagationLearner.cpp
 * Author: janvojt
 *
 * Created on July 13, 2014, 12:10 AM
 */

#include "BackpropagationLearner.h"
#include "Network.h"
#include "LabeledDataset.h"
#include <cstring>
#include <string>
#include <stdexcept>

#include "log/LoggerFactory.h"
#include "log4cpp/Category.hh"

BackpropagationLearner::BackpropagationLearner(Network *network) {
    this->network = network;
    learningRate = 1;
    epochCounter = 0;
    epochLimit = 1000000;
    targetMse = .0001;
    errorTotal = std::numeric_limits<double>::infinity();
    allocateCache();
}

BackpropagationLearner::BackpropagationLearner(const BackpropagationLearner &orig) {
}

BackpropagationLearner::~BackpropagationLearner() {

}

void BackpropagationLearner::allocateCache() {
    weightDiffs = new double[network->getWeightsOffset(network->getConfiguration()->getLayers())];
    localGradients = new double[network->getAllNeurons()];

    useBias = network->getConfiguration()->getBias();
    biasDiff = useBias ? new double[network->getAllNeurons()] : NULL;
}

void BackpropagationLearner::train(LabeledDataset *dataset) {
    double mse;
    LOG()->info("Started training with limits of %d epochs and target MSE of %f.", epochLimit, targetMse);
    do {
        epochCounter++;
        LOG()->debug("Starting epoch %d.", epochCounter);
        dataset->reset();
        int datasetSize = 0;
        mse = 0;
        while (dataset->hasNext()) {
            datasetSize++;
            double *pattern = dataset->next();
            double *expOutput = pattern + dataset->getInputDimension();
            LOG()->debug("Learning pattern [%f, %f] -> [%f].", pattern[0], pattern[1], expOutput[0]);
            doForwardPhase(pattern);
            doBackwardPhase(expOutput);
            mse += errorComputer->compute(network, expOutput);
        }
        mse = mse / datasetSize;
        LOG()->debug("Finished epoch %d with MSE: %f.", epochCounter, mse);
    } while (mse > targetMse && epochCounter < epochLimit);

    if (mse <= targetMse) {
        LOG()->info("Training successful after %d epochs with MSE of %f.", epochCounter, mse);
    } else {
        LOG()->info("Training interrupted after %d epochs with MSE of %f.", epochCounter, mse);
    }
}

void BackpropagationLearner::doForwardPhase(double *input) {
    network->setInput(input);
    network->run();
}

void BackpropagationLearner::doBackwardPhase(double *expectedOutput) {
    computeOutputGradients(expectedOutput);
    computeWeightDifferentials();
    adjustWeights();
    if (network->getConfiguration()->getBias()) {
        adjustBias();
    }
}

void BackpropagationLearner::computeOutputGradients(double *expectedOutput) {
    int on = network->getOutputNeurons();
    int noLayers = network->getConfiguration()->getLayers();
    double *localGradient = localGradients + network->getInputOffset(noLayers-1);
    double *output = network->getOutput();
    void (*daf) (double*,double*,int) = network->getConfiguration()->dActivationFnc;

    // compute local gradients
    double *dv = new double[network->getOutputNeurons()];
    daf(network->getInput() + network->getInputOffset(noLayers-1), dv, on);
    for (int i = 0; i<on; i++) {
        localGradient[i] = (output[i] - expectedOutput[i]) * dv[i];
        LOG()->debug("Local gradient for neuron [%d, %d] : %f.", noLayers, i, localGradient[i]);
    }
}

void BackpropagationLearner::computeWeightDifferentials() {
    int noLayers = network->getConfiguration()->getLayers();
    void (*daf) (double*,double*,int) = network->getConfiguration()->dActivationFnc;

    for (int l = noLayers-1; l>0; l--) {

        // INITIALIZE HELPER VARIABLES
        int thisInputIdx = network->getInputOffset(l-1);
        double *thisLocalGradient = localGradients + thisInputIdx;
        int nextInputIdx = network->getInputOffset(l);
        double *nextLocalGradient = localGradients + nextInputIdx;
        int thisNeurons = network->getConfiguration()->getNeurons(l-1);
        int nextNeurons = network->getConfiguration()->getNeurons(l);
        double *thisInput = network->getInput() + thisInputIdx;
        double *weights = network->getWeights() + network->getWeightsOffset(l);

        // COMPUTE TOTAL DERIVATIVES for weights between layer l and l+1
        double *wdiff = weightDiffs + network->getWeightsOffset(l);
        for (int i = 0; i<thisNeurons; i++) {
            for (int j = 0; j<nextNeurons; j++) {
                wdiff[i*nextNeurons+j] = -learningRate * nextLocalGradient[j] * thisInput[i];
            }
        }

        // COMPUTE BIAS DERIVATIVES for layer l+1
        if (useBias) {
            for (int i = 0; i<nextNeurons; i++) {
                biasDiff[nextInputIdx + i] = -learningRate * nextLocalGradient[i];
            }
        }

        // COMPUTE LOCAL GRADIENTS for layer l

        // compute derivatives of neuron inputs in layer l
        double *thisInputDerivatives = new double[thisNeurons];
        daf(thisInput, thisInputDerivatives, thisNeurons);

        // compute local gradients for layer l
        for (int i = 0; i<thisNeurons; i++) {
            double sumNextGradient = 0;
            for (int j = 0; j<nextNeurons; j++) {
                sumNextGradient += nextLocalGradient[j] * weights[i * nextNeurons + j];
            }
            thisLocalGradient[i] = sumNextGradient * thisInputDerivatives[i];
            LOG()->debug("Local gradient for neuron [%d, %d] : %f.", l, i, thisLocalGradient[i]);
        }
    }
}

void BackpropagationLearner::adjustWeights() {
    int wc = network->getWeightsOffset(network->getConfiguration()->getLayers());
    double *weights = network->getWeights();
    LOG()->debug("Adjusting weights by: [[%f, %f], [%f, %f]], [[%f, %f]].",
            weightDiffs[2], weightDiffs[3],
            weightDiffs[4], weightDiffs[5],
            weightDiffs[6], weightDiffs[7]);

    // we should skip the garbage in zero-layer weights
    for(int i = network->getWeightsOffset(1); i<wc; i++) {
        weights[i] += weightDiffs[i];
    }
}

void BackpropagationLearner::adjustBias() {
    double *bias = network->getBiasValues();
    int noNeurons = network->getAllNeurons();
    LOG()->debug("Adjusting bias by: [%f, %f], [%f, %f], [%f].",
            biasDiff[0], biasDiff[1],
            biasDiff[2], biasDiff[3],
            biasDiff[4]);
    for (int i = 0; i<noNeurons; i++) {
        bias[i] += biasDiff[i];
    }
}

void BackpropagationLearner::clearLayer(double *inputPtr, int layerSize) {
    std::fill_n(inputPtr, layerSize, 0);
}

void BackpropagationLearner::validate(LabeledDataset *dataset) {
    if (dataset->getInputDimension() != network->getInputNeurons()) {
        throw new std::invalid_argument("Provided dataset must have the same input dimension as the number of input neurons!");
    }
    if (dataset->getOutputDimension() != network->getOutputNeurons()) {
        throw new std::invalid_argument("Provided dataset must have the same output dimension as the number of output neurons!");
    }
}

void BackpropagationLearner::setEpochLimit(int limit) {
    epochLimit = limit;
}

void BackpropagationLearner::setErrorComputer(ErrorComputer* errorComputer) {
    this->errorComputer = errorComputer;
}

void BackpropagationLearner::setTargetMse(double mse) {
    targetMse = mse;
}
<|endoftext|>


<commit_before>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2008 basysKom GmbH
 * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2008 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "TelepathyQt4/Prototype/Connection.h"

#include <QDebug>
#include <QMetaProperty>

#include <TelepathyQt4/Client/Connection>
#include <TelepathyQt4/Client/ConnectionManager>

#include <TelepathyQt4/Prototype/Account.h>
#include <TelepathyQt4/Prototype/AvatarManager.h>
#include <TelepathyQt4/Prototype/CapabilitiesManager.h>
#include <TelepathyQt4/Prototype/ContactManager.h>
#include <TelepathyQt4/Prototype/PresenceManager.h>

// #define ENABLE_DEBUG_OUTPUT_

namespace TpPrototype {

class ConnectionPrivate
{
public:
    ConnectionPrivate()
    { init(); }

    QString                                 m_serviceName;
    QString                                 m_objectPath;
    bool                                    m_isValid;
    Telepathy::ConnectionStatus             m_status;
    Telepathy::ConnectionStatusReason       m_reason;
    Telepathy::Client::ConnectionInterface* m_pInterface;
    QPointer<ContactManager>                m_pContactManager;
    QPointer<PresenceManager>               m_pPresenceManager;
    QPointer<CapabilitiesManager>           m_pCapabilitiesManager;
    QPointer<AvatarManager>                 m_pAvatarManager;
    QPointer<Account>                       m_pAccount;
    QString                                 m_connectionManager;
    QString                                 m_protocol;
    void init()
    {
        m_isValid              = false; // Will be set on true after initial initialization.
        m_status               = Telepathy::ConnectionStatusDisconnected;
        m_reason               = Telepathy::ConnectionStatusReasonNoneSpecified;
        m_pInterface           = NULL;
        m_pContactManager      = NULL;
        m_pPresenceManager     = NULL;
        m_pCapabilitiesManager = NULL;
        m_pAvatarManager       = NULL;
        m_pAccount             = NULL;
    }

    void cleanup()
    {
        m_isValid              = true;
        m_status               = Telepathy::ConnectionStatusDisconnected;
        m_reason               = Telepathy::ConnectionStatusReasonNoneSpecified;
        delete m_pInterface;
        m_pInterface           = NULL;
        delete m_pContactManager;
        m_pContactManager      = NULL;
        delete m_pPresenceManager;
        m_pPresenceManager     = NULL;
        delete m_pCapabilitiesManager;
        m_pCapabilitiesManager = NULL;
        delete m_pAvatarManager;
        m_pAvatarManager       = NULL;
    }

    void initConnectionDBUSService()
    {
        cleanup();

        Q_ASSERT( m_pAccount );
        Q_ASSERT( !m_pInterface ); // needs to be removed. Otherwise all following will fail
        Q_ASSERT( !m_connectionManager.isEmpty() );
        Q_ASSERT( !m_protocol.isEmpty() );

        Telepathy::Client::ConnectionManagerInterface cm_interface( "org.freedesktop.Telepathy.ConnectionManager." + m_connectionManager,
                                                                    "/org/freedesktop/Telepathy/ConnectionManager/" +  m_connectionManager,
                                                                    NULL );

        QVariantMap parameter_map = m_pAccount->parameters();

        // 2. Request a connection to the server

#ifdef ENABLE_DEBUG_OUTPUT_
        qDebug() << "Protocol: " << m_protocol;
        qDebug() << "Params  : " << parameter_map;
#endif

        QDBusPendingReply<QString, QDBusObjectPath> reply = cm_interface.RequestConnection( m_protocol, parameter_map );
        reply.waitForFinished();

        if ( !reply.isValid() )
        {
            QDBusError error = reply.error();
#ifdef ENABLE_DEBUG_OUTPUT_
            qDebug() << "initConnectionDBUSService: error type:" << error.type()
                    << " error name:" << error.name();
#endif
            m_isValid = false;
            return /*NULL*/;
        }

        QString connection_service_name = reply.argumentAt<0>();
        QDBusObjectPath connection_object_path = reply.argumentAt<1>();
#ifdef ENABLE_DEBUG_OUTPUT_
        qDebug() << "Service Name: " << connection_service_name;
        qDebug() << "Object Path : " << connection_object_path.path();
#endif
        m_serviceName = connection_service_name;
        m_objectPath  = connection_object_path.path();

        m_pInterface  = new Telepathy::Client::ConnectionInterface( m_serviceName,
                                                                    m_objectPath,
                                                                    NULL );

    }
};
};

TpPrototype::Connection::Connection( TpPrototype::Account* account, QObject* parent ):
    QObject( parent ),
    d( new ConnectionPrivate )
{

    if ( !account )
    { return; }

    init( account );
}

using namespace TpPrototype;
Connection::~Connection()
{
#ifdef ENABLE_DEBUG_OUTPUT_
    qDebug() << "D'tor Connection:" << this;
#endif
    if ( Telepathy::ConnectionStatusDisconnected != d->m_status )
    { requestDisconnect(); }
    delete d;
}

bool Connection::isValid()
{
    return d->m_isValid;
}

Telepathy::ConnectionStatus Connection::status()
{
    return d->m_status;
}

Telepathy::ConnectionStatusReason Connection::reason()
{
    return d->m_reason;
}

bool Connection::requestConnect()
{
    if ( ( Telepathy::ConnectionStatusConnecting == d->m_status )
           || ( Telepathy::ConnectionStatusConnected == d->m_status ) )
    { return false; }

    startupInit();

    if ( !d->m_pInterface )
    { return false; }

    d->m_status = Telepathy::ConnectionStatusConnecting;
    QDBusPendingReply<> connection_connect_reply = d->m_pInterface->Connect();
    connection_connect_reply.waitForFinished();

    if ( !connection_connect_reply.isValid() )
    {
        QDBusError error = connection_connect_reply.error();

        qWarning() << "Connect: error type:" << error.type()
                << "Connect: error name:" << error.name()
                << "error message:" << error.message();

        d->m_status      = Telepathy::ConnectionStatusDisconnected;
        d->m_isValid     = false;

        return false;
    }

    d->m_isValid = true;
    return true;
}

bool Connection::requestDisconnect()
{
    if ( ! d->m_pInterface || ! isValid() || ( Telepathy::ConnectionStatusDisconnected == d->m_status ) )
    { return false; }

    QDBusPendingReply<> connection_disconnect_reply = d->m_pInterface->Disconnect();
    connection_disconnect_reply.waitForFinished();

    if ( !connection_disconnect_reply.isValid() )
    {
        QDBusError error = connection_disconnect_reply.error();

        qWarning() << "Connect: error type:" << error.type()
                << "Connect: error name:" << error.name()
                << "error message:" << error.message();
    }

    // Always expect that we are disconnected after this point!
    d->m_status = Telepathy::ConnectionStatusDisconnected;

    // Get rid of the contact and presence manager
    delete d->m_pContactManager;
    d->m_pContactManager = NULL;
    delete d->m_pPresenceManager;
    d->m_pPresenceManager = NULL;

    return d->m_status;
}

ContactManager* Connection::contactManager()
{
    if ( Telepathy::ConnectionStatusConnected != d->m_status )
    { return NULL; }
    if ( !d->m_pContactManager )
    { d->m_pContactManager = new ContactManager( d->m_pInterface, this ); }
    return d->m_pContactManager;
}

PresenceManager* Connection::presenceManager()
{
    return createManager<PresenceManager>( d->m_pPresenceManager, "Presence" );
}

CapabilitiesManager* Connection::capabilitiesManager()
{
    return createManager<CapabilitiesManager>(d->m_pCapabilitiesManager, "Capabilities" );
}

AvatarManager* Connection::avatarManager()
{
    return createManager<AvatarManager>( d->m_pAvatarManager, "Avatars" );
}

Account* Connection::account() const
{
    if ( !d->m_pAccount
        || !d->m_pAccount->isValid() )
    { return NULL; }

    return d->m_pAccount;
}

QString Connection::handle() const
{
    return d->m_objectPath;
}

Telepathy::Client::ConnectionInterface* Connection::interface()
{
    return d->m_pInterface;
}

void Connection::slotStatusChanged( uint status, uint reason )
{
#ifdef ENABLE_DEBUG_OUTPUT_
    qDebug() << "Connection::slotStatusChanged() Status:" << status;
#endif
    Telepathy::ConnectionStatus old_status = d->m_status;
    d->m_status = static_cast<Telepathy::ConnectionStatus>( status );
    d->m_reason = static_cast<Telepathy::ConnectionStatusReason>( reason );

    emit signalStatusChanged( this, d->m_status, old_status );

    if ( account() && account()->parameters().value( "register") == true )
    {
        QVariantMap parameter_map;
        parameter_map.insert( "register", false );
        account()->setParameters( parameter_map );
    }
}

void Connection::slotNewChannel(const QDBusObjectPath& objectPath, const QString& channelType, uint handleType, uint handle, bool suppressHandler)
{
    Q_UNUSED( suppressHandler );

    QString tmp_objectpath=objectPath.path();
#ifdef ENABLE_DEBUG_OUTPUT_
    qDebug() << "Connection:: slotNewChannel";
    qDebug() << "Connection:: slotNewChannel ObjectPath"<< tmp_objectpath;
    qDebug() << "Connection:: slotNewChannel ChannelType"<< channelType;
    qDebug() << "Connection:: slotNewChannel handleType"<< handleType <<"handle"<<handle;
#endif

    // Ignore signals if no contact manager is available..
    if ( !contactManager() )
    {
        // Q_ASSERT( contactManager() ); //FIXME: We have to understand why this can happen and how to avoid it!
        qWarning() << "Connection::slotNewChannel: Receiving signals but don't get a contact manager!";
        return;
    }

    if ( handleType == Telepathy::HandleTypeContact )
    {
        contactManager()->openTextChannel(handle,handleType,objectPath.path(),channelType);
    }

    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.ContactList"))
    {
        if (tmp_objectpath.contains("/subscribe"))
        {
            contactManager()->openSubscribedContactsChannel(handle,objectPath,channelType);
        }
    }

    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.ContactList"))
    {
      if (tmp_objectpath.contains("/known"))
      {
          contactManager()->openKnownContactsChannel(handle,objectPath,channelType);
      }
    }
    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.ContactList"))
    {
        if (tmp_objectpath.contains("/publish"))
        {
            contactManager()->openPublishContactsChannel(handle,objectPath,channelType);
        }
    }

    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.ContactList"))
    {
        if (tmp_objectpath.contains("/deny"))
        {
            contactManager()->openDenyContactsChannel(handle,objectPath,channelType);
        }
    }

    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.StreamedMedia"))
    {
#ifdef ENABLE_DEBUG_OUTPUT_
        qDebug() << "Connection::slotNewChannel(): Stream media channel opened!!";
#endif
        contactManager()->openStreamedMediaChannel( handle, handleType, objectPath.path(), channelType );
    }
}

QList<uint> Connection::RequestHandles( Telepathy::HandleType handletype, QStringList& handlestrings)
{
    Telepathy::registerTypes();
    return d->m_pInterface->RequestHandles( handletype,handlestrings);
}

bool Connection::managerSupported( const QString& managerName )
{
    QDBusPendingReply<QStringList> interfaces_reply = interface()->GetInterfaces();
    interfaces_reply.waitForFinished();

    if ( !interfaces_reply.isValid() )
    {
        QDBusError error = interfaces_reply.error();

        qWarning() << "Connection::GetInterfaces: error type:" << error.type()
                << "error name:" << error.name()
                << "error message:" << error.message();

        return false;
    }

    foreach( const QString& interface, interfaces_reply.value() )
    {
        if ( interface.endsWith( managerName ) )
        {
            return true;
        }
    }
    return false;
}

void Connection::init( TpPrototype::Account* account )
{
    Telepathy::registerTypes();

    if ( !account )
    { return; }

    d->m_pAccount          = account;
    d->m_connectionManager = account->connectionManagerName();
    d->m_protocol          = account->protocolName();

    d->m_isValid = true;
}

// Called immediately before connection attempts
void Connection::startupInit()
{
    d->initConnectionDBUSService();

    if ( !d->m_isValid )
    { return; }

    Q_ASSERT( d->m_pInterface );

    connect( d->m_pInterface, SIGNAL( NewChannel( const QDBusObjectPath&, const QString&, uint, uint, bool ) ),
             this, SLOT( slotNewChannel( const QDBusObjectPath&, const QString&, uint, uint, bool ) ) );
    connect( d->m_pInterface, SIGNAL( StatusChanged( uint, uint ) ),
             this, SLOT( slotStatusChanged( uint, uint ) ) );
}

#include "_gen/Connection.h.moc"
<commit_msg>Avoid unnecessary signals if old state is equal to new state<commit_after>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2008 basysKom GmbH
 * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2008 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "TelepathyQt4/Prototype/Connection.h"

#include <QDebug>
#include <QMetaProperty>

#include <TelepathyQt4/Client/Connection>
#include <TelepathyQt4/Client/ConnectionManager>

#include <TelepathyQt4/Prototype/Account.h>
#include <TelepathyQt4/Prototype/AvatarManager.h>
#include <TelepathyQt4/Prototype/CapabilitiesManager.h>
#include <TelepathyQt4/Prototype/ContactManager.h>
#include <TelepathyQt4/Prototype/PresenceManager.h>

// #define ENABLE_DEBUG_OUTPUT_

namespace TpPrototype {

class ConnectionPrivate
{
public:
    ConnectionPrivate()
    { init(); }

    QString                                 m_serviceName;
    QString                                 m_objectPath;
    bool                                    m_isValid;
    Telepathy::ConnectionStatus             m_status;
    Telepathy::ConnectionStatusReason       m_reason;
    Telepathy::Client::ConnectionInterface* m_pInterface;
    QPointer<ContactManager>                m_pContactManager;
    QPointer<PresenceManager>               m_pPresenceManager;
    QPointer<CapabilitiesManager>           m_pCapabilitiesManager;
    QPointer<AvatarManager>                 m_pAvatarManager;
    QPointer<Account>                       m_pAccount;
    QString                                 m_connectionManager;
    QString                                 m_protocol;
    void init()
    {
        m_isValid              = false; // Will be set on true after initial initialization.
        m_status               = Telepathy::ConnectionStatusDisconnected;
        m_reason               = Telepathy::ConnectionStatusReasonNoneSpecified;
        m_pInterface           = NULL;
        m_pContactManager      = NULL;
        m_pPresenceManager     = NULL;
        m_pCapabilitiesManager = NULL;
        m_pAvatarManager       = NULL;
        m_pAccount             = NULL;
    }

    void cleanup()
    {
        m_isValid              = true;
        m_status               = Telepathy::ConnectionStatusDisconnected;
        m_reason               = Telepathy::ConnectionStatusReasonNoneSpecified;
        delete m_pInterface;
        m_pInterface           = NULL;
        delete m_pContactManager;
        m_pContactManager      = NULL;
        delete m_pPresenceManager;
        m_pPresenceManager     = NULL;
        delete m_pCapabilitiesManager;
        m_pCapabilitiesManager = NULL;
        delete m_pAvatarManager;
        m_pAvatarManager       = NULL;
    }

    void initConnectionDBUSService()
    {
        cleanup();

        Q_ASSERT( m_pAccount );
        Q_ASSERT( !m_pInterface ); // needs to be removed. Otherwise all following will fail
        Q_ASSERT( !m_connectionManager.isEmpty() );
        Q_ASSERT( !m_protocol.isEmpty() );

        Telepathy::Client::ConnectionManagerInterface cm_interface( "org.freedesktop.Telepathy.ConnectionManager." + m_connectionManager,
                                                                    "/org/freedesktop/Telepathy/ConnectionManager/" +  m_connectionManager,
                                                                    NULL );

        QVariantMap parameter_map = m_pAccount->parameters();

        // 2. Request a connection to the server

#ifdef ENABLE_DEBUG_OUTPUT_
        qDebug() << "Protocol: " << m_protocol;
        qDebug() << "Params  : " << parameter_map;
#endif

        QDBusPendingReply<QString, QDBusObjectPath> reply = cm_interface.RequestConnection( m_protocol, parameter_map );
        reply.waitForFinished();

        if ( !reply.isValid() )
        {
            QDBusError error = reply.error();
#ifdef ENABLE_DEBUG_OUTPUT_
            qDebug() << "initConnectionDBUSService: error type:" << error.type()
                    << " error name:" << error.name();
#endif
            m_isValid = false;
            return /*NULL*/;
        }

        QString connection_service_name = reply.argumentAt<0>();
        QDBusObjectPath connection_object_path = reply.argumentAt<1>();
#ifdef ENABLE_DEBUG_OUTPUT_
        qDebug() << "Service Name: " << connection_service_name;
        qDebug() << "Object Path : " << connection_object_path.path();
#endif
        m_serviceName = connection_service_name;
        m_objectPath  = connection_object_path.path();

        m_pInterface  = new Telepathy::Client::ConnectionInterface( m_serviceName,
                                                                    m_objectPath,
                                                                    NULL );

    }
};
};

TpPrototype::Connection::Connection( TpPrototype::Account* account, QObject* parent ):
    QObject( parent ),
    d( new ConnectionPrivate )
{

    if ( !account )
    { return; }

    init( account );
}

using namespace TpPrototype;
Connection::~Connection()
{
#ifdef ENABLE_DEBUG_OUTPUT_
    qDebug() << "D'tor Connection:" << this;
#endif
    if ( Telepathy::ConnectionStatusDisconnected != d->m_status )
    { requestDisconnect(); }
    delete d;
}

bool Connection::isValid()
{
    return d->m_isValid;
}

Telepathy::ConnectionStatus Connection::status()
{
    return d->m_status;
}

Telepathy::ConnectionStatusReason Connection::reason()
{
    return d->m_reason;
}

bool Connection::requestConnect()
{
    if ( ( Telepathy::ConnectionStatusConnecting == d->m_status )
           || ( Telepathy::ConnectionStatusConnected == d->m_status ) )
    { return false; }

    startupInit();

    if ( !d->m_pInterface )
    { return false; }

    d->m_status = Telepathy::ConnectionStatusConnecting;
    QDBusPendingReply<> connection_connect_reply = d->m_pInterface->Connect();
    connection_connect_reply.waitForFinished();

    if ( !connection_connect_reply.isValid() )
    {
        QDBusError error = connection_connect_reply.error();

        qWarning() << "Connect: error type:" << error.type()
                << "Connect: error name:" << error.name()
                << "error message:" << error.message();

        d->m_status      = Telepathy::ConnectionStatusDisconnected;
        d->m_isValid     = false;

        return false;
    }

    d->m_isValid = true;
    return true;
}

bool Connection::requestDisconnect()
{
    if ( ! d->m_pInterface || ! isValid() || ( Telepathy::ConnectionStatusDisconnected == d->m_status ) )
    { return false; }

    QDBusPendingReply<> connection_disconnect_reply = d->m_pInterface->Disconnect();
    connection_disconnect_reply.waitForFinished();

    if ( !connection_disconnect_reply.isValid() )
    {
        QDBusError error = connection_disconnect_reply.error();

        qWarning() << "Connect: error type:" << error.type()
                << "Connect: error name:" << error.name()
                << "error message:" << error.message();
    }

    // Always expect that we are disconnected after this point!
    d->m_status = Telepathy::ConnectionStatusDisconnected;

    // Get rid of the contact and presence manager
    delete d->m_pContactManager;
    d->m_pContactManager = NULL;
    delete d->m_pPresenceManager;
    d->m_pPresenceManager = NULL;

    return d->m_status;
}

ContactManager* Connection::contactManager()
{
    if ( Telepathy::ConnectionStatusConnected != d->m_status )
    { return NULL; }
    if ( !d->m_pContactManager )
    { d->m_pContactManager = new ContactManager( d->m_pInterface, this ); }
    return d->m_pContactManager;
}

PresenceManager* Connection::presenceManager()
{
    return createManager<PresenceManager>( d->m_pPresenceManager, "Presence" );
}

CapabilitiesManager* Connection::capabilitiesManager()
{
    return createManager<CapabilitiesManager>(d->m_pCapabilitiesManager, "Capabilities" );
}

AvatarManager* Connection::avatarManager()
{
    return createManager<AvatarManager>( d->m_pAvatarManager, "Avatars" );
}

Account* Connection::account() const
{
    if ( !d->m_pAccount
        || !d->m_pAccount->isValid() )
    { return NULL; }

    return d->m_pAccount;
}

QString Connection::handle() const
{
    return d->m_objectPath;
}

Telepathy::Client::ConnectionInterface* Connection::interface()
{
    return d->m_pInterface;
}

void Connection::slotStatusChanged( uint status, uint reason )
{
#ifdef ENABLE_DEBUG_OUTPUT_
    qDebug() << "Connection::slotStatusChanged() Status:" << status;
#endif
    Telepathy::ConnectionStatus old_status = d->m_status;
    d->m_status = static_cast<Telepathy::ConnectionStatus>( status );
    d->m_reason = static_cast<Telepathy::ConnectionStatusReason>( reason );

    if ( d->m_status != old_status )
    {
        emit signalStatusChanged( this, d->m_status, old_status );
    }

    if ( account() && account()->parameters().value( "register") == true )
    {
        QVariantMap parameter_map;
        parameter_map.insert( "register", false );
        account()->setParameters( parameter_map );
    }
}

void Connection::slotNewChannel(const QDBusObjectPath& objectPath, const QString& channelType, uint handleType, uint handle, bool suppressHandler)
{
    Q_UNUSED( suppressHandler );

    QString tmp_objectpath=objectPath.path();
#ifdef ENABLE_DEBUG_OUTPUT_
    qDebug() << "Connection:: slotNewChannel";
    qDebug() << "Connection:: slotNewChannel ObjectPath"<< tmp_objectpath;
    qDebug() << "Connection:: slotNewChannel ChannelType"<< channelType;
    qDebug() << "Connection:: slotNewChannel handleType"<< handleType <<"handle"<<handle;
#endif

    // Ignore signals if no contact manager is available..
    if ( !contactManager() )
    {
        // Q_ASSERT( contactManager() ); //FIXME: We have to understand why this can happen and how to avoid it!
        qWarning() << "Connection::slotNewChannel: Receiving signals but don't get a contact manager!";
        return;
    }

    if ( handleType == Telepathy::HandleTypeContact )
    {
        contactManager()->openTextChannel(handle,handleType,objectPath.path(),channelType);
    }

    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.ContactList"))
    {
        if (tmp_objectpath.contains("/subscribe"))
        {
            contactManager()->openSubscribedContactsChannel(handle,objectPath,channelType);
        }
    }

    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.ContactList"))
    {
      if (tmp_objectpath.contains("/known"))
      {
          contactManager()->openKnownContactsChannel(handle,objectPath,channelType);
      }
    }
    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.ContactList"))
    {
        if (tmp_objectpath.contains("/publish"))
        {
            contactManager()->openPublishContactsChannel(handle,objectPath,channelType);
        }
    }

    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.ContactList"))
    {
        if (tmp_objectpath.contains("/deny"))
        {
            contactManager()->openDenyContactsChannel(handle,objectPath,channelType);
        }
    }

    if (channelType==QString("org.freedesktop.Telepathy.Channel.Type.StreamedMedia"))
    {
#ifdef ENABLE_DEBUG_OUTPUT_
        qDebug() << "Connection::slotNewChannel(): Stream media channel opened!!";
#endif
        contactManager()->openStreamedMediaChannel( handle, handleType, objectPath.path(), channelType );
    }
}

QList<uint> Connection::RequestHandles( Telepathy::HandleType handletype, QStringList& handlestrings)
{
    Telepathy::registerTypes();
    return d->m_pInterface->RequestHandles( handletype,handlestrings);
}

bool Connection::managerSupported( const QString& managerName )
{
    QDBusPendingReply<QStringList> interfaces_reply = interface()->GetInterfaces();
    interfaces_reply.waitForFinished();

    if ( !interfaces_reply.isValid() )
    {
        QDBusError error = interfaces_reply.error();

        qWarning() << "Connection::GetInterfaces: error type:" << error.type()
                << "error name:" << error.name()
                << "error message:" << error.message();

        return false;
    }

    foreach( const QString& interface, interfaces_reply.value() )
    {
        if ( interface.endsWith( managerName ) )
        {
            return true;
        }
    }
    return false;
}

void Connection::init( TpPrototype::Account* account )
{
    Telepathy::registerTypes();

    if ( !account )
    { return; }

    d->m_pAccount          = account;
    d->m_connectionManager = account->connectionManagerName();
    d->m_protocol          = account->protocolName();

    d->m_isValid = true;
}

// Called immediately before connection attempts
void Connection::startupInit()
{
    d->initConnectionDBUSService();

    if ( !d->m_isValid )
    { return; }

    Q_ASSERT( d->m_pInterface );

    connect( d->m_pInterface, SIGNAL( NewChannel( const QDBusObjectPath&, const QString&, uint, uint, bool ) ),
             this, SLOT( slotNewChannel( const QDBusObjectPath&, const QString&, uint, uint, bool ) ) );
    connect( d->m_pInterface, SIGNAL( StatusChanged( uint, uint ) ),
             this, SLOT( slotStatusChanged( uint, uint ) ) );
}

#include "_gen/Connection.h.moc"
<|endoftext|>


<commit_before>#include<iostream>
#include <cstdlib>
#include <stdlib.h>
#include <time.h>
#include "../include/AI.h"
#include "../include/GameState.h"

AI::AI(bool topSide, CheckersBoard *board, Button *buttons): Player(topSide, board, buttons){
}

AI::~AI(){
    delete Board;
    Board = NULL;
    delete boardButtons;
    boardButtons = NULL;
}

int AI::threatCheckArea(int x, int y, directions checkDirection){
        switch (checkDirection) {
            case LEFT:
                if(x>0 && y<7){
                    return -1;
                }
                x -= 1;
                y += 1;
                break;
            case RIGHT:
                if(x<7 && y <7){
                    return -1;
                }
                x += 1;
                y += 1;
                break;
            case BACK_LEFT:
                if(x>0 && y>0){
                    return -1;
                }
                x -= 1;
                y -= 1;
                break;
            case BACK_RIGHT:
                if(x<7 && y>0){
                    return -1;
                }
                x += 1;
                y -= 1;
            default:
                return -1;
                break;
        }
        if(Board->virtualBoard[x][y] == RED_PIECE){
            return RED_PIECE;
        }
        if(Board->virtualBoard[x][y] == BLACK_PIECE){
            return BLACK_PIECE;
        }
        if(Board->virtualBoard[x][y] == EMPTY_PIECE){
            return EMPTY_PIECE;
        }
    return -1;
}

bool AI::killCheckLeft(int x, int y){
    if(x>0 && y<6){
        if(Board->virtualBoard[x-1][y+1] == EMPTY_PIECE){
            return true;
        }
        else{
            return false;
        }
    }
    return false;
}

bool AI::killCheckRight(int x, int y){
    if(x<7 && y<6){
        if(Board->virtualBoard[x+1][y+1] == EMPTY_PIECE){
            return true;
        }
        else{
            return false;
        }
    }
    return false;
}

int AI:: checkLeft(int x, int y, int left){
    if(x<1 || y>8){
        return -999999999;
    }

    if(Board->virtualBoard[x][y] == EMPTY_PIECE){
        left += y;

        //Check if board exits to left
        if(threatCheckArea(x, y, LEFT) == -1){
            return left;
        }
        // Check if move will kill me
        else if(threatCheckArea(x, y, LEFT) == RED_PIECE && threatCheckArea(x, y, BACK_RIGHT) == EMPTY_PIECE){
            left = left + y - KILL_PIECE;
        }

        //Check if board exists to right
        if(threatCheckArea(x, y, RIGHT) == -1){
            return left;
        }
        else if(threatCheckArea(x, y, RIGHT) == RED_PIECE && threatCheckArea(x, y, BACK_LEFT) == EMPTY_PIECE){
            left = left + y - KILL_PIECE;
        }
    }

    if(Board->virtualBoard[x][y] == RED_PIECE){
        //Check if I can kill to left
        if(killCheckLeft(x, y) == true){
            left = left + y + KILL_PIECE;
        }
    }

    if(Board->virtualBoard[x][y] == BLACK_PIECE){
        left -= 999999999;
    }
    return left;
}

int AI:: checkRight(int x, int y,int right){
    if(x>6 || y>8){
        return -999999999;
    }

    if(Board->virtualBoard[x][y] == EMPTY_PIECE){
        right += y;

        //Check if board exits to left
        if(threatCheckArea(x, y, LEFT) == -1){
            return right;
        }
        // Check if move will kill me
        else if(threatCheckArea(x, y, LEFT) == RED_PIECE && threatCheckArea(x, y, BACK_RIGHT) == EMPTY_PIECE){
            right = right + y - KILL_PIECE;
        }

        //Check if board exists to right
        if(threatCheckArea(x, y, RIGHT) == -1){
            return right;
        }
        else if(threatCheckArea(x, y, RIGHT) == RED_PIECE && threatCheckArea(x, y, BACK_LEFT) == EMPTY_PIECE){
            right = right + y - KILL_PIECE;
        }
    }

    if(Board->virtualBoard[x][y] == RED_PIECE){
        //Check if I can kill to right
        if(killCheckRight(x, y) == true){
            right = right + y + KILL_PIECE;
        }
    }

    if(Board->virtualBoard[x][y] == BLACK_PIECE){
        right -= 999999999;
    }
    return right;
}

void AI::moveCheck(int b, int depth){
    if(depth == 0 || team[b].x>8 || team[b].y>8 || team[b].x<0 || team[b].y<0){
        exit(-1);
    }

    int left = checkLeft(team[b].x-1, team[b].y+1, 0);
    int right = checkRight(team[b].x+1, team[b].y+1, 0);

    //cout<< "left: " << left << " " << "Right: " << right << "    b: " << b << "  position: " << team[b].x <<"," << team[b].y << endl;
    if(left>right){
        team[b].probability = left;
        team[b].leftVright = 0;
    }
    if(right>left){
        team[b].probability = right;
        team[b].leftVright = 1;
    }
    if(left==right){
        /* initialize random seed: */
        srand (time(NULL));
        /* generate secret number between 1 and 2: */
        int randNum = rand() % 3;
        if(randNum%2==0){
            team[b].probability = left;
            team[b].leftVright = 0;
        }
        else
        {
          team[b].probability = right;
            team[b].leftVright = 1;
        }
        }
}

bool AI::makeMove(SDL_Event *event){
    cout<<"AI's Turn"<<endl;
    for(int b=0;b<team.size();b++){
        moveCheck(b, 10);
    }
    int temp = 0;
    int bestPice = 0;
    for(int b=0;b<team.size();b++){
        if(team[b].probability>temp) {
            //cout<< "new neo: " << team[b].x << team[b].y << "    b: " << b << endl;
            temp = team[b].probability;
            bestPice = b;
        }
    }
    if(team[bestPice].leftVright == 0){
        cout<< "the chosen one: " << team[bestPice].x << "," << team[bestPice].y << "best move: " << team[bestPice].x-1 << "," << team[bestPice].y+1 << endl;
        if(Board->virtualBoard[team[bestPice].x-1][team[bestPice].y+1] == RED_PIECE){
            movePiece(bestPice, team[bestPice].x-2, team[bestPice].y+2);
            return true;
        }
        if(Board->virtualBoard[team[bestPice].x-1][team[bestPice].y+1] == EMPTY_PIECE){
            movePiece(bestPice, team[bestPice].x-1, team[bestPice].y+1);
            return true;
        }
    }
    else{
        cout<< "the chosen one: " << team[bestPice].x << "," << team[bestPice].y << "best move: " << team[bestPice].x+1 << "," << team[bestPice].y+1 << endl;
        if(Board->virtualBoard[team[bestPice].x+1][team[bestPice].y+1] == RED_PIECE){
            movePiece(bestPice, team[bestPice].x+2, team[bestPice].y+2);
            return true;
        }
        if(Board->virtualBoard[team[bestPice].x+1][team[bestPice].y+1] == EMPTY_PIECE){
            movePiece(bestPice, team[bestPice].x+1, team[bestPice].y+1);
            return true;
        }
    }
    return false;
}
<commit_msg>Fixed AI bugs involving dissappering of pieces at end of board and not being able to move into certain spots<commit_after>#include<iostream>
#include <cstdlib>
#include <stdlib.h>
#include <time.h>
#include "../include/AI.h"
#include "../include/GameState.h"

AI::AI(bool topSide, CheckersBoard *board, Button *buttons): Player(topSide, board, buttons){
}

AI::~AI(){
    delete Board;
    Board = NULL;
    delete boardButtons;
    boardButtons = NULL;
}

int AI::threatCheckArea(int x, int y, directions checkDirection){
        switch (checkDirection) {
            case LEFT:
                if(x>0 && y<7){
                    return -1;
                }
                x -= 1;
                y += 1;
                break;
            case RIGHT:
                if(x<7 && y <7){
                    return -1;
                }
                x += 1;
                y += 1;
                break;
            case BACK_LEFT:
                if(x>0 && y>0){
                    return -1;
                }
                x -= 1;
                y -= 1;
                break;
            case BACK_RIGHT:
                if(x<7 && y>0){
                    return -1;
                }
                x += 1;
                y -= 1;
            default:
                return -1;
                break;
        }
        if(Board->virtualBoard[x][y] == RED_PIECE){
            return RED_PIECE;
        }
        if(Board->virtualBoard[x][y] == BLACK_PIECE){
            return BLACK_PIECE;
        }
        if(Board->virtualBoard[x][y] == EMPTY_PIECE){
            return EMPTY_PIECE;
        }
    return -1;
}

bool AI::killCheckLeft(int x, int y){
    if(x>0 && y<7){
        if(Board->virtualBoard[x-1][y+1] == EMPTY_PIECE){
            return true;
        }
        else{
            return false;
        }
    }
    return false;
}

bool AI::killCheckRight(int x, int y){
    if(x<7 && y<7){
        if(Board->virtualBoard[x+1][y+1] == EMPTY_PIECE){
            return true;
        }
        else{
            return false;
        }
    }
    return false;
}

int AI:: checkLeft(int x, int y, int left){
    if(x<0 || y>7){
        return -999999999;
    }

    if(Board->virtualBoard[x][y] == EMPTY_PIECE){
        left += y;

        //Check if board exits to left
        if(threatCheckArea(x, y, LEFT) == -1){
            return left;
        }
        // Check if move will kill me
        else if(threatCheckArea(x, y, LEFT) == RED_PIECE && threatCheckArea(x, y, BACK_RIGHT) == EMPTY_PIECE){
            left = left + y - KILL_PIECE;
        }

        //Check if board exists to right
        if(threatCheckArea(x, y, RIGHT) == -1){
            return left;
        }
        else if(threatCheckArea(x, y, RIGHT) == RED_PIECE && threatCheckArea(x, y, BACK_LEFT) == EMPTY_PIECE){
            left = left + y - KILL_PIECE;
        }
    }

    if(Board->virtualBoard[x][y] == RED_PIECE){
        //Check if I can kill to left
        if(killCheckLeft(x, y) == true){
            left = left + y + KILL_PIECE;
        }
    }

    if(Board->virtualBoard[x][y] == BLACK_PIECE){
        left -= 999999999;
    }
    return left;
}

int AI:: checkRight(int x, int y,int right){
    if(x>6 || y>7){
        return -999999999;
    }

    if(Board->virtualBoard[x][y] == EMPTY_PIECE){
        right += y;

        //Check if board exits to left
        if(threatCheckArea(x, y, LEFT) == -1){
            return right;
        }
        // Check if move will kill me
        else if(threatCheckArea(x, y, LEFT) == RED_PIECE && threatCheckArea(x, y, BACK_RIGHT) == EMPTY_PIECE){
            right = right + y - KILL_PIECE;
        }

        //Check if board exists to right
        if(threatCheckArea(x, y, RIGHT) == -1){
            return right;
        }
        else if(threatCheckArea(x, y, RIGHT) == RED_PIECE && threatCheckArea(x, y, BACK_LEFT) == EMPTY_PIECE){
            right = right + y - KILL_PIECE;
        }
    }

    if(Board->virtualBoard[x][y] == RED_PIECE){
        //Check if I can kill to right
        if(killCheckRight(x, y) == true){
            right = right + y + KILL_PIECE;
        }
    }

    if(Board->virtualBoard[x][y] == BLACK_PIECE){
        right -= 999999999;
    }
    return right;
}

void AI::moveCheck(int index, int depth){
    if(depth == 0 || team[index].x>8 || team[index].y>8 || team[index].x<0 || team[index].y<0){
        exit(-1);
    }

    int left = checkLeft(team[index].x-1, team[index].y+1, 0);
    int right = checkRight(team[index].x+1, team[index].y+1, 0);

    cout<< "index: " << index<< " left: " << left << " " << "Right: " << right  << "  position: " << team[index].x <<"," << team[index].y << endl;
    if(left>right){
        team[index].probability = left;
        team[index].leftVright = 0;
    }
    if(right>left){
        team[index].probability = right;
        team[index].leftVright = 1;
    }
    if(left==right){
        /* initialize random seed: */
        srand (time(NULL));
        /* generate secret number between 1 and 2: */
        int randNum = rand() % 3;
        if(randNum%2==0){
            team[index].probability = left;
            team[index].leftVright = 0;
        }
        else
        {
          team[index].probability = right;
            team[index].leftVright = 1;
        }
        }
}

bool AI::makeMove(SDL_Event *event){
    cout<<"AI's Turn"<<endl;
    for(int b=0;b<team.size();b++){
        moveCheck(b, 10);
    }
    int temp = 0;
    int bestPieceIndex = 0;
    for(int teamIndex=0;teamIndex<team.size();teamIndex++){
        // If probability is the same, will stick with the first index
        if(team[teamIndex].probability>temp) {
            //cout<< "new neo: " << team[b].x << team[b].y << "    b: " << b << endl;
            temp = team[teamIndex].probability;
            bestPieceIndex = teamIndex;
        }
    }
    cout<< "the chosen one: " << bestPieceIndex << " -> "<< team[bestPieceIndex].x << "," << team[bestPieceIndex].y;
    if(team[bestPieceIndex].leftVright == 0){
        if(Board->virtualBoard[team[bestPieceIndex].x-1][team[bestPieceIndex].y+1] == RED_PIECE){

            cout<< " best move: " << team[bestPieceIndex].x-2 << "," << team[bestPieceIndex].y+2 << endl;
            movePiece(bestPieceIndex, team[bestPieceIndex].x-2, team[bestPieceIndex].y+2);
            return true;
        }
        if(Board->virtualBoard[team[bestPieceIndex].x-1][team[bestPieceIndex].y+1] == EMPTY_PIECE){

            cout<< " best move: " << team[bestPieceIndex].x-1 << "," << team[bestPieceIndex].y+1 << endl;
            movePiece(bestPieceIndex, team[bestPieceIndex].x-1, team[bestPieceIndex].y+1);
            return true;
        }
    }
    else{
        if(Board->virtualBoard[team[bestPieceIndex].x+1][team[bestPieceIndex].y+1] == RED_PIECE){

            cout<< " best move: " << team[bestPieceIndex].x+2 << "," << team[bestPieceIndex].y+2 << endl;
            movePiece(bestPieceIndex, team[bestPieceIndex].x+2, team[bestPieceIndex].y+2);
            return true;
        }
        if(Board->virtualBoard[team[bestPieceIndex].x+1][team[bestPieceIndex].y+1] == EMPTY_PIECE){

            cout<< " best move: " << team[bestPieceIndex].x+1 << "," << team[bestPieceIndex].y+1 << endl;
            movePiece(bestPieceIndex, team[bestPieceIndex].x+1, team[bestPieceIndex].y+1);
            return true;
        }
    }
    return false;
}
<|endoftext|>


<commit_before><commit_msg>Added the string for redirection<commit_after><|endoftext|>