<html>

<head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 6.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>TrianGO</title>
</head>

<body>



<p align="left"><font size="6" color="#FF0000"><span lang="en-ca"><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </b></span>
</font><span lang="en-ca"><font size="6" color="#FF0000"><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TrianGO</b></font></span></p>
<p align="left"><span lang="en-ca"><b><font size="6" color="#FF0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font>
<font size="4" color="#FF0000">A game of GO on triangles&nbsp; </font> </b></span></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A. First Edition</font></b></pre>
</div>
<div align="left">
  <pre><b><font size="3">This is <span lang="en-ca">my project of comp6711 and it is an interesting little game of triangles which simulates some feature </span></font></b></pre>
</div>
<div align="left">
  <pre><b><font size="3"><span lang="en-ca">of game GO.</span></font></b></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">B</span>.<span lang="en-ca"><a name="problem"></a>The problem</span></font></b></pre>
</div>
<div align="left">
  <p ALIGN="LEFT"><span lang="en-ca">To best understand the game, you may need 
	to download a demo
	<a href="http://tech.groups.yahoo.com/group/comp6231winter/files/comp6711/">
	slides from here</a>.</span></div>
<div align="left">
  <p ALIGN="LEFT">¡¡</div>
<div align="left">
  <p ALIGN="LEFT">¡¡</div>
<div align="left">
  <b><font color="#ff0000" size="5"><span lang="en-ca"><a name="explain"></a>C</span>.<span lang="en-ca">The
  </span></font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>idea of 
  program</b></font></span></div>
<div align="left">
  ¡¡</div>
<p>¡¡</p>
<div align="left">
  <pre><b><font color="#ff0000" size="5">D.<span lang="en-ca"><a name="Method"></a>The </span>major functions</font></b></pre>
</div>
<div align="left">
	<pre><span lang="en-ca"><font size="3"><b>In order to run in OpenGL, you need download &quot;glut32.dll&quot; and &quot;glu32.dll&quot; in your system folder. </b></font></span></pre>
</div>
<div align="left">
	<pre><span lang="en-ca"><font size="3"><b>i.e. c:\windows\system32</b></font></span></pre>
</div>
<div align="left">
	<pre><span lang="en-ca"><font size="3"><b>And to compile the code, you need to link with &quot;openGL32.lib, glut32.lib, glu32.lib&quot; in your vc6++.</b></font></span></pre>
</div>
<div align="left">
	<pre>¡¡</pre>
</div>
<div align="left">
	<pre>¡¡</pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">E</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>Further improvement</b></font></span></pre>
</div>
<div align="left">
  <p class="MsoNormal">Compilation:</p>
	<p class="MsoNormal" style="text-indent: -18.0pt; margin-left: 33.0pt">a)<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	</span>This project only uses common glu and glut as library.</p>
	<p class="MsoNormal" style="text-indent: -18.0pt; margin-left: 33.0pt">b)<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	</span>In case when system is not installed with these library, copy 
	glu32.lib, glut32.lib to library path of Visual C++ 6.0. For example, the 
	path may look like this:</p>
	<p class="MsoNormal" style="margin-left:15.0pt">C:\Program Files\Microsoft 
	Visual Studio\VC98\Lib</p>
	<p class="MsoNormal" style="margin-left:15.0pt">&nbsp;</p>
	<p class="MsoNormal" style="text-indent: -18.0pt; margin-left: 33.0pt">c)<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	</span>My code will automatically add libs into project by macros, so you 
	don¡¯t have to add these libs into your Visual6.0 project file setting by 
	hand.</p>
	<p class="MsoNormal">&nbsp;</p>
	<p class="MsoNormal">Running: </p>
	<p class="MsoNormal" style="text-indent: -18.0pt; margin-left: 33.0pt">a)<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	</span>In system where glu or glut library are not installed, as long as you 
	keep glu32.dll and glut32.dll in same directory with executable file 
	¡°TrianGO.exe¡± it should be able to run correctly.</p>
	<p class="MsoNormal">&nbsp;</p>
	<p class="MsoNormal">Operation:</p>
	<p class="MsoNormal" style="text-indent: -18.0pt; margin-left: 33.0pt">a)<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	</span>create random points: by right click mouse or press ¡®n¡¯;</p>
	<p class="MsoNormal" style="text-indent: -18.0pt; margin-left: 33.0pt">b)<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	</span>create nested convex hull:&nbsp; by press ¡®n¡¯.</p>
	<p class="MsoNormal" style="text-indent: -18.0pt; margin-left: 33.0pt">c)<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	</span>create triangulation: press ¡®t¡¯.</p>
	<p class="MsoNormal" style="text-indent: -18.0pt; margin-left: 33.0pt">d)<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;
	</span>start playing: left click triangles in chess board.</p>
	<p class="MsoNormal" style="margin-left:15.0pt">&nbsp;</p>
	<p class="MsoNormal" style="margin-left:15.0pt">restart: press ¡®a¡¯ to clear 
	everything.</p>
	<p class="MsoNormal" style="margin-left:15.0pt">To show menu: press ¡®m¡¯</p>
	<p class="MsoNormal" style="margin-left:15.0pt">To exit: press ¡®esc¡¯</p>
	<p class="MsoNormal" style="margin-left:15.0pt">&nbsp;</p>
  <pre>¡¡</pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">F</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>File listing</b></font></span></pre>
</div>
<div align="left" style="width: 898; height: 86">
  <pre><font size="3"><b><span lang="en-ca">1. common.h</span></b></font></pre>
	<pre><span lang="en-ca"><font size="3"><b>2. common.cpp</b></font></span></pre>
  <pre><font size="3"><b><span lang="en-ca">3. </span>C<span lang="en-ca">onvexHull.h</span></b></font></pre>
	<pre><span lang="en-ca"><font size="3"><b>4. ConvexHull.cpp</b></font></span></pre>
  <pre><font size="3"><b><span lang="en-ca">5. main.cpp</span></b></font></pre>
  <pre>¡¡</pre>
	<pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: common</span>.<span lang="en-ca">h</span></b></font></pre>
	<pre>#ifndef COMMON_H
#define COMMON_H
#include &lt;set&gt;
#include &lt;vector&gt;
#include &lt;deque&gt;

using namespace std;


#pragma comment(lib, &quot;opengl32.lib&quot;)
#pragma comment(lib, &quot;glu32.lib&quot;)
#pragma comment(lib, &quot;glut32.lib&quot;)


const int winPos_x=0, winPos_y=0;
const int winSize_width=600, winSize_height=600;
static const char* windowTitle=&quot;Convex Hull Demo&quot;;

const int MaxIntegerValue=winSize_width/2-30;

typedef float TColor[3];

typedef float TVector2[2];

static TColor red={1,0,0}, green={0,1,0}, blue={0,0,1}, yellow={0,1,1}, beige={1,1,0};

typedef float TPlayerColors[2][3];

static float playerColor[3][3]={{1,0,0}, {0,0,1}, {0,1,1}};
struct TTriangle;


enum FaceStatus
{
	Red=0, Blue=1, Empty=2
};

struct TPoint
{
	float x;
	float y;
	const TPoint&amp; operator=(const TPoint&amp; other)
	{
		x=other.x;
		y=other.y;
		return *this;
	}
	TPoint(){;}
	TPoint(float theX, float theY) 
	{
		x=theX;
		y=theY;
	} 
	void display() const;	
	void display();
};

