Remove more CRs.
[ttt.git] / ver1 / ttt.c
index 80efd0878ee78591a7966e9df1bb5dc568cac040..541ba80b44b1973e46d0d216e6f8bfc289c7cb9d 100644 (file)
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <memory.h>\r
-#include <time.h>\r
-#include "ttt.h"\r
-\r
-SQUARE g_sComputerPlays = O_MARK;             // what side comp plays\r
-unsigned int g_uPly = 0;\r
-MOVE g_mvBest = { 0 };\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  SquareContentsToChar\r
-//\r
-// Synopsis:  Helper function for DrawBoard\r
-//\r
-// Arguments: IN SQUARE s - a square to return a char to represent\r
-//            \r
-// Returns:   char - character representing square\r
-//\r
-//+----------------------------------------------------------------------------\r
-char SquareContentsToChar(IN SQUARE s)\r
-{\r
-    static char c;\r
-    switch(s)\r
-    {\r
-        case X_MARK:\r
-            c = 'X';\r
-            break;\r
-        case O_MARK:\r
-            c = 'O';\r
-            break;\r
-        case EMPTY:\r
-            c = '_';\r
-            break;\r
-        default:\r
-            ASSERT(FALSE);\r
-            c = '?';\r
-            break;\r
-    }\r
-    return(c);\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  DrawBoard\r
-//\r
-// Synopsis:  Draw the board\r
-//\r
-// Arguments: IN POSITION *p - pointer to a position whose board to draw\r
-//            \r
-// Returns:   void\r
-//\r
-//+----------------------------------------------------------------------------\r
-void DrawBoard(IN POSITION *p)\r
-{\r
-    COORD x, y;\r
-\r
-    for (y = 0; y < BOARD_SIZE; y++)\r
-    {\r
-        for (x = 0; x < BOARD_SIZE; x++)\r
-        {\r
-            printf("%c ", SquareContentsToChar(p->sBoard[y][x]));\r
-        }\r
-        printf("\n");\r
-    }\r
-    ASSERT(X_OR_O(p->sWhoseTurn));\r
-    printf("\n%c to move.\n", SquareContentsToChar(p->sWhoseTurn));\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  ClearBoard\r
-//\r
-// Synopsis:  Clear the board\r
-//\r
-// Arguments: IN OUT POSITION *p - pointer to position whose board to clear\r
-//            \r
-// Returns:   void\r
-//\r
-//+----------------------------------------------------------------------------\r
-void ClearBoard(IN OUT POSITION *p)\r
-{\r
-    memset(p->sBoard, 0, sizeof(p->sBoard));\r
-    p->sWhoseTurn = X_MARK;                   // x's go first\r
-    p->uNumEmpty = (BOARD_SIZE * BOARD_SIZE);\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  IsLegalMove\r
-//\r
-// Synopsis:  Determine if a given move is legal on a given board\r
-//\r
-// Arguments: IN POSITION *p - the board to play the move on\r
-//            IN MOVE *m - the move in question\r
-//            \r
-// Returns:   BOOL - TRUE if it's legal, FALSE otherwise\r
-//\r
-//+----------------------------------------------------------------------------\r
-BOOL IsLegalMove(IN POSITION *p, IN MOVE *m)\r
-{\r
-    if ((m->cVpos < BOARD_SIZE) && (m->cHpos < BOARD_SIZE))\r
-    {\r
-        if (IS_SQUARE_EMPTY(p->sBoard[m->cVpos][m->cHpos]))\r
-        {\r
-            return(TRUE);\r
-        }\r
-    }\r
-    return(FALSE);\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  GetHumanMove\r
-//\r
-// Synopsis:  Ask the human for a move\r
-//\r
-// Arguments: IN POSITION *p - the current board\r
-//            OUT MOVE *m - the move the human made; this struct is populated\r
-//                      as a side-effect of this function.\r
-//            \r
-// Returns:   void* (populates the move struct)\r
-//\r
-//+----------------------------------------------------------------------------\r
-void GetHumanMove(IN POSITION *p, OUT MOVE *m)\r
-{\r
-    unsigned int x;\r
-\r
-    do\r
-    {\r
-        printf("Enter your move number: ");\r
-        scanf("%u", &x);\r
-        \r
-        m->cHpos = NUM_TO_HPOS(x);\r
-        m->cVpos = NUM_TO_VPOS(x);\r
-        m->sMark = OPPOSITE_MARK(g_sComputerPlays);\r
-    }\r
-    while(FALSE == IsLegalMove(p, m));\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  GameOver\r
-//\r
-// Synopsis:  Is the game over? \r
-//\r
-// Arguments: IN POSITION *p - the board\r
-//            OUT SQUARE *psWhoWon - who won the game (if it's over)\r
-//            \r
-// Returns:   TRUE if the game is over.  Also sets psWhoWon telling\r
-//            which side one if the game is over.  This also serves\r
-//            as a very simple evaluation routine for the search.\r
-// \r
-//            FALSE if the game is not over.\r
-//\r
-//+----------------------------------------------------------------------------\r
-BOOL GameOver(IN POSITION *p, OUT SQUARE *psWhoWon)\r
-{\r
-    int iSum;\r
-    COORD x, y;\r
-\r
-    for (x = 0; x < BOARD_SIZE; x++)\r
-    {\r
-        iSum = 0;\r
-\r
-        for (y = 0; y < BOARD_SIZE; y++)\r
-        {\r
-            iSum += p->sBoard[x][y];\r
-        }\r
-        if (abs(iSum) == BOARD_SIZE) goto winner;\r
-    }\r
-\r
-    for (y = 0; y < BOARD_SIZE; y++)\r
-    {\r
-        iSum = 0;\r
-\r
-        for (x = 0; x < BOARD_SIZE; x++)\r
-        {\r
-            iSum += p->sBoard[x][y];\r
-        }\r
-        if (abs(iSum) == BOARD_SIZE) goto winner;\r
-    }\r
-\r
-    iSum = 0;\r
-    for (x = 0; x < BOARD_SIZE; x++)\r
-    {\r
-        iSum += p->sBoard[x][x];\r
-    }\r
-    if (abs(iSum) == BOARD_SIZE) goto winner;\r
-\r
-    iSum = 0;\r
-    for (x = 0; x < BOARD_SIZE; x++)\r
-    {\r
-        iSum += p->sBoard[x][(BOARD_SIZE - 1 - x)];\r
-    }\r
-    if (abs(iSum) == BOARD_SIZE) goto winner;\r
-\r
-    *psWhoWon = EMPTY;\r
-    if (p->uNumEmpty == 0)\r
-    {\r
-        return(TRUE);\r
-    }\r
-    else\r
-    {\r
-        return(FALSE);\r
-    }\r
-\r
- winner:\r
-    *psWhoWon = (iSum / BOARD_SIZE);\r
-    ASSERT(X_OR_O(*psWhoWon));\r
-    return(TRUE);\r
-}\r
-\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  MakeMove\r
-//\r
-// Synopsis:  Make a move on a board  \r
-//\r
-// Arguments: IN OUT POSITION *p - the board\r
-//            IN MOVE *m - the move\r
-//            \r
-// Returns:   void\r
-//\r
-//+----------------------------------------------------------------------------\r
-void MakeMove(IN OUT POSITION *p, IN MOVE *m)\r
-{\r
-    if (TRUE == IsLegalMove(p, m))\r
-    {\r
-        ASSERT(p->sBoard[m->cVpos][m->cHpos] == EMPTY);\r
-        p->sBoard[m->cVpos][m->cHpos] = m->sMark;\r
-        p->uNumEmpty--;\r
-        ASSERT(p->uNumEmpty < (BOARD_SIZE * BOARD_SIZE));\r
-        p->sWhoseTurn = OPPOSITE_MARK(p->sWhoseTurn);\r
-        g_uPly++;\r
-        ASSERT(g_uPly > 0);\r
-    }\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  UnmakeMove\r
-//\r
-// Synopsis:  The opposite of MakeMove\r
-//\r
-// Arguments: IN OUT POSITION *p - the board\r
-//            IN MOVE *m - the move to undo\r
-//            \r
-// Returns:   void\r
-//\r
-//+----------------------------------------------------------------------------\r
-void UnmakeMove(IN OUT POSITION *p, IN MOVE *m)\r
-{\r
-    if (p->sBoard[m->cVpos][m->cHpos] == m->sMark)\r
-    {\r
-        p->sBoard[m->cVpos][m->cHpos] = EMPTY;\r
-        p->uNumEmpty++;\r
-        ASSERT(p->uNumEmpty > 0);\r
-        ASSERT(p->uNumEmpty <= (BOARD_SIZE * BOARD_SIZE));\r
-        p->sWhoseTurn = OPPOSITE_MARK(p->sWhoseTurn);\r
-        ASSERT(g_uPly > 0);\r
-        g_uPly--;\r
-    }\r
-}\r
-\r
-\r
-int\r
-SimpleSearch(IN POSITION *p)\r
-{\r
-    SQUARE sWhoWon;\r
-    SQUARE s;\r
-    MOVE mv;\r
-    int iScore;\r
-    int iBestScore = -INFINITY;\r
-\r
-    //\r
-    // Evaluate this position\r
-    //\r
-    if (TRUE == GameOver(p, &sWhoWon))\r
-    {\r
-        if (sWhoWon == p->sWhoseTurn)\r
-        {\r
-            return(+INFINITY);\r
-        }\r
-        else if (sWhoWon == (p->sWhoseTurn * -1))\r
-        {\r
-            return(-INFINITY);\r
-        }\r
-        return(DRAWSCORE);\r
-    }\r
-\r
-    //\r
-    // No one won, game is still going.  Evaluate every\r
-    // possible move from here.\r
-    //\r
-    ASSERT(p->uNumEmpty > 0);\r
-    for (s = 0; s < (BOARD_SIZE * BOARD_SIZE); s++)\r
-    {\r
-        mv.cHpos = NUM_TO_HPOS(s);\r
-        mv.cVpos = NUM_TO_VPOS(s);\r
-        mv.sMark = p->sWhoseTurn;\r
-\r
-        if (IsLegalMove(p, &mv))\r
-        {\r
-            MakeMove(p, &mv);\r
-\r
-            iScore = -1 * SimpleSearch(p);\r
-            if (iScore > iBestScore)\r
-            {\r
-                iBestScore = iScore;\r
-                if (g_uPly == 1)\r
-                {\r
-                    g_mvBest = mv;\r
-                }\r
-            }\r
-\r
-            UnmakeMove(p, &mv);\r
-        }\r
-    }\r
-    return(iBestScore);\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  SearchForComputerMove\r
-//\r
-// Synopsis:  Use our sophisticated search algorithm to find a computer\r
-//            move\r
-//\r
-// Arguments: IN POSITION *p - the current board\r
-//            OUT MOVE *m - the move the computer chooses; this move struct\r
-//                      is populated as a side-effect of this function.\r
-//            \r
-// Returns:   void* (populates move struct)\r
-//\r
-//+----------------------------------------------------------------------------\r
-void SearchForComputerMove(IN POSITION *p, OUT MOVE *m)\r
-{\r
-    unsigned int x;\r
-\r
-#if defined(PLAY_RANDOMLY)\r
-    do\r
-    {\r
-        x = rand() % (BOARD_SIZE * BOARD_SIZE);\r
-        m->cHpos = NUM_TO_HPOS(x);\r
-        m->cVpos = NUM_TO_VPOS(x);\r
-        m->sMark = g_sComputerPlays;\r
-    }\r
-    while(FALSE == IsLegalMove(p, m));\r
-#elif defined(SIMPLE_SEARCH)\r
-    g_uPly = 0;\r
-    SimpleSearch(p);\r
-    *m = g_mvBest;\r
-#else\r
-    #error "No Search Strategy Defined"\r
-#endif\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function:  main\r
-//\r
-// Synopsis:  The program entry point and main game loop.\r
-//\r
-// Arguments: void\r
-//            \r
-// Returns:   int\r
-//\r
-//+----------------------------------------------------------------------------\r
-int main(void)\r
-{\r
-    POSITION p;\r
-    MOVE mv;\r
-    SQUARE sResult;\r
-\r
-    //\r
-    // Randomize: the random numbers returned by rand() will be based on\r
-    // the system clock when the program starts up.\r
-    //\r
-    srand(time(0));\r
-\r
-    //\r
-    // Setup the board and draw it once.\r
-    //\r
-    ClearBoard(&p);\r
-    DrawBoard(&p);\r
-\r
-    //\r
-    // Main game loop\r
-    //\r
-    do\r
-    {\r
-        // \r
-        // See whose turn it is -- the human's or the computers -- and\r
-        // get a move from whoever's turn it is.\r
-        //\r
-        if (p.sWhoseTurn == g_sComputerPlays)\r
-        {\r
-            SearchForComputerMove(&p, &mv);\r
-        }\r
-        else\r
-        {\r
-            GetHumanMove(&p, &mv);\r
-        }\r
-\r
-        //\r
-        // Make the move on the board and draw the board again.\r
-        //\r
-        MakeMove(&p, &mv);\r
-        DrawBoard(&p);\r
-    }\r
-    while(FALSE == GameOver(&p, &sResult));\r
-\r
-    //\r
-    // If we get here the game is over... see what happened.\r
-    //\r
-    switch(sResult)\r
-    {\r
-        case X_MARK:\r
-            printf("\nX's win.\n");\r
-            break;\r
-        case O_MARK:\r
-            printf("\nO's win.\n");\r
-            break;\r
-        default:\r
-            printf("Tie (what a surprise)\n");\r
-            break;\r
-    }\r
-\r
-    exit(0);\r
-}\r
-\r
+#include <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+#include <time.h>
+#include "ttt.h"
+
+SQUARE g_sComputerPlays = O_MARK;             // what side comp plays
+unsigned int g_uPly = 0;
+MOVE g_mvBest = { 0 };
+
+//+----------------------------------------------------------------------------
+//
+// Function:  SquareContentsToChar
+//
+// Synopsis:  Helper function for DrawBoard
+//
+// Arguments: IN SQUARE s - a square to return a char to represent
+//            
+// Returns:   char - character representing square
+//
+//+----------------------------------------------------------------------------
+char SquareContentsToChar(IN SQUARE s)
+{
+    static char c;
+    switch(s)
+    {
+        case X_MARK:
+            c = 'X';
+            break;
+        case O_MARK:
+            c = 'O';
+            break;
+        case EMPTY:
+            c = '_';
+            break;
+        default:
+            ASSERT(FALSE);
+            c = '?';
+            break;
+    }
+    return(c);
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:  DrawBoard
+//
+// Synopsis:  Draw the board
+//
+// Arguments: IN POSITION *p - pointer to a position whose board to draw
+//            
+// Returns:   void
+//
+//+----------------------------------------------------------------------------
+void DrawBoard(IN POSITION *p)
+{
+    COORD x, y;
+
+    for (y = 0; y < BOARD_SIZE; y++)
+    {
+        for (x = 0; x < BOARD_SIZE; x++)
+        {
+            printf("%c ", SquareContentsToChar(p->sBoard[y][x]));
+        }
+        printf("\n");
+    }
+    ASSERT(X_OR_O(p->sWhoseTurn));
+    printf("\n%c to move.\n", SquareContentsToChar(p->sWhoseTurn));
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:  ClearBoard
+//
+// Synopsis:  Clear the board
+//
+// Arguments: IN OUT POSITION *p - pointer to position whose board to clear
+//            
+// Returns:   void
+//
+//+----------------------------------------------------------------------------
+void ClearBoard(IN OUT POSITION *p)
+{
+    memset(p->sBoard, 0, sizeof(p->sBoard));
+    p->sWhoseTurn = X_MARK;                   // x's go first
+    p->uNumEmpty = (BOARD_SIZE * BOARD_SIZE);
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:  IsLegalMove
+//
+// Synopsis:  Determine if a given move is legal on a given board
+//
+// Arguments: IN POSITION *p - the board to play the move on
+//            IN MOVE *m - the move in question
+//            
+// Returns:   BOOL - TRUE if it's legal, FALSE otherwise
+//
+//+----------------------------------------------------------------------------
+BOOL IsLegalMove(IN POSITION *p, IN MOVE *m)
+{
+    if ((m->cVpos < BOARD_SIZE) && (m->cHpos < BOARD_SIZE))
+    {
+        if (IS_SQUARE_EMPTY(p->sBoard[m->cVpos][m->cHpos]))
+        {
+            return(TRUE);
+        }
+    }
+    return(FALSE);
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:  GetHumanMove
+//
+// Synopsis:  Ask the human for a move
+//
+// Arguments: IN POSITION *p - the current board
+//            OUT MOVE *m - the move the human made; this struct is populated
+//                      as a side-effect of this function.
+//            
+// Returns:   void* (populates the move struct)
+//
+//+----------------------------------------------------------------------------
+void GetHumanMove(IN POSITION *p, OUT MOVE *m)
+{
+    unsigned int x;
+
+    do
+    {
+        printf("Enter your move number: ");
+        scanf("%u", &x);
+        
+        m->cHpos = NUM_TO_HPOS(x);
+        m->cVpos = NUM_TO_VPOS(x);
+        m->sMark = OPPOSITE_MARK(g_sComputerPlays);
+    }
+    while(FALSE == IsLegalMove(p, m));
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:  GameOver
+//
+// Synopsis:  Is the game over? 
+//
+// Arguments: IN POSITION *p - the board
+//            OUT SQUARE *psWhoWon - who won the game (if it's over)
+//            
+// Returns:   TRUE if the game is over.  Also sets psWhoWon telling
+//            which side one if the game is over.  This also serves
+//            as a very simple evaluation routine for the search.
+// 
+//            FALSE if the game is not over.
+//
+//+----------------------------------------------------------------------------
+BOOL GameOver(IN POSITION *p, OUT SQUARE *psWhoWon)
+{
+    int iSum;
+    COORD x, y;
+
+    for (x = 0; x < BOARD_SIZE; x++)
+    {
+        iSum = 0;
+
+        for (y = 0; y < BOARD_SIZE; y++)
+        {
+            iSum += p->sBoard[x][y];
+        }
+        if (abs(iSum) == BOARD_SIZE) goto winner;
+    }
+
+    for (y = 0; y < BOARD_SIZE; y++)
+    {
+        iSum = 0;
+
+        for (x = 0; x < BOARD_SIZE; x++)
+        {
+            iSum += p->sBoard[x][y];
+        }
+        if (abs(iSum) == BOARD_SIZE) goto winner;
+    }
+
+    iSum = 0;
+    for (x = 0; x < BOARD_SIZE; x++)
+    {
+        iSum += p->sBoard[x][x];
+    }
+    if (abs(iSum) == BOARD_SIZE) goto winner;
+
+    iSum = 0;
+    for (x = 0; x < BOARD_SIZE; x++)
+    {
+        iSum += p->sBoard[x][(BOARD_SIZE - 1 - x)];
+    }
+    if (abs(iSum) == BOARD_SIZE) goto winner;
+
+    *psWhoWon = EMPTY;
+    if (p->uNumEmpty == 0)
+    {
+        return(TRUE);
+    }
+    else
+    {
+        return(FALSE);
+    }
+
+ winner:
+    *psWhoWon = (iSum / BOARD_SIZE);
+    ASSERT(X_OR_O(*psWhoWon));
+    return(TRUE);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:  MakeMove
+//
+// Synopsis:  Make a move on a board  
+//
+// Arguments: IN OUT POSITION *p - the board
+//            IN MOVE *m - the move
+//            
+// Returns:   void
+//
+//+----------------------------------------------------------------------------
+void MakeMove(IN OUT POSITION *p, IN MOVE *m)
+{
+    if (TRUE == IsLegalMove(p, m))
+    {
+        ASSERT(p->sBoard[m->cVpos][m->cHpos] == EMPTY);
+        p->sBoard[m->cVpos][m->cHpos] = m->sMark;
+        p->uNumEmpty--;
+        ASSERT(p->uNumEmpty < (BOARD_SIZE * BOARD_SIZE));
+        p->sWhoseTurn = OPPOSITE_MARK(p->sWhoseTurn);
+        g_uPly++;
+        ASSERT(g_uPly > 0);
+    }
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:  UnmakeMove
+//
+// Synopsis:  The opposite of MakeMove
+//
+// Arguments: IN OUT POSITION *p - the board
+//            IN MOVE *m - the move to undo
+//            
+// Returns:   void
+//
+//+----------------------------------------------------------------------------
+void UnmakeMove(IN OUT POSITION *p, IN MOVE *m)
+{
+    if (p->sBoard[m->cVpos][m->cHpos] == m->sMark)
+    {
+        p->sBoard[m->cVpos][m->cHpos] = EMPTY;
+        p->uNumEmpty++;
+        ASSERT(p->uNumEmpty > 0);
+        ASSERT(p->uNumEmpty <= (BOARD_SIZE * BOARD_SIZE));
+        p->sWhoseTurn = OPPOSITE_MARK(p->sWhoseTurn);
+        ASSERT(g_uPly > 0);
+        g_uPly--;
+    }
+}
+
+
+int
+SimpleSearch(IN POSITION *p)
+{
+    SQUARE sWhoWon;
+    SQUARE s;
+    MOVE mv;
+    int iScore;
+    int iBestScore = -INFINITY;
+
+    //
+    // Evaluate this position
+    //
+    if (TRUE == GameOver(p, &sWhoWon))
+    {
+        if (sWhoWon == p->sWhoseTurn)
+        {
+            return(+INFINITY);
+        }
+        else if (sWhoWon == (p->sWhoseTurn * -1))
+        {
+            return(-INFINITY);
+        }
+        return(DRAWSCORE);
+    }
+
+    //
+    // No one won, game is still going.  Evaluate every
+    // possible move from here.
+    //
+    ASSERT(p->uNumEmpty > 0);
+    for (s = 0; s < (BOARD_SIZE * BOARD_SIZE); s++)
+    {
+        mv.cHpos = NUM_TO_HPOS(s);
+        mv.cVpos = NUM_TO_VPOS(s);
+        mv.sMark = p->sWhoseTurn;
+
+        if (IsLegalMove(p, &mv))
+        {
+            MakeMove(p, &mv);
+
+            iScore = -1 * SimpleSearch(p);
+            if (iScore > iBestScore)
+            {
+                iBestScore = iScore;
+                if (g_uPly == 1)
+                {
+                    g_mvBest = mv;
+                }
+            }
+
+            UnmakeMove(p, &mv);
+        }
+    }
+    return(iBestScore);
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:  SearchForComputerMove
+//
+// Synopsis:  Use our sophisticated search algorithm to find a computer
+//            move
+//
+// Arguments: IN POSITION *p - the current board
+//            OUT MOVE *m - the move the computer chooses; this move struct
+//                      is populated as a side-effect of this function.
+//            
+// Returns:   void* (populates move struct)
+//
+//+----------------------------------------------------------------------------
+void SearchForComputerMove(IN POSITION *p, OUT MOVE *m)
+{
+    unsigned int x;
+
+#if defined(PLAY_RANDOMLY)
+    do
+    {
+        x = rand() % (BOARD_SIZE * BOARD_SIZE);
+        m->cHpos = NUM_TO_HPOS(x);
+        m->cVpos = NUM_TO_VPOS(x);
+        m->sMark = g_sComputerPlays;
+    }
+    while(FALSE == IsLegalMove(p, m));
+#elif defined(SIMPLE_SEARCH)
+    g_uPly = 0;
+    SimpleSearch(p);
+    *m = g_mvBest;
+#else
+    #error "No Search Strategy Defined"
+#endif
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:  main
+//
+// Synopsis:  The program entry point and main game loop.
+//
+// Arguments: void
+//            
+// Returns:   int
+//
+//+----------------------------------------------------------------------------
+int main(void)
+{
+    POSITION p;
+    MOVE mv;
+    SQUARE sResult;
+
+    //
+    // Randomize: the random numbers returned by rand() will be based on
+    // the system clock when the program starts up.
+    //
+    srand(time(0));
+
+    //
+    // Setup the board and draw it once.
+    //
+    ClearBoard(&p);
+    DrawBoard(&p);
+
+    //
+    // Main game loop
+    //
+    do
+    {
+        // 
+        // See whose turn it is -- the human's or the computers -- and
+        // get a move from whoever's turn it is.
+        //
+        if (p.sWhoseTurn == g_sComputerPlays)
+        {
+            SearchForComputerMove(&p, &mv);
+        }
+        else
+        {
+            GetHumanMove(&p, &mv);
+        }
+
+        //
+        // Make the move on the board and draw the board again.
+        //
+        MakeMove(&p, &mv);
+        DrawBoard(&p);
+    }
+    while(FALSE == GameOver(&p, &sResult));
+
+    //
+    // If we get here the game is over... see what happened.
+    //
+    switch(sResult)
+    {
+        case X_MARK:
+            printf("\nX's win.\n");
+            break;
+        case O_MARK:
+            printf("\nO's win.\n");
+            break;
+        default:
+            printf("Tie (what a surprise)\n");
+            break;
+    }
+
+    exit(0);
+}
+