home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / othl-111.zip / Othello.c < prev    next >
C/C++ Source or Header  |  1994-07-26  |  32KB  |  1,243 lines

  1. ///////////////////////////////////////////////////////////////////////////
  2. // Othello.c
  3. //
  4. // Copyright (c) 1994 by John Morris    All Rights Reserved
  5. ///////////////////////////////////////////////////////////////////////////
  6. //
  7. // This Othello door source code is meant to be an example of an OS/2
  8. // type door which will run under Adept under menu option 802, or under
  9. // GMon/2 using the OS/2 door redirection flag.
  10. //
  11. // Notice there is no special com routines used here!  This file is the 
  12. // entire program!
  13. //
  14. // Under Adept and GMon/2 redirection, STDIN, STDOUT, and STDERR
  15. // are redirected thru unnamed pipes to the parent program. The parent program
  16. // then routes the information to the proper place (com port, or named pipe)
  17. //
  18. // When running the program from Adept or from GMon/2 you will see the output
  19. // appear on the regular BBS screen.
  20. //
  21. // This program (through no fault of my own.. it appears to be a quirk of the
  22. // Watcom C32 10.0 IO library) operates slightly differently when used from
  23. // the OS/2 command line than from Adept or GMon/2 (IO is controlled more
  24. // precisely from the latter two)
  25. //
  26. // I'll make more notes on the code added to make the program work more
  27. // efficiently thru pipes.
  28. //
  29. // Please keep jokes about the game itself to yourself <grin>
  30. //
  31. // Compiler command:
  32. //
  33. // wcl386 /3r /w3 /l=os2v2 othello.c
  34. //
  35. // Sample Command line: (from an Adept menu)
  36. //
  37. // Othello d:\Adept\System\Line{LN\Session.Info
  38. //
  39. // command line contains 1 parm. The name of the Session.Info file!
  40. //
  41. ///////////////////////////////////////////////////////////////////////////
  42.  
  43. #define INCL_DOS
  44.  
  45. #include <os2.h>
  46.  
  47. #include <ctype.h>
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <fcntl.h>
  52. #include <io.h>
  53. #include <share.h>
  54. #include <sys\types.h>
  55. #include <sys\stat.h>
  56. #include <time.h>
  57. #include <malloc.h>
  58. #include <math.h>
  59.  
  60. #include <myquirks.h>   // my own C programming quirks
  61.  
  62. // Input defs
  63. #define INPUTUCASE      0x00000001
  64. #define TURBO           0x00000002
  65.  
  66. // ANSI colors defs..
  67. #define BLACK   0
  68. #define RED     1
  69. #define GREEN   2
  70. #define YELLOW  3
  71. #define BLUE    4
  72. #define MAGENTA 5
  73. #define CYAN    6
  74. #define WHITE   7
  75.  
  76. ///////////////////////////////////////////////////////////////////////////
  77. // Global variables (begin with 'o')
  78.  
  79. static int      oBlack               = 0;            
  80.  
  81. static int      oBoard[10][10];
  82.  
  83. static int      oWasBoard[10][10];
  84.  
  85. static char    *oColumnLetters       = "ABCDEFGH";
  86.  
  87. static int      oComputer            = 0;
  88.  
  89. static int      oComputerPieces      = 0;
  90.  
  91. static int      oCornersSacrificed   = 0;
  92.  
  93. static int      oHandicap            = 0;
  94.  
  95. static int      oHandicapRecipient   = 0;
  96.  
  97. static int      oHuman               = 0;
  98.  
  99. static int      oHumanPieces         = 0;
  100.  
  101. static int      oMoveRow             = 0;            
  102.  
  103. static int      oNextRow[8]          = { 0, -1, -1, -1, 0, 1, 1, 1 };
  104.  
  105. static int      oMoveCol             = 0;            
  106.  
  107. static int      oNextCol[8]          = { 1, 1, 0, -1, -1, -1, 0, 1 };
  108.  
  109. static int      oSpacesTaken         = 0;
  110.  
  111. static int      oPiecesTaken         = 0;
  112.  
  113. static char     oPieceType[3][5];
  114.  
  115. static int      oRed                 = 0;       
  116.  
  117. static int      oGoodGuy             = 0;
  118.  
  119. static int      oBadGuy             = 0;
  120.  
  121. static int      oZ                   = 0;
  122.  
  123. static int      oANSIRow[8]          = { 4, 6, 8, 10, 12, 14, 16, 18 };
  124.  
  125. static int      oANSICol[8]          = { 15, 21, 27, 33, 39, 45, 51, 57 };
  126.  
  127. static BOOL     oBoardDisplayed      = FALSE;
  128.  
  129. static BOOL     oColor               = FALSE;
  130.  
  131. static BOOL     oBright              = FALSE;
  132.  
  133. static int      oForeColor           = 7;
  134.  
  135. static int      oBackColor           = 0;
  136.  
  137. static char     oTempString[512];
  138.  
  139. static int      oArgLen              = 0;
  140.  
  141. static int      oArgValue            = 0;
  142.  
  143. static char    *Copyright = {"\n\rCopyright (c) 1994 by John Morris   All Rights Reserved\n\r" };
  144.  
  145. ///////////////////////////////////////////////////////////////////////////
  146. // game functions
  147. static int  PlayGame(void);
  148. static int  PlayAgain(void);
  149. static void TellPieces(void);
  150. static int  NextToOpponent(void);
  151. static void TakePieces(BOOL ChangeBoard);
  152. static void DisplayBoard(void);
  153. static void WipeLine(int RowNumber);
  154. static void AskHandicap(void);
  155. static void HumanGetsHandicap(void);
  156. static void AskCorners(void);
  157. static void EndGame(void);
  158.  
  159. ///////////////////////////////////////////////////////////////////////////
  160. // IO procs
  161. int   YorN(char *YorNQuestion);
  162. void  OutPut(char *String, int NumLineFeeds);
  163. int   Input(char *Prompt, int Flags, int MaxLength);
  164. void  WipeLine(int Row);
  165. void  ANSIString(int ForeColor, int BackColor);
  166. void  BuffFile(char *FileToView);
  167. ULONG Random(ULONG Low, ULONG High);
  168. ULONG mult(ULONG p, ULONG q);
  169. void  Randomize(void);
  170. float Zero2OneRand(void);
  171.  
  172. static void ReadSessionInfo(char *SessionInfoName);
  173.  
  174.  
  175. void main(int ArgC, char **ArgV)
  176. {   
  177.     // Session.Info Filename should have been passed as the only
  178.     // command on the command line
  179.     if (ArgC > 1)
  180.         ReadSessionInfo(ArgV[1]);
  181.  
  182.     /////////////////////////////////////////////
  183.     // no buffering on Std IO
  184.     //
  185.     // an important step. eliminate the compilers file IO
  186.     // buffering.. everything should go thru the pipes NOW!
  187.     // let the parent program buffer things.
  188.     //
  189.     setvbuf(stdin,  NULL, _IONBF, 0);
  190.     setvbuf(stdout, NULL, _IONBF, 0);
  191.     setvbuf(stderr, NULL, _IONBF, 0);
  192.  
  193.     /////////////////////////////////////////////
  194.     // set translation mode
  195.     //
  196.     // Also everything should be binary in nature
  197.     // make that is so.
  198.     //
  199.     setmode(fileno(stdin),  O_BINARY);
  200.     setmode(fileno(stdout), O_BINARY);
  201.     setmode(fileno(stderr), O_BINARY);
  202.  
  203.     // Run Othello
  204.     PgmMain();
  205.  
  206.     return;
  207.  
  208. static void PgmMain(void)
  209. {
  210.     int  Neutral = 0;     
  211.  
  212.     Randomize();
  213.  
  214.     // clear screen
  215.  
  216.     fprintf(stderr, "\r\n   " __DATE__ " " __TIME__);
  217.     fprintf(stderr, Copyright);
  218.     fprintf(stderr, "\r\n");
  219.  
  220.     OutPut("\r\nO T H E L L O", 0);
  221.      
  222.     oForeColor = YELLOW;
  223.      
  224.     if (YorN("\r\n\r\nDo you require instructions ([Y]/N)? "))
  225.     {
  226.         oForeColor = CYAN;
  227.         OutPut("\r\nOTHELLO is played on an 8 X 8 checker board,", 1);
  228.         OutPut("rows numbered 1 to 8 and columns A to H.", 1);
  229.         OutPut("The initial configuration is all blank, except", 1);
  230.         OutPut("for the center four squares, which form the pattern", 1);
  231.         OutPut("     0 X", 1);
  232.         OutPut("     X 0", 1);
  233.         OutPut("Place your piece so that it 'outflanks'", 1);
  234.         OutPut("mine, creating a horizontal, vertical, or diagonal", 1);
  235.         OutPut("run of my pieces bounded at each end by at least", 1);
  236.         OutPut("one of yours.  This will 'flip' my pieces ", 1);
  237.         OutPut("converting them to yours.  You must capture a", 1);
  238.         OutPut("piece if possible.   If you have no legal move", 1);
  239.         OutPut("forfeit your turn by entering 0,0.", 2);
  240.         oForeColor = MAGENTA;
  241.         OutPut("Scoring is as follows:", 1);
  242.         OutPut("No handicap       --  (X'S - O'S) * 10", 1);
  243.         OutPut("You take handicap -- ((X'S - O'S) * 10) - (80  * # corners taken)", 1);
  244.         OutPut("You give handicap -- ((X'S - O'S) * 10) + (2.5 * # corners given)", 1);
  245.         OutPut("If you quit before game's end, I'll deduct a 1000 points!", 2);
  246.     }
  247.  
  248.     oBlack  = -1;
  249.     Neutral = 0;                 
  250.     oRed    = 1;
  251.  
  252.     if (NOT oColor)
  253.     {
  254.         strcpy(oPieceType[oBlack + 1]  , "X");
  255.         strcpy(oPieceType[Neutral + 1] , ".");
  256.         strcpy(oPieceType[oRed + 1]    , "O");
  257.     }
  258.      
  259.     do
  260.     {
  261.         if (NOT PlayGame())
  262.             break;
  263.    
  264.     } while (PlayAgain());
  265.  
  266.     EndGame();
  267. }
  268.  
  269. static int PlayGame(void)
  270. {
  271.     int     LastPiecesTaken;
  272.     long    GamePoints;
  273.     int     Lasti;
  274.     int     Lastj; 
  275.     char   *Column;
  276.  
  277.     for (oMoveRow = 0; oMoveRow < 10; oMoveRow++)
  278.     {
  279.         for (oMoveCol = 0; oMoveCol < 10; oMoveCol++)
  280.         {
  281.             oBoard[oMoveRow][oMoveCol] = 0;
  282.             oWasBoard[oMoveRow][oMoveCol] = 0;
  283.         }
  284.     }
  285.  
  286.     oBoard[4][4] = oRed;
  287.     oBoard[5][5] = oRed;
  288.     oBoard[4][5] = oBlack;
  289.     oBoard[5][4] = oBlack;
  290.     oComputerPieces = 2;
  291.     oHumanPieces = 2;
  292.     oSpacesTaken = 4;
  293.     oZ = FALSE;
  294.     oHandicap = 0;
  295.     oBoardDisplayed = FALSE;
  296.     oForeColor = GREEN;
  297.     sprintf(oTempString, "You are %s, and I am %s. Enter X if you want %s: ",
  298.                          oColor ? "Red"   : "O",
  299.                          oColor ? "Black" : "X",
  300.                          oColor ? "Black" : "X");
  301.  
  302.     Input(oTempString, INPUTUCASE, 1);
  303.  
  304.     oComputer = oBlack;
  305.     oHuman    = oRed;
  306.  
  307.     if (*oTempString == 'X')
  308.     {
  309.         oComputer = oRed;
  310.         oHuman    = oBlack;
  311.     } 
  312.  
  313.     AskHandicap();
  314.  
  315.     oForeColor = YELLOW;
  316.     if (YorN("Would you like to move first ([Y]/N)? "))
  317.     {
  318.         DisplayBoard();
  319.  
  320. HumanMove:
  321.  
  322.         oGoodGuy = oHuman;
  323.         oBadGuy = oComputer;
  324.  
  325. AskMove: 
  326.         do
  327.         {
  328.             do
  329.             {
  330.                 oForeColor = WHITE;
  331.  
  332.                 if (oColor)
  333.                     WipeLine(23);
  334.  
  335.                 sprintf(oTempString, "Your move, (row,column), %sF)orfeit, Q)uit? ", oColor ? "R)edraw, " : "");
  336.                 Input(oTempString, INPUTUCASE, 4);
  337.                      
  338.                 if (*oTempString == 'F')
  339.                     goto IsForfeit;
  340.  
  341.                 if (*oTempString == 'Q')
  342.                 {
  343.                     if (oColor)
  344.                         WipeLine(22);
  345.                 
  346.                     OutPut("Chickened out, huh!?.", 1);
  347.                     return (TRUE);
  348.                 }
  349.                      
  350.                 if (oColor AND *oTempString == 'R')
  351.                 {
  352.                     oBoardDisplayed = FALSE;
  353.  
  354.                     for (oMoveRow = 0; oMoveRow < 10; oMoveRow++)
  355.                     {
  356.                         for (oMoveCol = 0; oMoveCol < 10; oMoveCol++)
  357.                         {
  358.                             oWasBoard[oMoveRow][oMoveCol] = 0;
  359.                         }
  360.                     }
  361.  
  362.                     DisplayBoard();
  363.  
  364.                     goto AskMove;
  365.                 }
  366.  
  367.                 if (NOT strchr(oTempString, ','))
  368.                 {
  369.                     oForeColor = RED;
  370.                     if (NOT oColor)
  371.                         OutPut("Row,Column with a comma...", 1);
  372.                     goto  AskMove;
  373.                 } 
  374.                      
  375.                 if (oArgLen != 3 )
  376.                 {
  377.                     oForeColor = RED;
  378.                     if (NOT oColor)
  379.                         OutPut("Try again...", 1);
  380.                     goto  AskMove;
  381.                 } 
  382.                  
  383.             } while (oArgValue < 0 OR oArgValue > 8 );
  384.  
  385.             oMoveRow = (int) oArgValue;
  386.  
  387.             Column = strchr(oTempString, ',') + 1;
  388.              
  389.             if (oMoveRow)
  390.             {
  391.                 if (Column = strchr(oColumnLetters, *Column))
  392.                 {
  393.                     oMoveCol = (int) (Column - oColumnLetters) + 1;
  394.                     // oMoveRow,oMoveCol is human move...
  395.                     goto g540;
  396.                 }
  397.                 else
  398.                     goto AskMove;
  399.             } 
  400.  
  401. IsForfeit:
  402.             oForeColor = MAGENTA;
  403.              
  404.             if (oColor)
  405.                 WipeLine(23);
  406.  
  407.         } while (NOT YorN("Are you forfeiting your turn ([Y]/N)? "));
  408.  
  409.         if (NOT oZ)
  410.         {
  411.             oZ = TRUE;
  412.             goto ComputerMove;
  413.         } 
  414.     } 
  415.     else
  416.     {
  417. ComputerMove:  
  418.  
  419.         LastPiecesTaken = -1;
  420.         Lasti = 0;
  421.         Lastj = 0;
  422.         oGoodGuy = oComputer;
  423.         oBadGuy = oHuman;
  424.         oMoveRow = 0;
  425.  
  426.         if (oColor)
  427.             WipeLine(21);
  428.  
  429.         do 
  430.         {
  431.             oMoveRow++;
  432.             for (oMoveCol = 1; oMoveCol <= 8; oMoveCol++)
  433.             {
  434.                 if (oBoard[oMoveRow][oMoveCol] == 0)
  435.                 {
  436.                     if (NextToOpponent())
  437.                     {
  438.                         TakePieces(FALSE);
  439.                          
  440.                         if (oPiecesTaken != 0)
  441.                         {
  442.                             // computer likes corners....
  443.                             if (((oMoveRow - 1) * (oMoveRow - 8)) == 0)
  444.                                 oPiecesTaken += 4;
  445.                              
  446.                             if (((oMoveCol - 1) * (oMoveCol - 8)) == 0)
  447.                                 oPiecesTaken += 4;
  448.                              
  449.                             // doesn't like corners inside corners
  450.                             if (Zero2OneRand() > 0.32)
  451.                             {
  452.                                 if (((oMoveRow - 2) * (oMoveRow - 7)) == 0)
  453.                                     oPiecesTaken >>= 1;
  454.  
  455.                                 if (((oMoveCol - 2) * (oMoveCol - 7)) == 0)
  456.                                     oPiecesTaken >>= 1;
  457.                             }
  458.                              
  459.                             if (oPiecesTaken >= LastPiecesTaken)
  460.                             {
  461.                                 LastPiecesTaken = oPiecesTaken;
  462.                                 Lasti = oMoveRow;
  463.                                 Lastj = oMoveCol;
  464.                             } 
  465.                         } 
  466.                     }
  467.                 } 
  468.             }
  469.              
  470.         } while  (oMoveRow != 8);
  471.  
  472.         if (LastPiecesTaken > 0)
  473.         {
  474.             oZ = FALSE;
  475.             oForeColor = MAGENTA;
  476.             if (oColor)
  477.                 WipeLine(21);
  478.             sprintf(oTempString , "I will move to %d, %c", Lasti, oColumnLetters[Lastj - 1]);
  479. //            if (NOT oColor)
  480.                 OutPut(oTempString, oColor ? 0 : 1);
  481.             DosSleep(1000);
  482.             oMoveRow = Lasti;
  483.             oMoveCol = Lastj;
  484.             TakePieces(TRUE);
  485.             oComputerPieces = oComputerPieces + oPiecesTaken + 1 ;
  486.             oHumanPieces -= oPiecesTaken;
  487.             oSpacesTaken++;
  488.             sprintf(oTempString , "That gives me %d of your pieces", oPiecesTaken);
  489.             if (NOT oColor)
  490.                 OutPut(oTempString, 1);
  491.             oForeColor = CYAN;
  492.             TellPieces();
  493.             if (NOT oColor)
  494.                 DosSleep(1000);
  495.             DisplayBoard();
  496.             
  497.             if (oHumanPieces) 
  498.             {
  499.                 if (oSpacesTaken != 64)
  500.                     goto HumanMove;
  501.             }
  502.         } 
  503.         else
  504.         {
  505.             oForeColor = RED;
  506.  
  507.             if (oColor)
  508.                 WipeLine(22);
  509.  
  510.             OutPut("I forfeit my move", 1);
  511.              
  512.             if (NOT oZ)
  513.             {
  514.                 oZ = TRUE;
  515.                 goto HumanMove;
  516.             } 
  517.         } 
  518.     } 
  519. EndCheck:
  520.  
  521.     OutPut("", 1);
  522.  
  523.     TellPieces();
  524.  
  525.     if (NOT oColor)
  526.         DosSleep(1000);
  527.      
  528.     if (oColor)
  529.     {
  530.         WipeLine(21);
  531.         OutPut("\x1B[21;1H", 0);
  532.     }
  533.  
  534.     if (oHumanPieces == oComputerPieces)
  535.     {
  536.         OutPut("The game is a draw!!", 1);
  537.         return (TRUE);
  538.     } 
  539.     
  540.     if (oHumanPieces > oComputerPieces)
  541.     {
  542.         OutPut("Great job! You win!!", 1);
  543.     } 
  544.     else
  545.     {
  546.         OutPut("GOTCHA!  I won that one", 1);
  547.     } 
  548.  
  549.     GamePoints = ((oHumanPieces - oComputerPieces + oHandicap) * 100);
  550.     sprintf(oTempString , "You earned %ld points for that game", GamePoints);
  551.     if (NOT oColor)
  552.         OutPut(oTempString, 1);
  553.  
  554.     return (TRUE);
  555.  
  556. g540: 
  557.      
  558.     if (oBoard[oMoveRow][oMoveCol])
  559.     {
  560.         oForeColor = WHITE;
  561.  
  562.         if (oColor)
  563.             WipeLine(22);
  564.  
  565.         OutPut("Sorry that square is occupied. Try again!", 1);
  566.         DosSleep(1000);
  567.         goto AskMove;
  568.     } 
  569.  
  570.     if (NOT NextToOpponent())
  571.     {
  572.         oForeColor = RED;
  573.         if (oColor)
  574.             WipeLine(22);
  575.         OutPut("Sorry you are not next to one of my pieces. Try again!", 1);
  576.         DosSleep(1000);
  577.         goto AskMove;
  578.     } 
  579.  
  580.     TakePieces(FALSE);
  581.     
  582.     if (oPiecesTaken <= 0)
  583.     {
  584.         oForeColor = RED;
  585.         if (oColor)
  586.             WipeLine(22);
  587.         OutPut("Sorry that doesn't flank a row. Try again!", 1);
  588.         DosSleep(1000);
  589.         goto AskMove;
  590.     } 
  591.  
  592.     oZ = FALSE;
  593.     sprintf(oTempString , "That gives you %d of my pieces", oPiecesTaken);
  594.     if (NOT oColor)
  595.         OutPut(oTempString, 1);
  596.     TakePieces(TRUE);
  597.     oHumanPieces = oHumanPieces + oPiecesTaken + 1 ;
  598.     oComputerPieces -= oPiecesTaken;
  599.     oSpacesTaken++;
  600.     oForeColor = CYAN;
  601.     TellPieces();
  602.     DosSleep(1000);
  603.     DisplayBoard();
  604.     
  605.     if (oComputerPieces)
  606.     {
  607.         if (oSpacesTaken != 64)
  608.             goto ComputerMove;
  609.     }
  610.  
  611.     goto EndCheck;
  612. }
  613.  
  614. static void TellPieces(void)
  615. {
  616.     if (oColor)
  617.         OutPut("\x1B[20;17H\x1B[K", 0);
  618.  
  619.     sprintf(oTempString , "You have %d pieces, and I have %d pieces", oHumanPieces, oComputerPieces);
  620.     OutPut(oTempString, 1);
  621. }
  622.  
  623. static int PlayAgain(void)
  624. {
  625.     OutPut("", 1);
  626.  
  627.     oForeColor = YELLOW;
  628.  
  629.     if (oColor)
  630.         WipeLine(23);
  631.  
  632.     if (YorN("Do you want to play another game ([Y]/N)? "))
  633.         return (TRUE);
  634.  
  635.     OutPut("Thanks. Its been fun playing you.", 1);
  636.     OutPut("Exiting Othello, Bye", 1);
  637.  
  638.     return (FALSE);
  639. }
  640.  
  641. static int NextToOpponent(void)
  642. {
  643.     int   Index1;
  644.     int   Index2;
  645.  
  646.     for (Index1 = -1; Index1 <= 1; Index1++) 
  647.     {
  648.         for (Index2 = -1; Index2 <= 1; Index2++) 
  649.         {
  650.             if  (oBoard[oMoveRow + Index1][oMoveCol + Index2] == oBadGuy)
  651.             {
  652.                 return (TRUE);
  653.             }
  654.         }
  655.     }
  656.  
  657.     return (FALSE);
  658. }
  659.  
  660. static void TakePieces(BOOL ChangeBoard)
  661. {
  662.     int Index;
  663.     int NextSpaceIndex;
  664.     int NextRowIndex;
  665.     int AdjacentRow;
  666.     int NextColIndex;
  667.     int AdjacentCol;                                  
  668.     int s3;
  669.  
  670.     oPiecesTaken = 0;
  671.  
  672.     for (NextSpaceIndex = 0; NextSpaceIndex < 8; NextSpaceIndex++)
  673.     {
  674.         NextRowIndex = oNextRow[NextSpaceIndex];      //  0, -1, -1, -1, 0, 1, 1, 1 
  675.         NextColIndex = oNextCol[NextSpaceIndex];      //  1, 1, 0, -1, -1, -1, 0, 1 
  676.         AdjacentRow  = oMoveRow + NextRowIndex;
  677.         AdjacentCol  = oMoveCol + NextColIndex;
  678.         s3 = 0;
  679.         
  680.         if (oBoard[AdjacentRow][AdjacentCol] == oBadGuy)
  681. g750:  
  682.         {
  683.             s3++;
  684.             AdjacentRow += NextRowIndex;
  685.             AdjacentCol += NextColIndex;
  686.             
  687.             if (oBoard[AdjacentRow][AdjacentCol] == oGoodGuy)
  688.             {
  689.                 oPiecesTaken += s3;
  690.                 
  691.                 if (ChangeBoard)
  692.                 {
  693.                     AdjacentRow = oMoveRow;
  694.                     AdjacentCol = oMoveCol;
  695.                     for (Index = 0; Index <= s3; Index++)
  696.                     {
  697.                         oBoard[AdjacentRow][AdjacentCol] = oGoodGuy;
  698.                         AdjacentRow += NextRowIndex;
  699.                         AdjacentCol += NextColIndex;
  700.                     }
  701.                 } 
  702.             } 
  703.             else
  704.             {
  705.                 if (oBoard[AdjacentRow][AdjacentCol])
  706.                     goto  g750;
  707.             }
  708.  
  709.             goto  g770;
  710.         } 
  711.  
  712. g770:;
  713.  
  714.     }
  715.     return;
  716. }
  717.  
  718. static void DisplayBoard(void)
  719. {
  720.     int ArrayIndex1;
  721.     int ArrayIndex2;
  722.  
  723.     if (NOT oColor)
  724.         OutPut("    A   B   C   D   E   F   G   H ", 2);
  725.     else 
  726.         oBackColor = WHITE;
  727.  
  728.     if (oColor AND (NOT oBoardDisplayed))
  729.     {
  730.         oBoardDisplayed = TRUE;
  731.         BuffFile("Othello.Scn");
  732.     }
  733.  
  734.     for (ArrayIndex1 = 1; ArrayIndex1 <= 8; ArrayIndex1++)
  735.     {
  736.         if (NOT oColor)
  737.             sprintf(oTempString , "%d", ArrayIndex1);
  738.  
  739.         for (ArrayIndex2 = 1; ArrayIndex2 <= 8; ArrayIndex2++)
  740.         {
  741.             if (NOT oColor)
  742.             {
  743.                 strcat(oTempString , "   ");
  744.                 strcat(oTempString , oPieceType[oBoard[ArrayIndex1][ArrayIndex2] + 1]);
  745.             }
  746.             else
  747.             {
  748.                 if (oBoard[ArrayIndex1][ArrayIndex2] != oWasBoard[ArrayIndex1][ArrayIndex2])
  749.                 {
  750.                     oWasBoard[ArrayIndex1][ArrayIndex2] = oBoard[ArrayIndex1][ArrayIndex2];
  751.  
  752.                     oForeColor = (oBoard[ArrayIndex1][ArrayIndex2] == oRed) ? RED : BLACK;
  753.  
  754.                     sprintf(oTempString, "\x1B[%d;%dH█████", oANSIRow[ArrayIndex1 - 1], oANSICol[ArrayIndex2 - 1]);
  755.  
  756.                     OutPut(oTempString, 0);
  757.                 }
  758.             }
  759.         }
  760.  
  761.         if (NOT oColor)
  762.             OutPut(oTempString, 2);
  763.     }
  764.  
  765.     if (oColor)
  766.     {
  767.         oBackColor = BLACK;
  768.         WipeLine(22);
  769.     }
  770.  
  771.     return;
  772. }
  773.  
  774. static void WipeLine(int RowNumber)
  775. {
  776.     char WipeString[30];
  777.  
  778.     sprintf(WipeString, "\x1B[%d;1H\x1B[K\x1B[13C", RowNumber);
  779.  
  780.     OutPut(WipeString, 0);
  781.  
  782.     return;
  783. }
  784.  
  785. static void AskHandicap(void)
  786. {
  787.     oForeColor = GREEN;
  788.  
  789.     if (YorN("Do you wish to be given a handicap (i.e. Do you want a headstart) ([Y]/N)? "))
  790.     {
  791.         HumanGetsHandicap();
  792.     }
  793.     else
  794.     {
  795.         if (YorN("Do you wish to give me a handicap (i.e. Do you want a hard time) ([Y]/N)? "))
  796.         {
  797.             oHandicapRecipient = oComputer;
  798.             AskCorners();
  799.             oHandicap = oCornersSacrificed * 2.5;
  800.             oComputerPieces += oCornersSacrificed;
  801.         } 
  802.     }
  803.  
  804.     return;
  805. }
  806.  
  807. static void HumanGetsHandicap(void)
  808. {
  809.     oHandicapRecipient = oHuman;
  810.     AskCorners();
  811.     oHandicap = oCornersSacrificed * (-8);
  812.     oHumanPieces += oCornersSacrificed;
  813.  
  814.     return;
  815. }
  816.  
  817. static int CornerCol[4] = { 1, 1, 8, 8 };
  818. static int CornerRow[4] = { 1, 8, 8, 1 };
  819.  
  820. static void AskCorners(void)
  821. {
  822.     int Index;
  823.     int ArrayIndex1;
  824.     int ArrayIndex2;
  825.  
  826.     Input("How many corners (1-4) ", 0, 1);
  827.     oCornersSacrificed = (int) oArgValue;
  828.      
  829.     if (oCornersSacrificed > 4)
  830.     {
  831.         HumanGetsHandicap();
  832.         return;
  833.     } 
  834.      
  835.     if  (oCornersSacrificed < 1)
  836.     {
  837.         HumanGetsHandicap();
  838.         return;
  839.     } 
  840.     for (Index = 0; Index < oCornersSacrificed; Index++)
  841.     {
  842.         ArrayIndex1 = CornerCol[Index];
  843.         ArrayIndex2 = CornerRow[Index];
  844.         oBoard[ArrayIndex1][ArrayIndex2] = oHandicapRecipient;
  845.     }
  846.  
  847.     oSpacesTaken += oCornersSacrificed;
  848.  
  849.     return;
  850. }
  851.  
  852. void EndGame(void)
  853. {
  854.     exit (0);
  855. }
  856.  
  857. //////////////////////////////////////////////////////////
  858. // Output uses printf for its dirty work..  line feeds
  859. // are done separately in a loop according to the number
  860. // of LF's asked for.
  861. //
  862. // If the user has ANSI color, then a color string is sent
  863. // before each line (remember this is an example....)
  864. void OutPut(char *String, int NumLineFeeds)
  865. {
  866.     int Index;
  867.  
  868.     ANSIString(oForeColor, oBackColor);
  869.  
  870.     printf(String);
  871.  
  872.     for (Index = 0; Index < NumLineFeeds; Index++)
  873.         printf("\r\n");
  874.  
  875.     fflush(stdout);
  876.  
  877.     return;
  878. }
  879.  
  880. /////////////////////////////////////////////////////////
  881. // Input - we want to control the maximum length of the
  882. // input, and possibly as for upper case, or get keystrokes
  883. // in hot key mode.
  884. //
  885. int Input(char *Prompt, int Flags, int MaxLength)
  886. {
  887.     int Index = 0;
  888.     int CharIn;
  889.     time_t SleepTime;
  890.  
  891.     OutPut(Prompt, 0);
  892.  
  893.     memset(oTempString, 0, 512);
  894.  
  895.     if (MaxLength > 511)
  896.         MaxLength = 511;
  897.  
  898.     SleepTime = time(NULL) + 240L;
  899.  
  900.     while (1)
  901.     {
  902.         // this call works different from OS/2 command
  903.         // (versus Adept or GMon/2 redirection)
  904.         CharIn = getchar();
  905.  
  906.         if (CharIn != EOF)
  907.         {
  908.             SleepTime = time(NULL) + 240L;
  909.  
  910.             if (CharIn == '\r' || CharIn == '\n')
  911.                 break;
  912.  
  913.             if (CharIn == '\b' && Index)
  914.             {
  915.                 printf("\b \b");
  916.                 Index--;
  917.                 continue;
  918.             }
  919.  
  920.             // Ctrl-Y deletes all input
  921.             if (CharIn == 25 && Index)
  922.             {
  923.                 while (Index--)
  924.                     printf("\b \b");
  925.  
  926.                 continue;
  927.             }
  928.  
  929.             if (NOT isprint(CharIn))
  930.                 continue;
  931.  
  932.             fputc(CharIn, stdout);
  933.  
  934.             fflush(stdout);
  935.  
  936.             oTempString[Index++] = (char) CharIn;
  937.             oTempString[Index] = '\0';
  938.  
  939.             if (Index >= MaxLength)
  940.             {
  941.                 if (Flags & TURBO)
  942.                 {
  943.                     break;
  944.                 }
  945.  
  946.                 continue;
  947.             }
  948.         }
  949.         else
  950.         {
  951.             DosSleep(65);
  952.  
  953.             // we just fell asleep
  954.             if (SleepTime < time(NULL))
  955.                 exit(1);
  956.         }
  957.     }
  958.  
  959.     if (Flags & INPUTUCASE)
  960.         strupr(oTempString);
  961.  
  962.     // store value of string, if any
  963.     oArgValue = atoi(oTempString);
  964.  
  965.     // store length of string, if any
  966.     oArgLen = strlen(oTempString);
  967.  
  968.     OutPut("", 1);
  969.  
  970.     return (0);
  971. }
  972.  
  973. ////////////////////////////////////////////////////////
  974. // returns TRUE if Y (default) ... FALSE if N
  975. int YorN(char *YorNQuestion)
  976. {
  977.     int temp;
  978.  
  979.     do
  980.     {
  981.         Input(YorNQuestion, TURBO | INPUTUCASE, 1);
  982.  
  983.         temp = (int) *oTempString;
  984.  
  985.         if ((temp == 0) OR (temp == 'Y') OR (temp == 'N'))
  986.             break;
  987.  
  988.     } while(1);
  989.  
  990.     *oTempString = '\0';
  991.  
  992.     if ((temp == 'Y') OR (temp == 0))
  993.         return (TRUE);
  994.     else
  995.         return (FALSE);
  996. }
  997.  
  998. void ANSIString(int ForeColor, int BackColor)
  999. {
  1000.     int StrIndex;
  1001.     char ANSIStrBuff[20];
  1002.  
  1003.     if (NOT oColor)
  1004.         return;
  1005.  
  1006.     StrIndex = sprintf(ANSIStrBuff, "\x1B[%s", oBright ? "1;" : "");
  1007.  
  1008.     StrIndex += sprintf(ANSIStrBuff + StrIndex, "%d;", ForeColor + 30);
  1009.  
  1010.     StrIndex += sprintf(ANSIStrBuff + StrIndex, "%d", BackColor + 40);
  1011.  
  1012.     sprintf(ANSIStrBuff + StrIndex, "m");
  1013.  
  1014.     if (strlen(ANSIStrBuff) < 4)   //  ie. '\x1B[m'
  1015.         *ANSIStrBuff = '\0';
  1016.  
  1017.     printf(ANSIStrBuff);
  1018.  
  1019.     fflush(stdout);    
  1020.  
  1021.     return;
  1022. }
  1023.  
  1024. //////////////////////////////////////////////////////////////////////
  1025. // Read text file and display it to user
  1026. //
  1027. void BuffFile(char *FileToView)
  1028. {
  1029.     int BuffFileHandle, GraphicsHold;
  1030.     ULONG  BufferSize = 512;
  1031.     char  *FileBuffer;
  1032.     char  BuffFileName[80];
  1033.     char *ThisLine, *NextLine, *EndBuffer;
  1034.     int  BytesRead;
  1035.  
  1036.     strcpy(BuffFileName, FileToView);
  1037.  
  1038.     BuffFileHandle = sopen(BuffFileName, O_RDWR | O_TEXT, SH_DENYNO);
  1039.  
  1040.     if (BuffFileHandle == -1) // no file present
  1041.         return;
  1042.  
  1043.     BufferSize = (ULONG) (filelength(BuffFileHandle) + 2);
  1044.  
  1045.     FileBuffer = (char *) calloc(1, BufferSize);
  1046.  
  1047.     if (FileBuffer == NULL)
  1048.     {
  1049.         close(BuffFileHandle);
  1050.  
  1051.         return;
  1052.     }
  1053.  
  1054.     GraphicsHold = oColor;                 // color always off here.. so remember
  1055.  
  1056.     // stop ANSI color string from being displayed
  1057.     // in front of each line of file
  1058.     oColor = FALSE;                      // graphics status
  1059.  
  1060.     BytesRead = read(BuffFileHandle, FileBuffer, BufferSize - 2);
  1061.  
  1062.     if (BytesRead > 1)
  1063.     {
  1064.         EndBuffer = FileBuffer + BytesRead;
  1065.  
  1066.         ThisLine = FileBuffer;
  1067.  
  1068.         while (ThisLine)
  1069.         {
  1070.             NextLine = strchr(ThisLine, '\n');
  1071.  
  1072.             if (NextLine)
  1073.                 *NextLine++ = '\0';
  1074.  
  1075.             OutPut(ThisLine, 1);
  1076.  
  1077.             ThisLine = NextLine;
  1078.  
  1079.             if (ThisLine >= EndBuffer)
  1080.                 break;
  1081.         }
  1082.     }
  1083.  
  1084.     close(BuffFileHandle);
  1085.  
  1086.     free(FileBuffer);                  // free file buffer
  1087.  
  1088.     oColor = GraphicsHold;           // remember graphics mode
  1089.  
  1090.     return;
  1091. }
  1092.  
  1093.  
  1094.  
  1095. //////////// Random Number functions ///////////////
  1096.  
  1097. float Zero2OneRand(void)
  1098. {
  1099.     short rand_result;
  1100.  
  1101.     rand_result = rand();
  1102.  
  1103.     return ((float) rand_result / 32767.0);
  1104. }
  1105.  
  1106. ULONG rand_a;
  1107.  
  1108. void Randomize(void)
  1109. {
  1110.     srand((ULONG) time(NULL));
  1111.  
  1112.     rand_a = (ULONG) rand();
  1113.  
  1114.     srand(Random(1, (ULONG) 65535));
  1115.  
  1116.     return;
  1117. }
  1118.  
  1119. // ***************************************************************************
  1120. // * These routines are random number generators 2 have a setable range      *
  1121. // * of numbers, and one returns a float between 0 and 1                     *
  1122. // ***************************************************************************
  1123.  
  1124. ULONG rand_m  = 100000000;
  1125. ULONG rand_m1 = 10000;
  1126. ULONG rand_b  = 31415821;
  1127.  
  1128. ULONG Random(ULONG Low, ULONG High)
  1129. {
  1130.     rand_a = (ULONG) ((mult((ULONG) rand_a, (ULONG) rand_b) + 1) MOD rand_m);
  1131.     High = (ULONG) ((((rand_a / rand_m1) * (ULONG) High) / rand_m1) + 1);
  1132.     High -= Low;
  1133.  
  1134.     return (High);
  1135. }
  1136.  
  1137. ULONG mult(ULONG p, ULONG q)
  1138. {
  1139.     ULONG multie;
  1140.     ULONG p0, p1, q0, q1;
  1141.  
  1142.     p0 = (p MOD (ULONG) rand_m1);
  1143.     p1 = (p /   (ULONG) rand_m1);
  1144.     q0 = (q MOD (ULONG) rand_m1);
  1145.     q1 = (q /   (ULONG) rand_m1);
  1146.     multie = (ULONG) (((((p0 * q1) + (p1 * q0)) MOD rand_m1) * rand_m1 + (p0 * q0)) MOD rand_m);
  1147.  
  1148.     return (multie);
  1149. }
  1150.  
  1151. //////////////////////////////////////////////////////////
  1152. // Code to extract color (yes/no) flag from Session info
  1153. ///////////////////////////////////////////////////////////
  1154. char *SkipWhiteSpace(char *String);
  1155. char *SkipNonWhiteSpace(char *String);
  1156.  
  1157. void ReadSessionInfo(char *SessionInfoName)
  1158. {
  1159.     FILE *SessionInfoHandle;
  1160.     char  Input[301];
  1161.     int   Key;
  1162.     char *Keyword;
  1163.     char *Data;
  1164.     char *NewLine;
  1165.  
  1166.     SessionInfoHandle = fopen(SessionInfoName, "rt");
  1167.  
  1168.     if (SessionInfoHandle == NULL)
  1169.     {
  1170.         fprintf(stderr, "\n\rSession.Info interface. ");
  1171.         fprintf(stderr, "Can't open '%s'\n\r", SessionInfoName);
  1172.         DosSleep(2000);
  1173.         exit(1);
  1174.     }
  1175.  
  1176.     while (NOT feof(SessionInfoHandle))
  1177.     {
  1178.         if (NOT fgets(Input, 301, SessionInfoHandle))
  1179.             break;
  1180.  
  1181.         if (*Input == ';')
  1182.         {
  1183.             // comment line
  1184.             continue;
  1185.         }
  1186.  
  1187.         NewLine = strchr(Input, '\n');
  1188.  
  1189.         if (NewLine)
  1190.             *NewLine = '\0';
  1191.  
  1192.         Keyword = Input;
  1193.  
  1194.         Data = SkipNonWhiteSpace(Keyword);
  1195.  
  1196.         if (*Data)
  1197.         {
  1198.             *Data++ = '\0';
  1199.  
  1200.             Data = SkipWhiteSpace(Data);
  1201.  
  1202.             // Data now points to data!
  1203.         }
  1204.  
  1205.         // look for ANSICOLOR keyword,
  1206.         // and act on it.
  1207.         if (NOT stricmp(Keyword, "ANSICOLOR"))
  1208.         {
  1209.             oColor = atoi(Data);
  1210.  
  1211.             // all done.. ferget rest o' file
  1212.             break;
  1213.         }
  1214.  
  1215.     }
  1216.  
  1217.     fclose(SessionInfoHandle);
  1218.  
  1219.     return;
  1220. }
  1221.  
  1222. static char *SkipWhiteSpace(char *String)
  1223. {
  1224.     char *p = String;
  1225.  
  1226.     while (*p == ' ' || *p == '\t')
  1227.         p++;
  1228.  
  1229.     return (p);
  1230. }
  1231.  
  1232. static char *SkipNonWhiteSpace(char *String)
  1233. {
  1234.     char *p = String;
  1235.  
  1236.     while (*p && *p != ' ' && *p != '\t')
  1237.         p++;
  1238.  
  1239.     return (p);
  1240. }
  1241.  
  1242.