struct PrevPoint
{
	bool operator()(const TPoint&amp; first, const TPoint&amp; second)
	{
		if (first.x==second.x)
		{
			return first.y&gt;second.y;
		}
		else
		{
			return first.x&lt;second.x;
		}
	}
	bool operator()(const TPoint&amp; first, const TPoint&amp; second) const
	{
		if (first.x==second.x)
		{
			return first.y&gt;second.y;
		}
		else
		{
			return first.x&lt;second.x;
		}
	}
};

static PrevPoint prevPoint;


struct TPointContext
{
	TPoint point;
	TColor pointColor;
};

int compPoint(const void* elem1, const void* elem2);
float direction(TPoint* p, TPoint* q, TPoint* r);
float generateRandomValue();
void generatePoint(int pointNumber, TPoint*&amp; ptrArray);


typedef TPoint TTriPoint[3];

typedef set&lt;TPoint, PrevPoint&gt; TPointSet;
typedef vector&lt;TPoint&gt; TPointVector;
typedef deque&lt;TPoint&gt; TPointQueue;
typedef deque&lt;TTriangle&gt; TTriangleQueue;

const TPointSet&amp; setCopy(TPointSet&amp; dest, const TPointSet&amp; source);
void generateRandomPoint(int pointNumber, TPointSet&amp; pointSet);

struct TTriangle
{
	TTriPoint triangle;
	void assign(TPoint p1, TPoint p2, TPoint p3);

	bool pointInside(TPoint&amp; point);
	void display();
	void draw();
	TTriangle&amp; operator=(TTriangle&amp; other)
	{
		for (int i=0; i&lt;3; i++)
		{
			triangle[i]=other.triangle[i];
		}
		return *this;
	}
};



struct TEdge;
struct TFace;
typedef TEdge* TTripleEdgePtr[3];
typedef TPoint TPairPoint[2];

//undirected edge
struct TEdge
{
	TPairPoint pairPoint;
	TColor color;
	TFace* faces[2];
	void display();
	void draw();
};

struct PrevEdge
{
	//assume the point in edge is sorted when constructed.
	//that is, pointPair[0]&lt;pointPair[1]
	bool operator()(TEdge* first, TEdge* second)
	{
		for (int i=0; i&lt;2; i++)
		{
			if (prevPoint(first-&gt;pairPoint[i], second-&gt;pairPoint[i]))
			{
				return true;
			}
			if (prevPoint(second-&gt;pairPoint[i], first-&gt;pairPoint[i]))
			{
				return false;
			}
		}
		//equal edge
		return false;
	}
	bool operator()(TEdge* first, TEdge* second) const
	{
		for (int i=0; i&lt;2; i++)
		{
			if (prevPoint(first-&gt;pairPoint[i], second-&gt;pairPoint[i]))
			{
				return true;
			}
			if (prevPoint(second-&gt;pairPoint[i], first-&gt;pairPoint[i]))
			{
				return false;
			}
		}
		//equal edge
		return false;
	}
};

static PrevEdge prevEdge;

typedef set&lt;TEdge*, PrevEdge&gt; TEdgePtrSet;

struct TFace
{
	TTripleEdgePtr edges;
	TColor color;
	FaceStatus status;
	bool pointInside(TPoint&amp; point);
	void display();
	void draw();
	
};

struct PrevFace
{
	//assume three edges are sorted in TFace
	bool operator()(TFace* first, TFace* second)
	{
		for (int i=0; i&lt;3; i++)
		{
			if (prevEdge(first-&gt;edges[i], second-&gt;edges[i]))
			{
				return true;
			}
			if (prevEdge(second-&gt;edges[i], first-&gt;edges[i]))
			{
				return false;
			}
		}
		//if both equal
		return false;
	}
	bool operator()(TFace* first, TFace* second) const
	{
		for (int i=0; i&lt;3; i++)
		{
			if (prevEdge(first-&gt;edges[i], second-&gt;edges[i]))
			{
				return true;
			}
			if (prevEdge(second-&gt;edges[i], first-&gt;edges[i]))
			{
				return false;
			}
		}
		//if both equal
		return false;
	}
};

typedef set&lt;TFace*, PrevFace&gt; TFacePtrSet;
typedef set&lt;TFace*&gt; TFacePointerSet;
typedef vector&lt;TFace*&gt; TFacePtrVector;




#endif</pre>
	<pre>¡¡</pre>
	<pre>¡¡</pre>
	<pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: common</span>.<span lang="en-ca">cpp</span></b></font></pre>
	<pre>#include &quot;common.h&quot;
#include &lt;GL/glut.h&gt;
#include &lt;iostream&gt;

using namespace std;

float direction(TPoint* p, TPoint* q, TPoint* r)
{
	return q-&gt;x*r-&gt;y +p-&gt;x*q-&gt;y+p-&gt;y*r-&gt;x - p-&gt;y*q-&gt;x - q-&gt;y*r-&gt;x -p-&gt;x*r-&gt;y;
}


int compPoint(const void* elem1, const void* elem2)
{
	TPoint* ptr1, *ptr2;
	ptr1=(TPoint*)elem1;
	ptr2=(TPoint*)elem2;
	return ptr1-&gt;x-ptr2-&gt;x;
}

void generateRandomPoint(int pointNumber, TPointSet&amp; pointSet)
{
	TPoint point;
	pointSet.clear();
	for (int i=0; i&lt;pointNumber; i++)
	{
		point.x=generateRandomValue();
		point.y=generateRandomValue();
		pointSet.insert(point);
	}
}


void TTriangle::draw()
{
	glBegin(GL_POLYGON);
	for (int i=0; i&lt;3; i++)
	{
		glColor3fv(red);
		glVertex2f(triangle[i].x, triangle[i].y);
	}
	glEnd();
}


void TTriangle::display()
{
	for (int i=0; i&lt;3; i++)
	{
		triangle[i].display();
	}
}

void TPoint::display() const
{
	printf(&quot;[x=%f,y=%f]\n&quot;, x, y);
}

void TPoint::display() 
{
	printf(&quot;[x=%f,y=%f]\n&quot;, x, y);
}

/*
void TMyPointSet::display()
{
	for (TPointSet::const_iterator it=pointSet.begin(); it!=pointSet.end(); it++)
	{
		it-&gt;display();
	}
}

void TMyPointSet::generatePoint(int pointNumber)
{
	TPoint point;
	pointSet.clear();
	for (int i=0; i&lt;pointNumber; i++)
	{
		point.x=generateRandomValue();
		point.y=generateRandomValue();
		pointSet.insert(point);
	}
}
*/

const TPointSet&amp; setCopy(TPointSet&amp; dest, const TPointSet&amp; source)
{
	dest.clear();
	TPointSet::const_iterator it;
	for (it=source.begin(); it!=source.end(); it++)
	{
		dest.insert(*it);
	}
	return dest;
}


void TTriangle::assign(TPoint p1, TPoint p2, TPoint p3)
{
	triangle[0]=p1;
	triangle[1]=p2;
	triangle[2]=p3;
}


bool TTriangle::pointInside(TPoint&amp; point)
{
	float result[3];

	for (int i=0; i&lt;3; i++)
	{
		result[i]=direction(triangle+i, triangle+(i+1)%3, &amp;point);
	}
	
	return result[0]*result[1]&gt;=0&amp;&amp;result[0]*result[2]&gt;=0&amp;&amp;result[1]*result[2]&gt;=0;
}

bool TFace::pointInside(TPoint&amp; point)
{
	float result[3];
	TPoint points[3];
	points[0]=edges[0]-&gt;pairPoint[0];
	points[1]=edges[0]-&gt;pairPoint[1];
	points[2]=edges[2]-&gt;pairPoint[1];
	for (int i=0; i&lt;3; i++)
	{
		result[i]=direction(points+i, points+(i+1)%3, &amp;point);
	}
	
	return result[0]*result[1]&gt;=0&amp;&amp;result[0]*result[2]&gt;=0&amp;&amp;result[1]*result[2]&gt;=0;
}



