home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / util / gblanker-38.8.lha / GBlanker / GSource / Blankers / TicTacToe / blank.c next >
C/C++ Source or Header  |  1994-12-04  |  10KB  |  428 lines

  1. /*
  2.  *  Copyright (c) 1994 Michael D. Bayne.
  3.  *  All rights reserved.
  4.  *
  5.  *  Please see the documentation accompanying the distribution for distribution
  6.  *  and disclaimer information.
  7.  */
  8.  
  9. #include <exec/memory.h>
  10. #include "/includes.h"
  11. #include <stdlib.h>
  12.  
  13. #include "TicTacToe_rev.h"
  14. STATIC const UBYTE VersTag[] = VERSTAG;
  15.  
  16. UBYTE *AreaBuf;
  17. PLANEPTR ScratchBuf;
  18. struct AreaInfo InfRec;
  19. struct TmpRas ScratchRast;
  20. struct RastPort TmpRP;
  21.  
  22. #define PLAYER_X 1
  23. #define PLAYER_O 2
  24.  
  25. typedef struct _BoardInfo
  26. {
  27.     struct RastPort *bi_Rast;
  28.     LONG bi_Wid;
  29.     LONG bi_Hei;
  30.     LONG bi_Length;
  31.     LONG bi_Width;
  32.     LONG bi_XOff;
  33.     LONG bi_YOff;
  34.     LONG bi_MoveDelay;
  35.     LONG bi_GameDelay;
  36. }
  37. BoardInfo;
  38.  
  39. LONG Board[9];
  40. BoardInfo BrdInfo;
  41.  
  42. VOID Defaults( PrefObject *Prefs )
  43. {
  44.     Prefs[0].po_Level = 1;
  45.     Prefs[2].po_Level = 2;
  46.     Prefs[4].po_ModeID = getTopScreenMode();
  47. }
  48.  
  49. LONG SafeDelay( LONG Ticks )
  50. {
  51.     LONG RetVal = ContinueBlanking();
  52.  
  53.     while(( RetVal == OK )&&( Ticks > 0 ))
  54.     {
  55.         Delay( 2 );
  56.         RetVal = ContinueBlanking();
  57.         Ticks -= 2;
  58.     }
  59.  
  60.     return RetVal;
  61. }
  62.  
  63. VOID OldSloppyLine( BoardInfo *Inf, LONG x1, LONG y1, LONG x2, LONG y2,
  64.                    LONG Case )
  65. {
  66.     struct RastPort *Rast = Inf->bi_Rast;
  67.     LONG w = Inf->bi_Width;
  68.  
  69.     AreaEllipse( Rast, x1, y1, w/2, w/2 );
  70.     AreaEnd( Rast );
  71.  
  72.     AreaEllipse( Rast, x2, y2, w/2, w/2 );
  73.     AreaEnd( Rast );
  74.     
  75.     switch( Case )
  76.     {
  77.     case 1:
  78.         AreaMove( Rast, x1 + w/2, y1 );
  79.         AreaDraw( Rast, x2 + w/2, y2 );
  80.         AreaDraw( Rast, x2 - w/2, y2 );
  81.         AreaDraw( Rast, x1 - w/2, y1 );
  82.         break;
  83.     case 2:
  84.         AreaMove( Rast, x1, y1 + w/2 );
  85.         AreaDraw( Rast, x2, y2 + w/2 );
  86.         AreaDraw( Rast, x2, y2 - w/2 );
  87.         AreaDraw( Rast, x1, y1 - w/2 );
  88.         break;
  89.     case 3:
  90.         AreaMove( Rast, x1 + 7*w/20, y1 + 7*w/20 );
  91.         AreaDraw( Rast, x2 + 7*w/20, y2 + 7*w/20 );
  92.         AreaDraw( Rast, x2 - 7*w/20, y2 - 7*w/20 );
  93.         AreaDraw( Rast, x1 - 7*w/20, y1 - 7*w/20 );
  94.         break;
  95.     case 4:
  96.         AreaMove( Rast, x1 - 7*w/20, y1 + 7*w/20 );
  97.         AreaDraw( Rast, x2 - 7*w/20, y2 + 7*w/20 );
  98.         AreaDraw( Rast, x2 + 7*w/20, y2 - 7*w/20 );
  99.         AreaDraw( Rast, x1 + 7*w/20, y1 - 7*w/20 );
  100.         break;
  101.     }
  102.  
  103.     AreaEnd( Rast );
  104. }
  105.  
  106. VOID SloppyLine( BoardInfo *Inf, LONG x1, LONG y1, LONG x2, LONG y2 )
  107. {
  108.     LONG dx, dy, x, y, i, w = Inf->bi_Width, Case;
  109.     
  110.     if( x1 == x2 )
  111.         Case = 1;
  112.     else if( y1 == y2 )
  113.         Case = 2;
  114.     else if( y1 > y2 )
  115.         Case = 3;
  116.     else
  117.         Case = 4;
  118.  
  119.     x1 += ( RangeRand( w ) - w/2 );
  120.     x2 += ( RangeRand( w ) - w/2 );
  121.     y1 += ( RangeRand( w ) - w/2 );
  122.     y2 += ( RangeRand( w ) - w/2 );
  123.  
  124.     dx = ( x2 - x1 ) / 5;
  125.     dy = ( y2 - y1 ) / 5;
  126.  
  127.     for( i = 0, x = x1, y = y1; i < 5; x += dx, y += dy, i++ )
  128.     {
  129.         OldSloppyLine( Inf, x, y, x + dx, y + dy, Case );
  130.         Delay( 2 );
  131.     }
  132. }
  133.  
  134. VOID DrawO( BoardInfo *Inf, LONG Position )
  135. {
  136.     LONG XCenter, YCenter, Radius;
  137.     LONG o1, o2, o3, o4, w = Inf->bi_Width;
  138.  
  139.     o1 = RangeRand( w/2 ) - w/4;
  140.     o2 = RangeRand( w/2 ) - w/4;
  141.     o3 = RangeRand( w/2 ) - w/4;
  142.     o4 = RangeRand( w/2 ) - w/4;
  143.  
  144.     Radius = ( Inf->bi_Length/3 - 2*Inf->bi_Width ) / 2 + o3;
  145.     XCenter = Inf->bi_XOff + Inf->bi_Width + Radius +
  146.         (Position%3) * Inf->bi_Length/3 + o1;
  147.     YCenter = Inf->bi_YOff + Inf->bi_Width + Radius +
  148.         (Position/3) * Inf->bi_Length/3 + o2;
  149.  
  150.     SetAPen( Inf->bi_Rast, 3 );
  151.     
  152.     AreaEllipse( Inf->bi_Rast, XCenter, YCenter, Radius + o3, Radius + o4 );
  153.     Radius -= Inf->bi_Width;
  154.     AreaEllipse( Inf->bi_Rast, XCenter, YCenter, Radius + o3, Radius + o4 );
  155.     AreaEnd( Inf->bi_Rast );
  156. }
  157.  
  158. VOID DrawX( BoardInfo *Inf, LONG Position )
  159. {
  160.     LONG XOff = Inf->bi_XOff + Inf->bi_Width + (Position%3) * Inf->bi_Length/3;
  161.     LONG YOff = Inf->bi_YOff + Inf->bi_Width + (Position/3) * Inf->bi_Length/3;
  162.     LONG Dimen = Inf->bi_Length/3 - 2*Inf->bi_Width - Inf->bi_Width/2 - 1;
  163.     
  164.     SetAPen( Inf->bi_Rast, 2 );
  165.     SloppyLine( Inf, XOff + Inf->bi_Width/2, YOff + Inf->bi_Width/2,
  166.                XOff + Dimen, YOff + Dimen );
  167.     SloppyLine( Inf, XOff + Inf->bi_Width/2, YOff + Dimen, XOff + Dimen,
  168.                YOff + Inf->bi_Width/2 );
  169. }
  170.  
  171.  
  172. VOID DrawBoard( BoardInfo *Inf )
  173. {
  174.     SetAPen( Inf->bi_Rast, 1 );
  175.     SloppyLine( Inf, Inf->bi_XOff + Inf->bi_Length/3, Inf->bi_YOff,
  176.                Inf->bi_XOff + Inf->bi_Length/3,
  177.                Inf->bi_Hei - Inf->bi_YOff - 1 );
  178.     SloppyLine( Inf, Inf->bi_XOff + 2*Inf->bi_Length/3, Inf->bi_YOff,
  179.                Inf->bi_XOff + 2*Inf->bi_Length/3,
  180.                Inf->bi_Hei - Inf->bi_YOff - 1 );
  181.     SloppyLine( Inf, Inf->bi_XOff, Inf->bi_YOff + Inf->bi_Length/3,
  182.                Inf->bi_Wid - Inf->bi_XOff - 1,
  183.                Inf->bi_YOff + Inf->bi_Length/3 );
  184.     SloppyLine( Inf, Inf->bi_XOff, Inf->bi_YOff + 2*Inf->bi_Length/3,
  185.                Inf->bi_Wid - Inf->bi_XOff - 1,
  186.                Inf->bi_YOff + 2*Inf->bi_Length/3 );
  187. }
  188.  
  189. LONG CheckForWin( LONG *Board, BoardInfo *Inf )
  190. {
  191.     if( Inf )
  192.         SetAPen( Inf->bi_Rast, 1 );
  193.     
  194.     /* Check horizontal wins */
  195.     if( Board[0] && Board[0] == Board[1] && Board[0] == Board[2] )
  196.     {
  197.         if( Inf )
  198.             SloppyLine( Inf, Inf->bi_XOff, Inf->bi_YOff + Inf->bi_Length/6,
  199.                        Inf->bi_XOff + Inf->bi_Length - 1,
  200.                        Inf->bi_YOff + Inf->bi_Length/6 );
  201.         return Board[0];
  202.     }
  203.     if( Board[3] && Board[3] == Board[4] && Board[3] == Board[5] )
  204.     {
  205.         if( Inf )
  206.             SloppyLine( Inf, Inf->bi_XOff, Inf->bi_YOff + 3*Inf->bi_Length/6,
  207.                        Inf->bi_XOff + Inf->bi_Length - 1,
  208.                        Inf->bi_YOff + 3*Inf->bi_Length/6 );
  209.         return Board[3];
  210.     }
  211.     if( Board[6] && Board[6] == Board[7] && Board[6] == Board[8] )
  212.     {
  213.         if( Inf )
  214.             SloppyLine( Inf, Inf->bi_XOff, Inf->bi_YOff + 5*Inf->bi_Length/6,
  215.                        Inf->bi_XOff + Inf->bi_Length - 1,
  216.                        Inf->bi_YOff + 5*Inf->bi_Length/6 );
  217.         return Board[6];
  218.     }
  219.     
  220.     /* Check vertical wins */
  221.     if( Board[0] && Board[0] == Board[3] && Board[0] == Board[6] )
  222.     {
  223.         if( Inf )
  224.             SloppyLine( Inf, Inf->bi_XOff + Inf->bi_Length/6,
  225.                        Inf->bi_YOff, Inf->bi_XOff + Inf->bi_Length/6,
  226.                        Inf->bi_YOff + Inf->bi_Length - 1 );
  227.         return Board[0];
  228.     }
  229.     if( Board[1] && Board[1] == Board[4] && Board[1] == Board[7] )
  230.     {
  231.         if( Inf )
  232.             SloppyLine( Inf, Inf->bi_XOff + 3*Inf->bi_Length/6,
  233.                        Inf->bi_YOff, Inf->bi_XOff + 3*Inf->bi_Length/6,
  234.                        Inf->bi_YOff + Inf->bi_Length - 1 );
  235.         return Board[1];
  236.     }
  237.     if( Board[2] && Board[2] == Board[5] && Board[2] == Board[8] )
  238.     {
  239.         if( Inf )
  240.             SloppyLine( Inf, Inf->bi_XOff + 5*Inf->bi_Length/6,
  241.                        Inf->bi_YOff, Inf->bi_XOff + 5*Inf->bi_Length/6,
  242.                        Inf->bi_YOff + Inf->bi_Length - 1 );
  243.         return Board[2];
  244.     }
  245.     
  246.     /* Check diagonal wins */
  247.     if( Board[0] && Board[0] == Board[4] && Board[0] == Board[8] )
  248.     {    
  249.         if( Inf )
  250.             SloppyLine( Inf, Inf->bi_XOff, Inf->bi_YOff,
  251.                        Inf->bi_XOff + Inf->bi_Length - 1,
  252.                        Inf->bi_YOff + Inf->bi_Length - 1 );
  253.         return Board[0];
  254.     }
  255.     if( Board[2] && Board[2] == Board[4] && Board[2] == Board[6] )
  256.     {
  257.         if( Inf )
  258.             SloppyLine( Inf, Inf->bi_XOff, Inf->bi_YOff + Inf->bi_Length - 1,
  259.                        Inf->bi_XOff + Inf->bi_Length - 1, Inf->bi_YOff );
  260.         return Board[2];
  261.     }
  262.  
  263.     return FALSE;
  264. }
  265.  
  266. LONG Slots( LONG *Board )
  267. {
  268.     LONG i, NumSlots = 9;
  269.  
  270.     for( i = 0; i < 9; i++ )
  271.         NumSlots -= ( Board[i] ? 1 : 0 );
  272.  
  273.     return NumSlots;
  274. }
  275.  
  276. LONG Hypothesise( LONG *Board, LONG Player )
  277. {
  278.     LONG i;
  279.  
  280.     for( i = 0; i < 9; i++ )
  281.     {
  282.         if( !Board[i] )
  283.         {
  284.             Board[i] = Player;
  285.             if( CheckForWin( Board, 0L ) == Player )
  286.             {
  287.                 Board[i] = 0;
  288.                 return i;
  289.             }
  290.             Board[i] = 0;
  291.         }
  292.     }
  293.  
  294.     return -1;
  295. }
  296.  
  297. LONG PlayGame( BoardInfo *Inf, LONG *Board )
  298. {
  299.     LONG RetVal, i, CurMove, CurPlayer = PLAYER_X, Winner;
  300.  
  301.     SetRast( Inf->bi_Rast, 0 );
  302.     DrawBoard( Inf );
  303.  
  304.     for( i = 0; i < 9; i++ )
  305.         Board[i] = 0;
  306.  
  307.     do
  308.     {
  309.         if(( RetVal = SafeDelay( Inf->bi_MoveDelay )) != OK )
  310.             break;
  311.         
  312.         /* Go for the win. */
  313.         CurMove = Hypothesise( Board, CurPlayer );
  314.         if( CurMove == -1 )
  315.         {
  316.             LONG Other = ( CurPlayer == PLAYER_X ? PLAYER_O : PLAYER_X );
  317.  
  318.             /* Go for the block. */
  319.             CurMove = Hypothesise( Board, Other );
  320.             if( CurMove == -1 )
  321.             {
  322.                 CurMove = RangeRand( Slots( Board )) + 1;
  323.                 for( i = 0; i < 9; i++ )
  324.                 {
  325.                     if( !Board[i] )
  326.                         CurMove--;
  327.                     if( !CurMove )
  328.                     {
  329.                         CurMove = i;
  330.                         break;
  331.                     }
  332.                 }
  333.             }
  334.         }
  335.         Board[CurMove] = CurPlayer;
  336.         if( CurPlayer == PLAYER_X )
  337.         {
  338.             DrawX( Inf, CurMove );
  339.             CurPlayer = PLAYER_O;
  340.         }
  341.         else
  342.         {
  343.             DrawO( Inf, CurMove );
  344.             CurPlayer = PLAYER_X;
  345.         }
  346.         Winner = CheckForWin( Board, Inf );
  347.     }
  348.     while( !Winner && Slots( Board ));
  349.     
  350.     if( RetVal == OK )
  351.         return SafeDelay( Inf->bi_GameDelay );
  352.     else
  353.         return RetVal;
  354. }
  355.  
  356. LONG Blank( PrefOb