void TEdge::draw()
{
	glLineWidth(1);
	glBegin(GL_LINES);
	for (int i=0; i&lt;2; i++)
	{
		glColor3fv(color);
		glVertex2f(pairPoint[i].x, pairPoint[i].y);
	}
	glEnd();
}

void TEdge::display()
{
	printf(&quot;display edge\n&quot;);
	for (int i=0; i&lt;2; i++)
	{
		pairPoint[i].display();
	}
}

void TFace::display()
{
	printf(&quot;\n***************display face***********************\n&quot;);
	for (int i=0; i&lt;3; i++)
	{
		edges[i]-&gt;display();
	}
}

//why is that sequence? because first edge must have the no.1, no2 vertex
//the last edge or 3rd edge's second vertex must be last one
void TFace::draw()
{
	glBegin(GL_POLYGON);
		glColor3fv(color);
		glVertex2f(edges[0]-&gt;pairPoint[0].x, edges[0]-&gt;pairPoint[0].y);
		glColor3fv(color);
		glVertex2f(edges[0]-&gt;pairPoint[1].x, edges[0]-&gt;pairPoint[1].y);

		glColor3fv(color);
		glVertex2f(edges[2]-&gt;pairPoint[1].x, edges[2]-&gt;pairPoint[1].y);
	glEnd();
	for (int i=0; i&lt;3; i++)
	{
		edges[i]-&gt;draw();
	}
}




/*
void TMyPointSet::setArray(TPoint* inputArray, int inputNumber)
{
	pointSet.clear();

	pointSet.insert(inputArray, inputArray+inputNumber);
}
*/

float generateRandomValue()
{
	float intPart, floatPart;
	intPart=rand()%MaxIntegerValue * (rand()%2==0?1 : (-1));
	floatPart=(float)rand()/(float)RAND_MAX;
	return intPart+floatPart;
}</pre>
	<pre>¡¡</pre>
	<pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: convex</span>.<span lang="en-ca">h</span></b></font></pre>
  <pre>#ifndef CONVEXHULL_H
#define CONVEXHULL_H

#include &lt;vector&gt;
//#include &quot;DCEL.h&quot;
#include &lt;utility&gt;
#include &lt;GL/glut.h&gt;
#include &quot;common.h&quot;

using namespace std;

struct TConvex;
struct TBoard;

typedef vector&lt;TPointQueue&gt; TPointQueueVector;
typedef pair&lt;TPoint, TPoint&gt; TPointPair;
typedef vector&lt;TPointPair&gt; TPointPairVector;



struct TConvex
{
	TPointSet pointSet;
	void collectVertexUp(TPointQueue&amp;);
	void collectVertexDown(TPointQueue&amp;);
	void addPoint(TPointQueue&amp;, TPoint*);
	int number;
	void generatePoint(int pointNumber);
	void display();
	void convexHull(const TPointSet&amp; inputSet, TPointQueue&amp; pointqueue);
};

struct TNestConvex
{
	static void nestConvex(const TPointSet&amp; pointSet, TPointQueueVector&amp; convexQueue);
	static void triangulate(TPointQueueVector&amp; convexQueue, TPointPairVector&amp; pointPairVector);
	//static void triangulate(TPointQueueVector&amp; convexQueue, TTriangleQueue&amp; triangleQueue);

	static bool triangulate(TPointQueueVector&amp; convexQueue, TBoard&amp; board);
};


struct TBoard
{
	TEdgePtrSet edgePtrSet;
	TFacePtrSet facePtrSet;

	int controlCounter[3];

	void makeEdge(TPoint&amp; p1, TPoint&amp; p2, TEdge&amp; result);
	void makeFace(TPoint&amp; p1, TPoint&amp; p2, TPoint&amp; p3, TFace&amp; result);
	void makeBoard(TTriangleQueue&amp; triangleQueue);
	bool insertFace(TPoint&amp; p1, TPoint&amp; p2, TPoint&amp; p3);
	void clear();
	void draw();
	void drawEdge();
	void drawFace();
	void display();
	void displayFace();
	TFace* linearSearch(TPoint&amp; point);
	//TFace* binarySearch(TPoint&amp; point);
	bool validMove(TFace* face, FaceStatus player, bool justTest=false);

	//bool hasSpace(TFace* face, bool player);

	bool sameColor(TFace* him, FaceStatus player);

	bool isSurrounded(TFace* face, bool player);

	void getNeighbour(TFace* face, TFace* neighbours[3]);

	bool doSearchSpace(TFace* start, FaceStatus player, TFacePointerSet&amp; path);

	void removeEnemy(TFace* face, FaceStatus enemy);

	int countTriangle();
	bool controlBy(TFace* face, FaceStatus&amp; status, TFacePointerSet&amp; path);

};





class TPolygon
{
private:
	int number;
	TPoint* leftMost;
	TPoint* rightMost;
	
public:
	TPoint* ptrArray;
	//TPolygon();
	void createPolygon(int pointNumber, TPointQueue&amp; pointQueue);
	
};



#endif</pre>
	<pre>¡¡</pre>
	<pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: convex</span>.<span lang="en-ca">cpp</span></b></font></pre>
	<pre>#include &lt;iostream&gt;
#include &lt;cmath&gt;
#include &lt;vector&gt;
#include &quot;common.h&quot;
#include &quot;ConvexHull.h&quot;


using namespace std;


//GLenum drawingMode = GL_POINTS;



vector&lt;TPointContext&gt; separateVector;
vector&lt;TPointContext&gt; connectVector;

vector&lt;TPointContext&gt; polygonVector;
TPolygon polygon;

TConvex convex;



void TPolygon::createPolygon(int pointNumber, TPointQueue&amp; pointQueue)
{
	TPointContext pointContext;
	number=pointNumber;
	::generatePoint(pointNumber, ptrArray);
	qsort(ptrArray, number, sizeof(TPoint), compPoint);
	leftMost=ptrArray;
	rightMost=ptrArray+number-1;
	
	for (int i=0; i&lt;number; i++)
	{
		if (direction(leftMost, rightMost, ptrArray+i)&lt;=0)
		{
			pointQueue.push_back(ptrArray[i]);			
		}
		else
		{
			pointQueue.push_front(ptrArray[i]);			
		}		
	}
}

/*
TPolygon::TPolygon()
{
	createPolygon();
}
*/





void TConvex::generatePoint(int pointNumber)
{
	number=pointNumber;
	TPoint point;
	for (int i=0; i&lt;number; i++)
	{
		point.x=generateRandomValue();
		point.y=generateRandomValue();
		pointSet.insert(point);
	}
}

void generatePoint(int pointNumber, TPoint*&amp; ptrArray)
{
	TPointContext pointContext;
	ptrArray=new TPoint[pointNumber];
	for (int i=0; i&lt;pointNumber; i++)
	{
		ptrArray[i].x=generateRandomValue();
		ptrArray[i].y=generateRandomValue();
		pointContext.point=ptrArray[i];
		memcpy(pointContext.pointColor, red, sizeof(TColor));
		separateVector.push_back(pointContext);
		//glutPostRedisplay();			
		glutSwapBuffers();
	}
	//glutPostRedisplay();	
}


void TConvex::addPoint(TPointQueue&amp; pointQueue, TPoint* pointPtr)
{
	TPointQueue::reverse_iterator start, last;
	while (pointQueue.size()&gt;=2)
	{
		start=pointQueue.rbegin();
		last=start;
		start++;		

		if (direction(&amp;(*start), &amp;(*last), pointPtr)&gt;=0)
		{
			pointQueue.pop_back();
		}
		else
		{			
			break;
		}
	}
	pointQueue.push_back(*pointPtr);
}


void TConvex::collectVertexUp(TPointQueue&amp; pointQueue)
{
	TPointSet::iterator it, stop;

	it=pointSet.begin();
	stop=pointSet.end();

	pointQueue.push_back(*it);
	it++;
	pointQueue.push_back(*it);
	it++;
	
	while (it!=stop)
	{
		addPoint(pointQueue, &amp;(*it));
		it++;
	}
}

void printQueue(TPointQueue&amp; pointQueue)
{
	for (TPointQueue::iterator it=pointQueue.begin(); it!=pointQueue.end(); it++)
	{
		it-&gt;display();
	}
}

void TConvex::collectVertexDown(TPointQueue&amp; pointQueue)
{
	TPointSet::reverse_iterator it, stop;

	it=pointSet.rbegin();
	stop=pointSet.rend();

	pointQueue.push_back(*it);
	it++;
	pointQueue.push_back(*it);
	it++;
	
	while (it!=stop)
	{
		addPoint(pointQueue, &amp;(*it));
		it++;
	}
}

void TConvex::display()
{
	for (TPointSet::iterator it=pointSet.begin(); it!=pointSet.end(); it++)
	{
		it-&gt;display();
	}
}

void TConvex::convexHull(const TPointSet&amp; inputSet, TPointQueue&amp; pointQueue)
{
	int upSize, downSize;
	TPointQueue upQueue, downQueue;
	TPointQueue::iterator it;
	TPointSet::const_iterator setIt;
	pointSet.clear();
	pointQueue.clear();

	for (setIt=inputSet.begin(); setIt!=inputSet.end(); setIt++)
	{
		pointSet.insert(*setIt);
	}
	
	if (pointSet.size()&lt;3)
	{
		for (TPointSet::iterator it=pointSet.begin(); it!=pointSet.end(); it++)
		{
			pointQueue.push_back(*it);
		}
	}
	else
	{		
		collectVertexUp(upQueue);
		collectVertexDown(downQueue);
		for (it=upQueue.begin(); it!=upQueue.end(); it++)
		{
			pointQueue.push_back(*it);
		}
	
		pointQueue.pop_back();//remove last
		
		for (it=downQueue.begin(); it!=downQueue.end(); it++)
		{
			pointQueue.push_back(*it);
		}
		pointQueue.pop_back();//remove last

	}
	
}



void TNestConvex::nestConvex(const TPointSet&amp; pointSet, TPointQueueVector&amp; convexQueue)
{
	TConvex convex;
	TPointQueue pointQueue;
	TPointSet inputSet;
	TPointQueue::iterator qIt;

	setCopy(inputSet, pointSet);
	
	while (!inputSet.empty())
	{
		convex.convexHull(inputSet, pointQueue);
		//printf(&quot;get a convex\n&quot;);
		//printQueue(pointQueue);
		convexQueue.push_back(pointQueue);
		for (qIt=pointQueue.begin(); qIt!=pointQueue.end(); qIt++)
		{
			inputSet.erase(*qIt);
		}
	}
}

bool TNestConvex::triangulate(TPointQueueVector&amp; convexQueue, TBoard&amp; board)
{
	TPointQueue outside, inside;
	TTriangle triangle;
	int i, j, k;
	int counter;
	int inCounter, outCounter;
	TPoint outPoint, inPoint, nextIn, p1, p2, p3;
	float result;
	
	if (convexQueue.size()==0)
	{
		return false;
	}
	for (i=0; i&lt;convexQueue.size()-1; i++)
	{
		outside=convexQueue[i];
		inside=convexQueue[i+1];

		j=k=0;
		printf(&quot;\n&quot;);

		outCounter=outside.size();
		if (inside.size()==1)
		{
			inCounter=0;
		}
		else
		{
			inCounter=inside.size();
		}
		while (true)
		{	
			outPoint=outside[j];
			inPoint=inside[k];

			nextIn=inside[(k+1)%inside.size()];

			result=direction(&amp;inPoint, &amp;nextIn, &amp;outPoint);
					
			//here for the case the inside has only ONE vertex, the result is always 0
			//so, we move outside when result is zero
			if (result&gt;0&amp;&amp;inCounter&gt;0)
			{					
				p1=outPoint;
				p2=inPoint;
				k=(k+1)%inside.size();
				p3=inside[k];
				inCounter--;				
			}
			else
			{			
				p1=outPoint;
				p2=inPoint;				
				j=(j+1)%outside.size();			
				p3=outside[j];
				outCounter--;
			}		
			
			//triangle.display();
			///////////////////////////
			if (!board.insertFace(p1, p2, p3))
			{
				///////////////////////////////////////////////////
				printf(&quot;what? and inside convex is*******************\n\n&quot;, result);
				printQueue(inside);
				printf(&quot;\n***********outside convex is:*********************\n&quot;);
				printQueue(outside);
				printf(&quot;\n********************************\n&quot;);
				return false;
			}

			
			if (inCounter==0&amp;&amp;outCounter==0)
			{
				break;
			}		
		}	
	}
	outside=convexQueue.back();

	outPoint=outside[0];
	for (i=2; i&lt;outside.size(); i++)
	{
		p1=outside[0];
		p2=outside[i-1];
		p3=outside[i];
		if (!board.insertFace(p1, p2, p3))
		{
			printf(&quot;what????*****and the convex is::::\n&quot;);
			printQueue(outside);
			printf(&quot;\n**********immediately convex******************\n&quot;);
			printQueue(convexQueue[convexQueue.size()-2]);
			printf(&quot;\n**********immediately convex******************\n&quot;);
			return false;
		}
		//pointPairVector.push_back(make_pair(outPoint, inPoint));
	}
	return true;
}



void TNestConvex::triangulate(TPointQueueVector&amp; convexQueue, TPointPairVector&amp; pointPairVector)
{
	TPointQueue outside, inside;
	int i, j, k;
	int counter;
	bool inDone, outDone;
	TPoint outPoint, inPoint, nextIn, nextOut;
	float result;
	if (convexQueue.size()&lt;=1)
	{
		return;
	}
	for (i=0; i&lt;convexQueue.size()-1; i++)
	{
		outside=convexQueue[i];
		inside=convexQueue[i+1];
		//printf(&quot;outside queue:\n&quot;);
		//printQueue(outside);
		
		//printf(&quot;inside queue:\n&quot;);
		//printQueue(inside);
		

		j=k=0;
		printf(&quot;\n&quot;);
		if (inside.size()&gt;1)
		{
			counter=inside.size()+outside.size();
		}
		else
		{
			counter=outside.size();
		}

		//initially both the leftmost point pair will be stored

	
		while (true)
		{	
			outPoint=outside[j];
			inPoint=inside[k];
			//printf(&quot;outside[%f,%f],inside[%f,%f]\n&quot;, outPoint.x, outPoint.y, inPoint.x, inPoint.y);
			pointPairVector.push_back(make_pair(outPoint, inPoint));
			counter--;
			if (counter==0)
			{
				break;
			}

			nextIn=inside[(k+1)%inside.size()];

			result=direction(&amp;inPoint, &amp;nextIn, &amp;outPoint);
					
			//here for the case the inside has only ONE vertex, the result is always 0
			//so, we move outside when result is zero
			if (result&gt;0)
			{			
				//move outside
				k=(k+1)%inside.size();
				
			}
			else
			{			
				j=(j+1)%outside.size();			
			}	
		
		}
	
	}

	outside=convexQueue.back();

	outPoint=outside[0];
	for (i=2; i&lt;outside.size(); i++)
	{
		inPoint=outside[i];
		//printf(&quot;outside[%f,%f],inside[%f,%f]\n&quot;, outPoint.x, outPoint.y, inPoint.x, inPoint.y);
		pointPairVector.push_back(make_pair(outPoint, inPoint));
	}

}


void TBoard::makeEdge(TPoint&amp; first, TPoint&amp; second, TEdge&amp; result)
{
	if (prevPoint(first, second))
	{
		result.pairPoint[0]=first;
		result.pairPoint[1]=second;
	}
	else
	{
		result.pairPoint[0]=second;
		result.pairPoint[1]=first;
	}
}

void TBoard::makeFace(TPoint&amp; p1, TPoint&amp; p2, TPoint&amp; p3, TFace&amp; result)
{
	TEdge* swap;
	makeEdge(p1, p2, *result.edges[0]);
	makeEdge(p1, p3, *result.edges[1]);
	makeEdge(p2, p3, *result.edges[2]);

	
	//find the smallest edge
	//bubble sorting??
	for (int i=0; i&lt;2; i++)
	{
		for (int j=i+1; j&lt;3; j++)
		{
			if (!prevEdge(result.edges[i], result.edges[j]))
			{
				swap=result.edges[i];
				result.edges[i]=result.edges[j];
				result.edges[j]=swap;
			}
		}
	}
}

void TBoard::clear()
{
	TEdgePtrSet::iterator eit;
	TFacePtrSet::iterator fit;
	for (eit=edgePtrSet.begin(); eit!=edgePtrSet.end(); eit++)
	{
		delete *eit;
	}
	edgePtrSet.clear();
	for (fit=facePtrSet.begin(); fit!=facePtrSet.end(); fit++)
	{
		delete *fit;
	}
	facePtrSet.clear();
}


void TBoard::drawEdge()
{
	TEdgePtrSet::iterator eit;
	for (eit=edgePtrSet.begin(); eit!=edgePtrSet.end(); eit++)
	{
		(*eit)-&gt;draw();
	}
}

void TBoard::drawFace()
{
	TFacePtrSet::iterator fit;

	for (fit=facePtrSet.begin(); fit!=facePtrSet.end(); fit++)
	{
		(*fit)-&gt;draw();
	}
}

void TBoard::draw()
{
	TEdgePtrSet::iterator eit;
	TFacePtrSet::iterator fit;
	
	for (fit=facePtrSet.begin(); fit!=facePtrSet.end(); fit++)
	{
		(*fit)-&gt;draw();
	}
	for (eit=edgePtrSet.begin(); eit!=edgePtrSet.end(); eit++)
	{
		(*eit)-&gt;draw();
	}

}

TFace* TBoard::linearSearch(TPoint&amp; point)
{
	TFacePtrSet::iterator it, stop;	
	for (it=facePtrSet.begin(); it!=facePtrSet.end(); it++)
	{
		if ((*it)-&gt;pointInside(point))
		{
			return *it;
		}
	}
	return NULL;
}

void TBoard::displayFace()
{
	TFacePtrSet::iterator fit;
	printf(&quot;display face set\n&quot;);	
	for (fit=facePtrSet.begin(); fit!=facePtrSet.end(); fit++)
	{
		(*fit)-&gt;display();
	}
}

void TBoard::display()
{
	TEdgePtrSet::iterator eit;
	TFacePtrSet::iterator fit;
	printf(&quot;\n\n*********************************\ndisplay edge set\n&quot;);
	for (eit=edgePtrSet.begin(); eit!=edgePtrSet.end(); eit++)
	{
		(*eit)-&gt;display();
	}

	printf(&quot;display face set\n&quot;);	
	for (fit=facePtrSet.begin(); fit!=facePtrSet.end(); fit++)
	{
		(*fit)-&gt;display();
	}
}


bool TBoard::sameColor(TFace* him, FaceStatus player)
{
	return him-&gt;status==player;

}


//assume they are same color
bool TBoard::doSearchSpace(TFace* face, FaceStatus player, TFacePointerSet&amp; path)
{
	TFace* neighbour[3];
	//TFacePointerSet tempPath;
	TFacePointerSet::iterator it;
	if (path.find(face)!=path.end())
	{
		return false;
	}
	if (face-&gt;status==Empty)
	{
		return true;
	}
	//enemy
	if (face-&gt;status!=player)
	{
		return false;
	}
	//before that, let' place face into path

	path.insert(face);
	//otherwise it must be friend and we search recursively
	//find three neighbours
	getNeighbour(face, neighbour);
	
	for (int i=0; i&lt;3; i++)
	{			
		if (neighbour[i]!=NULL)
		{
			if (path.find(neighbour[i])==path.end())
			{
				//new path
				if (neighbour[i]-&gt;status==Empty)
				{
					return true;
				}

				if (neighbour[i]-&gt;status==player)
				{
					//avoid infinite loop, we check path at beginning, so don't add it here
					//and each sub-path search is independant, so, we give separate path
					/*
					tempPath.clear();
					for (it=path.begin(); it!=path.end(); it++)
					{
						tempPath.insert(*it);
					}
					if (doSearchSpace(neighbour[i], player, tempPath))
					{
						return true;
					}
					*/
					if (doSearchSpace(neighbour[i], player, path))
					{
						return true;
					}

				}
			}
			//else nothing
		}
	}
	//after all, 
	return false;//no chance to survive
}

void TBoard::getNeighbour(TFace* face, TFace* neighbour[3])
{
	for (int i=0; i&lt;3; i++)
	{
		if (face-&gt;edges[i]-&gt;faces[0]==face)
		{
			//doing little testing here
			if (face-&gt;edges[i]-&gt;faces[1]==face)
			{
				printf(&quot;data corrupted! two neighbour are the same!\n&quot;);
				exit(8);
			}
			neighbour[i]=face-&gt;edges[i]-&gt;faces[1];
		}
		else
		{
			//doing little testing here
			if (face-&gt;edges[i]-&gt;faces[1]!=face)
			{
				printf(&quot;data corrupted! face itself is not the neighbour!\n&quot;);
				exit(8);
			}
			neighbour[i]=face-&gt;edges[i]-&gt;faces[0];
		}
	}
}


bool TBoard::controlBy(TFace* face, FaceStatus&amp; status, TFacePointerSet&amp; path)
{
	/*
	TFace* neighbours[3];

	FaceStatus tempStatus;
	
	bool color[2];
	
	
	if (!path.insert(face).second)
	{
		return false;
	}

	color[0]=color[1]=false;

	getNeighbour(*it, neighbours);
	for (int i=0; i&lt;3; i++)
	{
		if (neighbours[i]!=NULL)
		{
			if (neighbours[i]-&gt;status==Empty)
			{
				if (controlBy(neighbours[i], tempStatus, path))
				{



			color[neighbours[i]-&gt;status]=true;
		}
	}
	if (color[Empty]||(color[Red]&amp;&amp;color[Blue]))
	{
		mutualCount++;
	}
	else
	{
		if (color[Red])
		{
*/
	return true;
}

/*
TFace* TBoard::binarySearch(TPoint&amp; point)
{
	TFace face;
	TEdge edges[3];
	int i;
	TFacePtrSet::iterator it;

	for (i=0; i&lt;3; i++)
	{		
		face.edges[i]=edges+i;
	}
	makeFace(point, point, point, face);

	it=facePtrSet.upper_bound(&amp;face);
	

	while (it!=facePtrSet.end())
	{
		if ((*it)-&gt;pointInside(point))
		{
			return *it;
		}
		it++;
	}

	return NULL;
}
*/

int TBoard::countTriangle()
{
	TFacePointerSet path;
	FaceStatus status;
	TFacePtrSet::iterator it;
	for (int i=0; i&lt;3; i++)
	{
		controlCounter[i]=0;
	}
	for (it=facePtrSet.begin(); it!=facePtrSet.end(); it++)
	{
		if ((*it)-&gt;status!=Empty)
		{
			controlCounter[(*it)-&gt;status]++;
		}
		else
		{
			path.clear();
			if (controlBy(*it, status, path))
			{
				controlCounter[status]++;
			}
			else
			{
				printf(&quot;unknown error\n&quot;);
				exit(8);
			}
		}
	}
	return -1;
}

			





bool TBoard::validMove(TFace* face, FaceStatus player, bool justTest)
{
	TFace* neighbour[3];
	TFacePointerSet path;
	FaceStatus enemy;
	int i;
	bool canKill=false;
	bool isValid=false;

	//if non-empty, no good move
	if (face-&gt;status==Red || face-&gt;status==Blue)
	{
		return false;
	}
	
	getNeighbour(face, neighbour);
	//so here, but if we do place our
	//chess piece, can we kill enemy? So, we need to test enemy's life
	//first temparorily change the status of face 

	face-&gt;status=player;
	//now test if enemy will survive
	enemy=(player==Red)?Blue:Red;
	
	for (i=0; i&lt;3; i++)
	{			
		if (neighbour[i]!=NULL)
		{		
			if (neighbour[i]-&gt;status==Empty)
			{
				isValid=true;
				break;
			}

			if (neighbour[i]-&gt;status==player)
			{
				//avoid infinite loop, we check path at beginning, so don't add it here
				//and each sub-path search is independant, so, we give separate path
				path.clear();
				path.insert(face);
			
				if (doSearchSpace(neighbour[i], player, path))
				{
					isValid=true;
					break;
				}			
			}
			//else nothing we ignore
		}
	}



	canKill=false;

	for (i=0; i&lt;3; i++)
	{
		if (neighbour[i]!=NULL)
		{	
			if (neighbour[i]-&gt;status==enemy)
			{
				//avoid infinite loop, we check path at beginning, so don't add it here
				//and each sub-path search is independant, so, we give separate path
				path.clear();
			
				if (!doSearchSpace(neighbour[i], enemy, path))
				{
					canKill=true;
					if (!justTest)
					{
						removeEnemy(neighbour[i], enemy);					
					}
				}			
			}
			//else nothing we ignore
		}
	}
	//always reset original status, because we may just do testing
	face-&gt;status=Empty;
	if (canKill)
	{
		return true;//
	}
	else
	{
		//we need to change status back		
		return isValid;
	}
}

void TBoard::removeEnemy(TFace* face, FaceStatus enemy)
{
	TFace* neighbour[3];
	getNeighbour(face, neighbour);

	face-&gt;status=Empty;
	memcpy(face-&gt;color, playerColor[Empty], sizeof(TColor));
	for (int i=0; i&lt;3; i++)
	{
		if (neighbour[i]!=NULL)
		{
			if (neighbour[i]-&gt;status==enemy)
			{
				neighbour[i]-&gt;status=Empty;
				removeEnemy(neighbour[i], enemy);//recursive
			}
		}
	}
}




bool TBoard::insertFace(TPoint&amp; p1, TPoint&amp; p2, TPoint&amp; p3)
{
	TFace* face;
	TEdge edges[3];
	TEdge* edge;
	int i;
	TColor color;
	TEdgePtrSet::iterator it;
	
	face=new TFace;
	face-&gt;status=Empty;
	for (i=0; i&lt;3; i++)
	{
		//temporary assign these edges
		face-&gt;edges[i]=edges+i;
		//color[i]=((edgePtrSet.size()*rand()%10+3)*2)/40.0;
	}

	makeFace(p1, p2, p3, *face);

	for (i=0; i&lt;3; i++)
	{			
		it=edgePtrSet.find(face-&gt;edges[i]);
		
		if (it==edgePtrSet.end())
		{
			//now replace real allocated edge with those temp edges
			edge=new TEdge;
			
			edge-&gt;faces[0]=face;
			edge-&gt;faces[1]=NULL;//assume unknown
			memcpy(edge-&gt;pairPoint, face-&gt;edges[i]-&gt;pairPoint, sizeof(TPairPoint));
			memcpy(edge-&gt;color, green, sizeof(TColor));
			edgePtrSet.insert(it, edge);
			face-&gt;edges[i]=edge;
		}
		else
		{
			face-&gt;edges[i]=*it;
			//doing a little testing here
			if (face-&gt;edges[i]-&gt;faces[0]==NULL)
			{
				printf(&quot;data corrupted, dangling edge found\n&quot;);
				exit(8);
			}
			if (face-&gt;edges[i]-&gt;faces[1]!=NULL)
			{
				printf(&quot;\n******************************************\n&quot;);
				printf(&quot;\n\n**********\ndata corrupted, one edge attached with three faces\n&quot;);
				printf(&quot;\nand here is the repeat edge\n&quot;);
				face-&gt;edges[i]-&gt;display();

				printf(&quot;\n************show us the face problem***************\n&quot;);
				face-&gt;display();

				printf(&quot;\n*****************and all faces are**********************\n&quot;);
				displayFace();
				return false;
				//exit(5);
			}
			face-&gt;edges[i]-&gt;faces[1]=face;
		}

		//face-&gt;edges[j]=new TEdge;
	}
	//now add the new face into face set
	memcpy(face-&gt;color, beige, sizeof(TColor));
	facePtrSet.insert(face);
	return true;
	//printf(&quot;now display the board\n&quot;);
	//displayFace();
}


void TBoard::makeBoard(TTriangleQueue&amp; triangleQueue)
{
	TFace* face;
	TEdge edges[3];
	TEdge* edge;
	int i, j;
	TColor color;
	TEdgePtrSet::iterator it;
	for (i=0; i&lt;triangleQueue.size(); i++)
	{
		face=new TFace;
		for (j=0; j&lt;3; j++)
		{
			//temporary assign these edges
			face-&gt;edges[j]=edges+j;
			//color[j]=i*30+j*40;
		}
	
		makeFace(triangleQueue[i].triangle[0], triangleQueue[i].triangle[1],
			triangleQueue[i].triangle[2], *face);


		for (j=0; j&lt;3; j++)
		{			
			it=edgePtrSet.find(face-&gt;edges[j]);
			
			if (it==edgePtrSet.end())
			{
				//now replace real allocated edge with those temp edges
				edge=new TEdge;
				
				edge-&gt;faces[0]=face;
				edge-&gt;faces[1]=NULL;//assume unknown
				memcpy(edge-&gt;pairPoint, face-&gt;edges[j]-&gt;pairPoint, sizeof(TPairPoint));
				memcpy(edge-&gt;color, green, sizeof(TColor));
				edgePtrSet.insert(it, edge);
				face-&gt;edges[j]=edge;
			}
			else
			{
				face-&gt;edges[j]=*it;
				//doing a little testing here
				if (face-&gt;edges[j]-&gt;faces[0]==NULL)
				{
					printf(&quot;data corrupted, dangling edge found\n&quot;);
					exit(8);
				}
				if (face-&gt;edges[j]-&gt;faces[1]!=NULL)
				{
					printf(&quot;\n******************************************\n&quot;);
					printf(&quot;\n\n**********\ndata corrupted, one edge attached with three faces\n&quot;);
					printf(&quot;\nand here is the repeat edge\n&quot;);
					face-&gt;edges[j]-&gt;display();

					printf(&quot;\n************show us the face problem***************\n&quot;);
					face-&gt;display();

					printf(&quot;\n*****************and all faces are**********************\n&quot;);
					displayFace();
					continue;
					//exit(5);
				}
				face-&gt;edges[j]-&gt;faces[1]=face;
			}

			//face-&gt;edges[j]=new TEdge;
		}
		//now add the new face into face set
		memcpy(face-&gt;color, color, sizeof(TColor));
		facePtrSet.insert(face);
		//printf(&quot;now display the board\n&quot;);
		//displayFace();
	}
}

		









</pre>
	<pre>
		


<font size="3" color="#FF0000"><b><span lang="en-ca">file name: main</span>.<span lang="en-ca">cpp</span></b></font>
</pre>
	<pre>/*********************************************************
nest convex:
1000: 1.3sec
5000: 5sec
10000: 16sec

triangulation:
1000: 0.3sec
5000: 1.3sec
10000: 1.6sec

*********************************************************/


#include &quot;common.h&quot;
#include &quot;ConvexHull.h&quot;
//#include &lt;windows.h&gt;

#include &lt;GL/glut.h&gt;
#include &lt;vector&gt;
#include &lt;deque&gt;
#include &lt;utility&gt;
#include &lt;ctime&gt;


using namespace std;

extern vector&lt;TPointContext&gt; separateVector;
extern vector&lt;TPointContext&gt; connectVector;
TPointPairVector pairVector;

TTriangleQueue triangleQueue;
extern TConvex convex;
extern TPolygon polygon;


bool gameEnd=false;

FaceStatus player=Red;

TPointQueue pointQueue;
TPointQueueVector convexQueueVector;
TPointSet pointSet;
TPointPairVector pointPairVector;

TFacePtrVector facePtrVector;

TBoard board;

bool showBoard=true;

TFacePtrSet::iterator fit;

void outputMessage();
void output(int x, int y, char *str);

void drawAxis()
{
	glLineWidth(1);
	glBegin(GL_LINES);
	glColor3fv(beige);
	glVertex2f(MaxIntegerValue,0);
	glColor3fv(red);
	glVertex2f(-MaxIntegerValue, 0);
	glEnd();

	glBegin(GL_LINES);
	glColor3fv(beige);
	glVertex2f(0, -MaxIntegerValue);
	glColor3fv(red);
	glVertex2f(0, MaxIntegerValue);
	glEnd();

}

void clearAll()
{
	separateVector.clear();
	connectVector.clear();
	pairVector.clear();
	convexQueueVector.clear();
	pointPairVector.clear();
	pairVector.clear();
	triangleQueue.clear();
	player=Red;
	gameEnd=false;
}


int index=0;

void displayMenu()
{
	printf(&quot;\n***********************************************\n&quot;);
	printf(&quot;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;Welcome To TrianGO&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;\n&quot;);
	printf(&quot;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;A Game of GO on Triangle&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;\n&quot;);
	printf(&quot;Operation:\n\
a)	create random points: by right click mouse or press 'n'; \n\
b)	create nested convex hull:  by press 'n'. \n\
c)	create triangulation: press 't'. \n\
d)	start playing: left click triangles in chess board. \n\
	restart: press 'a' to clear everything. \n\
	show menu: press 'm' \n\
	exit: press 'esc'\n&quot;);

	printf(&quot;\n***********************************************\n&quot;);
}

void displayCallback()
{
	int separateNumber, connectNumber, pairNumber, i, j;
	glClearColor(1,1,0,1);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	//separateNumber=separateVector.size();
	separateNumber=separateVector.size();
	connectNumber=connectVector.size();
	pairNumber=pairVector.size();

	//connectNumber=0;

	glPointSize(5.0);
	glLineWidth(5);

	if (connectNumber&gt;0)
	{
		
		glBegin(GL_LINE_LOOP);
		for (i=0; i&lt;connectNumber; i++)
		{
			glColor3fv(connectVector[i].pointColor);
			glVertex2f(connectVector[i].point.x, connectVector[i].point.y);
			//printf(&quot;x=%f, y=%f\n&quot;, connectVector[i].pointPtr-&gt;x, 
			//	connectVector[i].pointPtr-&gt;y);
			
		}
		glEnd();
	
		glBegin(GL_POINTS);
		for (i=0; i&lt;connectNumber; i++)
		{
			glColor3fv(connectVector[i].pointColor);
			glVertex2f(connectVector[i].point.x, connectVector[i].point.y);
			
			//printf(&quot;x=%f, y=%f\n&quot;, separateVector[i].pointPtr-&gt;x, separateVector[i].pointPtr-&gt;y);
		}
		glEnd();
	
	}
	if (separateNumber&gt;0)
	{
		glBegin(GL_POINTS);
		for (i=0; i&lt;separateNumber; i++)
		{
			glColor3fv(separateVector[i].pointColor);
			glVertex2f(separateVector[i].point.x, separateVector[i].point.y);
			
			//printf(&quot;x=%f, y=%f\n&quot;, separateVector[i].pointPtr-&gt;x, separateVector[i].pointPtr-&gt;y);
		}
		glEnd();
	}
	if (pairNumber&gt;0)
	{
		for (i=0; i&lt;pairNumber; i++)
		{
			glBegin(GL_LINES);
			glColor3fv(blue);
			glVertex2f(pairVector[i].first.x, pairVector[i].first.y);
			glColor3fv(blue);
			glVertex2f(pairVector[i].second.x, pairVector[i].second.y);
			
			glEnd();
		}
	}

	for (i=0; i&lt;convexQueueVector.size(); i++)
	{
		glBegin(GL_LINE_LOOP);
		for (j=0; j&lt;convexQueueVector[i].size(); j++)
		{			
			glColor3fv(red);
						
			glVertex2f(convexQueueVector[i][j].x, convexQueueVector[i][j].y);			
		}
		glEnd();		
	}



	if (triangleQueue.size()&gt;0)
	{
		triangleQueue[index].draw();
	}

	//board.draw();
	if (showBoard)
	{
		/*
		for (i=0; i&lt;facePtrVector.size(); i++)
		{
			facePtrVector[i]-&gt;draw();
		}
		*/
		board.drawFace();

	}

	//board.drawEdge();


	//drawAxis();

	outputMessage();

	glutSwapBuffers();
	//glutPostRedisplay();
}

void outputMessage()
{
	TFacePtrSet::iterator it;
	const int CharHeight=15;
	char msg[20];
	int winner;
	int counter[3]={0};
	static char* playerName[4]={&quot;RED&quot;, &quot;BLUE&quot;, &quot;EMPTY&quot;, &quot;NOBODY&quot;};
	int currentx, currenty;


	for (it=board.facePtrSet.begin(); it!=board.facePtrSet.end(); it++)
	{
		counter[(*it)-&gt;status]++;
	}

	currentx=-winSize_width/2+2;
	currenty=winSize_height/2-CharHeight;

	sprintf(msg, &quot;[PLAYER] %s&quot;, playerName[player]);
	output(currentx, currenty, msg);
	currenty-=CharHeight;

	for (int i=0; i&lt;3; i++)
	{		
		sprintf(msg, &quot;[%s] %d&quot;, playerName[i], counter[i]);
		output(currentx, currenty, msg);
		currenty-=CharHeight;
	}
	if (gameEnd)
	{
		if (counter[Red]&gt;counter[Blue])
		{
			winner=Red;
		}
		else
		{
			if (counter[Red]&lt;counter[Blue])
			{
				winner=Blue;
			}
			else
			{
				winner=3;
			}
		}
		sprintf(msg, &quot;[WINNER] %s!&quot;, playerName[winner]);
		output(currentx, currenty, msg);
	}
}

void output(int x, int y, char *str)
{
	int len, i;
	glColor3fv(red);
	glRasterPos2f(x, y);
	len = (int) strlen(str);
	for (i = 0; i &lt; len; i++)
	{	
		glutBitmapCharacter(GLUT_BITMAP_8_BY_13 , str[i]);
	}
}




void keyboardCallback(unsigned char key, int x, int y)
{
	//int i;
	//bool noProblem=false;
	TPointContext pointContext;
	unsigned long int startSec;

	TPointPair pointPair;
	TPointQueue::iterator it;
	TPointSet::iterator setIt;
	TFacePtrSet::iterator fit;
	//float coord[4];
	switch (key)
	{
	case 27:
		exit(0);
		break;
	case 's':
		//convex.generatePoint(10);
		generateRandomPoint(10, pointSet);
		for (setIt=pointSet.begin(); setIt!=pointSet.end(); setIt++)
		{
			pointContext.point=*setIt;
			memcpy(pointContext.pointColor, red, sizeof(TColor));
		
			separateVector.push_back(pointContext);
			
		}	
		/*
		for (setIt=convex.pointSet.begin(); setIt!=convex.pointSet.end(); setIt++)
		{
			memcpy(pointContext.pointColor, red, sizeof(TColor));
			pointContext.point=*setIt;
			separateVector.push_back(pointContext);
		}
		*/
		break;
	case 'm':
		displayMenu();
		break;
	case 'c':		
		convex.convexHull(pointSet, pointQueue);	
		for (it=pointQueue.begin(); it!=pointQueue.end(); it++)
		{
			memcpy(pointContext.pointColor, green, sizeof(TColor));
			pointContext.point=*it;
			connectVector.push_back(pointContext);
			
		}
		break;

	case 'p':
		pointQueue.clear();
		polygon.createPolygon(11, pointQueue);
		for (it=pointQueue.begin(); it!=pointQueue.end(); it++)
		{
			memcpy(pointContext.pointColor, blue, sizeof(TColor));
			pointContext.point=*it;
			connectVector.push_back(pointContext);
			//glutPostRedisplay();
		}
		break;
	case 'e':
		separateVector.clear();
		connectVector.clear();
		break;
	case 'n':
		if (pointSet.size()==0)
		{
			generateRandomPoint(8, pointSet);
		}
		convexQueueVector.clear();
		startSec=glutGet(GLUT_ELAPSED_TIME);
		TNestConvex::nestConvex(pointSet, convexQueueVector);
		startSec=glutGet(GLUT_ELAPSED_TIME)-startSec;
		//printf(&quot;nest convex time takes %d milli seconds\n&quot;, startSec);

		//TNestConvex::triangulate(convexQueueVector, pointPairVector);

		//pairVector.insert(pairVector.end(), pointPairVector.begin(), pointPairVector.end());

		break;
	case 'r':
		startSec=glutGet(GLUT_ELAPSED_TIME);
		TNestConvex::triangulate(convexQueueVector, pointPairVector);
		startSec=glutGet(GLUT_ELAPSED_TIME)-startSec;
		//printf(&quot;triangulation time takes %d milli seconds\n&quot;, startSec);
		pairVector.insert(pairVector.end(), pointPairVector.begin(), pointPairVector.end());
		break;
	case 'a':
		separateVector.clear();
		connectVector.clear();
		pairVector.clear();
		convexQueueVector.clear();
		pointPairVector.clear();
		pointSet.clear();
		triangleQueue.clear();
		board.clear();
		displayMenu();
		break;

	case 't':
		//triangleQueue.clear();
		startSec=glutGet(GLUT_ELAPSED_TIME);
		showBoard=TNestConvex::triangulate(convexQueueVector, board);

		startSec=glutGet(GLUT_ELAPSED_TIME)-startSec;
		//printf(&quot;triangulation time takes %d milli seconds\n&quot;, startSec);
		/*
		for (i=0; i&lt;triangleQueue.size(); i++)
		{
			printf(&quot;triangle retrieved\n&quot;);
			triangleQueue[i].display();
		}
		*/
		if (showBoard)
		{
			//board.makeBoard(triangleQueue);
			
		
			clearAll();
		}
		
		break;


	case 'g':
		index=(index+1)%triangleQueue.size();
		break;
	

	}
	glutPostRedisplay();
}

void reshapeCallback(int width, int height)
{
	glutPostRedisplay();
}


void init()
{
	displayMenu();
	glShadeModel(GL_FLAT);
	//glShadeModel(GL_SMOOTH);
	gluOrtho2D((float)winSize_width/-2.0, (float)winSize_width/2.0, 
		(float)winSize_height/-2.0, (float)winSize_height/2.0);
}


void mouseCallback(int button, int state, int x, int y)
{
	TPoint point;
	TFacePtrSet::iterator it;
	TFace* face;
	FaceStatus enemy;
	//printf(&quot;coord[x=%d,y=%d]\n&quot;, x, y);
	point.x=x-winSize_width/2;
	point.y=winSize_height/2-y;
	TPointContext pointContext;

	if (button==GLUT_LEFT_BUTTON &amp;&amp;state==GLUT_DOWN)
	{
		face=board.linearSearch(point);
		if (face!=NULL)
		{
			//showBoard=false;
			//board.checkColor(face, redPlayer);
			if (board.validMove(face, player))
			{
				memcpy(face-&gt;color, playerColor[player], sizeof(TColor));
				face-&gt;status=player;
				enemy=(player==Red)?Blue:Red;
				
				//but before that, let's see if it is end of game.
				gameEnd=true;
				
				for (it=board.facePtrSet.begin(); it!=board.facePtrSet.end(); it++)
				{
					if (board.validMove(*it, enemy, true))
					{
						gameEnd=false;
						break;
					}
				}
				player=(player==Red)?Blue:Red;
				glutPostRedisplay();
			}		
		}

	}
	if (button==GLUT_RIGHT_BUTTON &amp;&amp;state==GLUT_DOWN)
	{
		pointSet.insert(point);
		pointContext.point=point;
		memcpy(pointContext.pointColor, red, sizeof(TColor));
		separateVector.push_back(pointContext);
		glutPostRedisplay();
	}
}




int main(int argc, char** argv)
{
	srand(time(0));
	glutInit(&amp;argc, argv);
	glutInitWindowPosition(winPos_x, winPos_y);
	glutInitWindowSize(winSize_width, winSize_height);	
	glutInitDisplayMode(GLUT_RGBA|GLUT_ALPHA|GLUT_DOUBLE);
	glutCreateWindow(windowTitle);

	glutMouseFunc(mouseCallback);
	glutDisplayFunc(displayCallback);
	glutKeyboardFunc(keyboardCallback);
	glutReshapeFunc(reshapeCallback);

	init();





	//printf(&quot;before convex hull\n&quot;);
	//convex.display();

	//convex.convexHull(pointSet);
	//printf(&quot;after convex hull\n&quot;);
	//pointSet.display();
	//glutPostRedisplay();
	//glutShowWindow();

	glutMainLoop();

	return 0;
}</pre>
	<pre>


</pre>
</div>

<pre><span lang="en-ca">			</span></pre>

<pre><span lang="en-ca">				</span> <a href="game24.htm"><img src="picture/back.gif" style="border: medium none" alt="back.gif (341 bytes)" width="32" height="35"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="index.htm"><img src="picture/up.gif" style="border: medium none" alt="up.gif (335 bytes)" width="35" height="32"></a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="picture/next.gif" style="border: medium none" alt="next.gif (337 bytes)" width="32" height="35"> </pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                   
&nbsp;&nbsp;&nbsp;</p>

</body>

</html>