home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 22 / AACD 22.iso / AACD / Games / Connect4 / source / gameboardclass.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-13  |  22.8 KB  |  672 lines

  1. #include "gameboardclass.h"
  2. #include "graphics_support.h"
  3. #include "computer_player.h"
  4. #include <hardware/blit.h>
  5. #include <stdio.h>
  6.  
  7. // Uncomment these to debug
  8. //#define GAMEBOARDCLASS_DEBUG
  9. //#define GRID_DEBUG
  10.  
  11. __saveds ULONG gameboardDispatcher (__reg("a0") struct IClass *cl,
  12.                                     __reg("a2") Object *obj,
  13.                                     __reg("a1") Msg msg)
  14. {
  15.     switch (msg->MethodID)
  16.     {
  17.         case OM_NEW             : return(gameboardNew           (cl, obj, msg));
  18.         case OM_DISPOSE         : return(gameboardDispose       (cl, obj, msg));
  19.         case OM_SET             : return(gameboardSet           (cl, obj, (struct opSet *)msg));
  20.         case OM_GET             : return(gameboardGet           (cl, obj, (struct opGet *)msg));
  21.         case MUIM_Draw          : return(gameboardDraw          (cl, obj, (struct MUIP_Draw *)msg));
  22.         case MUIM_HandleInput   : return(gameboardHandleInput   (cl, obj, (struct MUIP_HandleInput *)msg));
  23.         case MUIM_Setup         : return(gameboardSetup         (cl, obj, (struct MUIP_Setup *)msg));
  24.         case MUIM_Cleanup       : return(gameboardCleanup       (cl, obj, (struct MUIP_CleanUp *)msg));
  25.         case MUIM_Gameboard_MakeMove  : return(gameboardMakeMove (cl,obj, msg));
  26.     }
  27.  
  28.     return (DoSuperMethodA(cl, obj, msg));
  29. }
  30.  
  31. __saveds ULONG gameboardNew (struct IClass *cl, Object *obj, Msg *msg)
  32. {
  33.     struct gameboarddata *gb_data;
  34.  
  35.     if (!(obj=(Object *)DoSuperMethodA(cl, obj, msg)))
  36.         return 0;
  37.  
  38.     gb_data=INST_DATA(cl, obj);
  39.  
  40.     // Initialise the columntop[] and filled[][] arrays to -1
  41.     {
  42.         int i, j;
  43.  
  44.         for (i=0; i<7; i++)
  45.         {
  46.             gb_data->columntop[i]=-1;
  47.             for (j=0; j<5; j++)
  48.                 gb_data->filled[i][j]=-1;
  49.         }
  50.     }
  51.     
  52.     gb_data->current_player=red_player; // red player goes first
  53.  
  54.     gb_data->inputactive=FALSE;         // Can't play until this is TRUE
  55.     gb_data->restartgameboard=FALSE;
  56.  
  57.     loadiff("PROGDIR:gfx/red_counter",    &gb_data->red_width,    &gb_data->red_height,    &gb_data->red_depth,    NULL, &gb_data->red_body,    &gb_data->red_palette);
  58.     loadiff("PROGDIR:gfx/yellow_counter", &gb_data->yellow_width, &gb_data->yellow_height, &gb_data->yellow_depth, NULL, &gb_data->yellow_body, &gb_data->yellow_palette);
  59.    
  60.     return ((ULONG)obj);
  61. }
  62.  
  63. __saveds ULONG gameboardDispose (struct IClass *cl, Object *obj, Msg *msg)
  64. {
  65.     struct gameboarddata *gb_data=INST_DATA(cl, obj);
  66.     
  67.     // Free everything that loadiff() allocated for us
  68.     free(gb_data->red_palette);
  69.     free(gb_data->red_body);
  70.  
  71.     free(gb_data->yellow_palette);
  72.     free(gb_data->yellow_body);
  73.  
  74.     return (DoSuperMethodA(cl, obj, msg));
  75. }
  76.  
  77.  
  78. __saveds ULONG gameboardSet (struct IClass *cl, Object *obj, struct opSet *msg)
  79. {
  80.     {
  81.         struct TagItem *ti, *tstate;
  82.         struct gameboarddata *gb_data=INST_DATA(cl, obj);
  83.  
  84.         ti=msg->ops_AttrList;
  85.         tstate=ti;
  86.     
  87.         while (ti = NextTagItem(&tstate))
  88.         {
  89.             switch (ti->ti_Tag)
  90.             {
  91.                 case MUIA_Gameboard_CurrentPlayer:
  92.                         gb_data->current_player=ti->ti_Data;
  93.                         /*
  94.                         ** FOR SOME REASON, THIS IS A BIG NO-NO!!!!!!!!!!!
  95.                         **
  96.                         // Build a message and send it to the Notify class (our superclass)
  97.                         {
  98.                             struct TagItem tt[2];
  99.  
  100.                             tt[0].ti_Tag=ti->ti_Tag;
  101.                             tt[1].ti_Data=ti->ti_Data;
  102.                             tt[2].ti_Tag=TAG_DONE;
  103.  
  104.                             DoSuperMethod(cl, obj, OM_NOTIFY, tt, msg->ops_GInfo, 0L);
  105.                         }
  106.                         */
  107.                         break;
  108.  
  109.                 case MUIA_Gameboard_Inputactive:
  110.                         gb_data->inputactive=ti->ti_Data;
  111.                         break;
  112.  
  113.                 case MUIA_Gameboard_Winner:
  114.                         gb_data->winning_player=ti->ti_Data;
  115.                         break;
  116.  
  117.                 case MUIA_Gameboard_Restart:
  118.                         gb_data->restartgameboard=ti->ti_Data;
  119.                         MUI_Redraw(obj, MADF_DRAWUPDATE);
  120.                         break;
  121.  
  122.                 case MUIA_Gameboard_Tiegame:
  123.                         gb_data->tiegame=ti->ti_Data;
  124.                         break;
  125.  
  126.                 case MUIA_Gameboard_RedPlayer:
  127.                         gb_data->opponent[red_player].type=ti->ti_Data;
  128.                         break;
  129.  
  130.                 case MUIA_Gameboard_YellowPlayer:
  131.                         gb_data->opponent[yellow_player].type=ti->ti_Data;
  132.                         break;
  133.  
  134.                 case MUIA_Gameboard_RedDetail:
  135.                         gb_data->opponent[red_player].data=ti->ti_Data;
  136.                         break;
  137.  
  138.                 case MUIA_Gameboard_YellowDetail:
  139.                         gb_data->opponent[yellow_player].data=ti->ti_Data;
  140.                         break;
  141.             }
  142.         }
  143.     }
  144.     return (DoSuperMethodA(cl, obj, (Msg)msg));
  145. }
  146.  
  147. __saveds ULONG gameboardGet (struct IClass *cl, Object *obj, struct opGet *msg)
  148. {
  149.     struct gameboarddata *gb_data=INST_DATA(cl, obj);
  150.  
  151.     switch (msg->opg_AttrID)
  152.     {
  153.         case MUIA_Gameboard_CurrentPlayer:
  154.             *(msg->opg_Storage)=gb_data->current_player;
  155.             return TRUE;
  156.  
  157.         case MUIA_Gameboard_RedPlayer:
  158.             *(msg->opg_Storage)=gb_data->opponent[red_player].type;
  159.             return TRUE;
  160.  
  161.         case MUIA_Gameboard_YellowPlayer:
  162.             *(msg->opg_Storage)=gb_data->opponent[yellow_player].type;
  163.             return TRUE;
  164.  
  165.         case MUIA_Gameboard_RedDetail:
  166.             *(msg->opg_Storage)=gb_data->opponent[red_player].data;
  167.             return TRUE;
  168.  
  169.         case MUIA_Gameboard_YellowDetail:
  170.             *(msg->opg_Storage)=gb_data->opponent[yellow_player].data;
  171.             return TRUE;
  172.     }
  173.  
  174.     return(DoSuperMethodA(cl, obj, (Msg)msg));
  175. }
  176.  
  177.  
  178. __saveds ULONG gameboardDraw (struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
  179. {
  180.     DoSuperMethodA(cl, obj, (Msg)msg);
  181.  
  182.     if (msg->flags & MADF_DRAWOBJECT)
  183.     {
  184.         struct gameboarddata *gb_data=INST_DATA(cl, obj);
  185.         int column, row;
  186.  
  187.         for (column=0; column<7; column++)
  188.         {
  189.             for (row=0; row<5; row++)
  190.             {
  191.                 if (gb_data->filled[column][row]==red_player)
  192.                 {
  193.                     BltMaskBitMapRastPort(gb_data->red_bitmap, 0, 0, _rp(obj),
  194.                                           _mleft(obj)+13+(column*60)+7, _mtop(obj)+12+((4-row)*60)+7,
  195.                                           gb_data->red_width, gb_data->red_height,
  196.                                           (ABC|ABNC|ANBC), gb_data->mask_bitmap->Planes[0]);
  197.                 }
  198.                 else if (gb_data->filled[column][row]==yellow_player)
  199.                 {
  200.                     BltMaskBitMapRastPort(gb_data->yellow_bitmap, 0, 0, _rp(obj),
  201.                                           _mleft(obj)+13+(column*60)+7, _mtop(obj)+12+((4-row)*60)+7,
  202.                                           gb_data->yellow_width, gb_data->yellow_height,
  203.                                           (ABC|ABNC|ANBC), gb_data->mask_bitmap->Planes[0]);
  204.                 }
  205.             }
  206.         }
  207.     }
  208.     else if (msg->flags & MADF_DRAWUPDATE)
  209.     {
  210.         struct gameboarddata *gb_data=INST_DATA(cl, obj);
  211.         
  212.         if (gb_data->restartgameboard)
  213.         {
  214.             // Initialise the columntop[] and filled[][] arrays to -1
  215.             {
  216.                 int i, j;
  217.  
  218.                 for (i=0; i<7; i++)
  219.                 {
  220.                     gb_data->columntop[i]=-1;
  221.                     for (j=0; j<5; j++)
  222.                         gb_data->filled[i][j]=-1;
  223.                 }
  224.             }
  225.  
  226.             gb_data->current_player=red_player; // red player goes first
  227.             gb_data->inputactive=FALSE;         // Can't play until this is TRUE
  228.             gb_data->restartgameboard=FALSE;
  229.  
  230.             // Clear all the pieces
  231.             {
  232.                 int column, row;
  233.  
  234.                 for (column=0; column<7; column++)
  235.                 {
  236.                     for (row=0; row<5; row++)
  237.                     {
  238.                         BltMaskBitMapRastPort(gb_data->blank_bitmap, 0, 0, _rp(obj),
  239.                                               _mleft(obj)+13+(column*60)+7, _mtop(obj)+12+((4-row)*60)+7,
  240.                                               gb_data->blank_width, gb_data->blank_height,
  241.                                               (ABC|ABNC|ANBC), gb_data->mask_bitmap->Planes[0]);
  242.                     }
  243.                 }
  244.             }
  245.         }
  246.         else
  247.         {
  248.             if (gb_data->current_player==red_player)
  249.             {
  250.                 BltMaskBitMapRastPort(gb_data->red_bitmap, 0, 0, _rp(obj),
  251.                                       gb_data->counterx, gb_data->countery,
  252.                                       gb_data->red_width, gb_data->red_height,
  253.                                       (ABC|ABNC|ANBC), gb_data->mask_bitmap->Planes[0]);
  254.             }
  255.             else
  256.             {
  257.                 BltMaskBitMapRastPort(gb_data->yellow_bitmap, 0, 0, _rp(obj),
  258.                                       gb_data->counterx, gb_data->countery,
  259.                                       gb_data->yellow_width, gb_data->yellow_height,
  260.                                       (ABC|ABNC|ANBC), gb_data->mask_bitmap->Planes[0]);
  261.             }
  262.         }
  263.     }
  264.  
  265.     return 0;
  266. }
  267.  
  268. __saveds ULONG gameboardHandleInput (struct IClass *cl, Object *obj, struct MUIP_HandleInput *msg)
  269. {
  270.     #define _isbetween(a, x, b) ((x)>=(a) && (x)<=(b))
  271.     #define _isinobject(x, y) (_isbetween(_mleft(obj), (x), _mright(obj))  \
  272.                             && _isbetween(_mtop(obj), (y), _mbottom(obj)))
  273.  
  274.     struct gameboarddata *gb_data=INST_DATA(cl, obj);
  275.  
  276.     if (gb_data->inputactive)
  277.     {
  278.         if (msg->imsg)
  279.         {
  280.             if (msg->imsg->Class==IDCMP_MOUSEBUTTONS)
  281.             {
  282.                 if (msg->imsg->Code==SELECTDOWN)
  283.                 {
  284.                     if (_isinobject(msg->imsg->MouseX, msg->imsg->MouseY))
  285.                     {
  286.                         int column;
  287.  
  288.                         if ((column=msg->imsg->MouseX-_mleft(obj)-13)>=0)
  289.                         {
  290.                             column=column/60;
  291.  
  292.                             if (column>=0 && column<=6)
  293.                             {
  294.                                 if (gb_data->columntop[column]<4)
  295.                                 {
  296.                                     gb_data->column=column;
  297.                                     DoMethod(obj, MUIM_Gameboard_MakeMove);
  298.                                 }
  299.                             }
  300.                         }
  301.                     }
  302.                 }
  303.             }
  304.         }
  305.     }
  306.  
  307.     return 0;
  308. }
  309.  
  310. __saveds ULONG gameboardSetup (struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
  311. {
  312.     if (!(DoSuperMethodA(cl, obj, (Msg)msg)))
  313.         return (FALSE);
  314.  
  315.     {
  316.         struct gameboarddata *gb_data=INST_DATA(cl, obj);
  317.         UBYTE mask_body[270] =
  318.         {
  319.             /* Plane 0 */
  320.             0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
  321.             0x80, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0xFF,
  322.             0xFF, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x00,
  323.             0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xFF,
  324.             0xFF, 0x80, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF,
  325.             0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
  326.             0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
  327.             0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF,
  328.             0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8,
  329.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
  330.             0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF,
  331.             0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
  332.             0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xFF,
  333.             0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFF,
  334.             0xFF, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xF8, 0x00,
  335.             0x00, 0x7F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
  336.             0x80, 0x00, 0x00, 0x01, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00
  337.         };
  338.  
  339.         UBYTE blank_body[270] =
  340.         {
  341.             /*Plane 0*/
  342.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  343.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  344.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  345.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  346.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  347.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  348.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  349.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  350.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  351.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  352.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  353.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  354.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  355.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  356.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  357.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  358.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  359.         };
  360.  
  361.         // Create red counter bitmap
  362.         gb_data->red_bitmap=bodytobitmap(gb_data->red_width, gb_data->red_height, gb_data->red_depth, gb_data->red_body);
  363.  
  364.         // Create yellow counter bitmap
  365.         gb_data->yellow_bitmap=bodytobitmap(gb_data->yellow_width, gb_data->yellow_height, gb_data->yellow_depth, gb_data->yellow_body);
  366.  
  367.         // Create counter mask bitmap
  368.         gb_data->mask_bitmap=bodytobitmap(45, 45, 1, mask_body);
  369.  
  370.         // Create blank square bitmap
  371.         gb_data->blank_width=45;
  372.         gb_data->blank_height=45;
  373.         gb_data->blank_depth=1;
  374.         gb_data->blank_bitmap=bodytobitmap(gb_data->blank_width, gb_data->blank_height, gb_data->blank_depth, blank_body);
  375.         // and set up its palette
  376.         {
  377.             int i;
  378.             for (i=0; i<3; i++)
  379.             {
  380.                 gb_data->blank_palette[i]  =0x00000000;
  381.                 gb_data->blank_palette[i+3]=0xFFFFFFFF;
  382.             }
  383.         }
  384.  
  385.         {
  386.             struct Screen *screen=_screen(obj);
  387.             int i;
  388.  
  389.             // Initialise allocated pen array
  390.             for (i=0; i<GAMEBOARD_PENS; i++)
  391.             {
  392.                 gb_data->pens[i].number=-1;
  393.                 gb_data->pens[i].red=0;
  394.                 gb_data->pens[i].green=0;
  395.                 gb_data->pens[i].blue=0;
  396.             }
  397.  
  398.             // Remap colours in red and yellow counter bitmaps
  399.             #ifdef GRAPHICS_SUPPORT_DEBUG
  400.             puts("##red bitmap");
  401.             #endif
  402.             remapbitmap(gb_data->red_bitmap, screen->ViewPort.ColorMap, gb_data->red_palette, gb_data->pens, GAMEBOARD_PENS);
  403.  
  404.             #ifdef GRAPHICS_SUPPORT_DEBUG
  405.             puts("##yellow bitmap");
  406.             #endif
  407.             remapbitmap(gb_data->yellow_bitmap, screen->ViewPort.ColorMap, gb_data->yellow_palette, gb_data->pens, GAMEBOARD_PENS);
  408.  
  409.             #ifdef GRAPHICS_SUPPORT_DEBUG
  410.             puts("##blank bitmap");
  411.             #endif
  412.             remapbitmap(gb_data->blank_bitmap, screen->ViewPort.ColorMap, gb_data->blank_palette, gb_data->pens, GAMEBOARD_PENS);
  413.         }
  414.  
  415.     }
  416.  
  417.     MUI_RequestIDCMP(obj, IDCMP_MOUSEBUTTONS);
  418.  
  419.     return (TRUE);
  420. }
  421.  
  422.  
  423. __saveds ULONG gameboardCleanup (struct IClass *cl, Object *obj, struct MUIP_CleanUp *msg)
  424. {
  425.     struct gameboarddata *gb_data=INST_DATA(cl, obj);
  426.     struct Screen *screen=_screen(obj);
  427.  
  428.     freeallocatedpens(screen->ViewPort.ColorMap, gb_data->pens, GAMEBOARD_PENS);
  429.  
  430.     FreeBitMap(gb_data->red_bitmap);
  431.     FreeBitMap(gb_data->yellow_bitmap);
  432.     FreeBitMap(gb_data->mask_bitmap);
  433.     FreeBitMap(gb_data->blank_bitmap);
  434.  
  435.     MUI_RejectIDCMP(obj, IDCMP_MOUSEBUTTONS);
  436.  
  437.     return (DoSuperMethodA(cl, obj, (Msg)msg));
  438. }
  439.  
  440. __saveds ULONG gameboardMakeMove (struct IClass *cl, Object *obj, Msg *msg)
  441. {
  442.     struct gameboarddata *gb_data=INST_DATA(cl, obj);
  443.     int row, column=gb_data->column;
  444.  
  445.     // Overide the imported column number if the current player is non-local
  446.     if (gb_data->opponent[gb_data->current_player].type==PlayerType_Computer)
  447.     {
  448.         gb_data->column=computer_player(gb_data->opponent[gb_data->current_player].data, gb_data->filled, gb_data->columntop, gb_data->current_player, FALSE);  
  449.         if (gb_data->column==-1)    // Possible error if user enters out of range value for computer skill level...
  450.             gb_data->column=0;      // ...in which case the characteristic response will be to always go in the first column ie. pretty shitty AI !!!
  451.         column=gb_data->column;
  452.     }
  453.  
  454.     row=gb_data->columntop[column]+1;
  455.     gb_data->columntop[column]++;
  456.  
  457.     gb_data->filled[column][row]=gb_data->current_player;
  458.  
  459.     #ifdef GRID_DEBUG
  460.     {
  461.         char i, j;
  462.  
  463.         for (i=4; i>=0; i--)
  464.         {
  465.             for (j=0; j<7; j++)
  466.                 printf("%2.d ", gb_data->filled[j][i]);
  467.             printf("\n");
  468.         }
  469.         printf("\n");
  470.     }
  471.     #endif
  472.  
  473.  
  474.     gb_data->row=row;
  475.     gb_data->counterx=_mleft(obj)+13+(column*60)+7;
  476.     gb_data->countery=_mtop(obj)+12+((4-row)*60)+7;
  477.     MUI_Redraw(obj, MADF_DRAWUPDATE);
  478.     if (!testwinordraw(obj, gb_data))   // if the game isn't over, change player
  479.     {
  480.         if (gb_data->current_player==red_player)
  481.             SetAttrs(obj, MUIA_Gameboard_CurrentPlayer, yellow_player, TAG_DONE);
  482.         else
  483.             SetAttrs(obj, MUIA_Gameboard_CurrentPlayer, red_player, TAG_DONE);
  484.     }
  485.  
  486.     return 0;
  487. }
  488.  
  489.  
  490. BOOL testwinordraw (Object *obj, struct gameboarddata *gb_data)
  491. {
  492.     char result, winner=-1;
  493.     if ((result=testS(gb_data, gb_data->column, gb_data->row))>=0)
  494.         winner=result;
  495.  
  496.     if ((result=testWE(gb_data, gb_data->column, gb_data->row))>=0)
  497.         winner=result;
  498.  
  499.     if ((result=testNESW(gb_data, gb_data->column, gb_data->row))>=0)
  500.         winner=result;
  501.  
  502.     if ((result=testNWSE(gb_data, gb_data->column, gb_data->row))>=0)
  503.         winner=result;
  504.  
  505.     if (winner>=0)
  506.     {
  507.         SetAttrs(obj, MUIA_Gameboard_Winner, winner, TAG_DONE);
  508.         return TRUE;
  509.     }
  510.     else if (fullboard(gb_data))
  511.     {
  512.         SetAttrs(obj, MUIA_Gameboard_Tiegame, TRUE, TAG_DONE);
  513.         return TRUE;
  514.     }
  515.  
  516.     return FALSE;
  517. }
  518.  
  519. /* Test from current position->South
  520. **
  521. **                               +
  522. **                               |
  523. **
  524. ** RESULT:
  525. **          red_player or yellow_player, or -1 if no-one has won
  526. */
  527. char testS (struct gameboarddata *gb_data, int column, int row)
  528. {
  529.     if (row>=3)
  530.     {
  531.         char total, i;
  532.  
  533.         total=0;
  534.         for (i=row; i>=(row-3); i--)
  535.             total+=gb_data->filled[column][i];
  536.  
  537.         if (total==0)
  538.             return red_player;
  539.         else if (total==4)
  540.             return yellow_player;
  541.         else
  542.             return -1;
  543.     }
  544.     else
  545.         return -1;
  546. }
  547.  
  548. /* Test from current position->West and from current position->East
  549. **
  550. **                             --+--
  551. **
  552. ** RESULT:
  553. **          red_player or yellow_player, or -1 if no-one has won
  554. */
  555. char testWE (struct gameboarddata *gb_data, int column, int row)
  556. {
  557.     char total, i;
  558.  
  559.     total=0;
  560.     for (i=0; i<7; i++)
  561.     {
  562.         if (gb_data->filled[i][row]==gb_data->current_player)
  563.             total++;
  564.         else if (total>=4)
  565.             break;
  566.         else
  567.             total=0;
  568.         #ifdef GAMEBOARDCLASS_DEBUG
  569.         printf("WE total=%d\n", total);
  570.         #endif
  571.     }
  572.  
  573.     if (total>=4)
  574.         return gb_data->current_player;
  575.     else
  576.         return -1;
  577. }
  578.  
  579. /* Test from current position->NorthEast and from current position->SouthWest
  580. **
  581. **                                /
  582. **                               +
  583. **                              /
  584. **
  585. ** RESULT:
  586. **          red_player or yellow_player, or -1 if no-one has won
  587. */
  588. char testNESW(struct gameboarddata *gb_data, int column, int row)
  589. {
  590.     char diagrow=0;
  591.     char total=0;
  592.     char diagcolumn;
  593.  
  594.     for (diagcolumn=column-row; diagrow<5; diagcolumn++)
  595.     {
  596.         if (diagcolumn>=0 && diagcolumn<=6)
  597.         {
  598.             if (gb_data->filled[diagcolumn][diagrow]==gb_data->current_player)
  599.                 total++;
  600.             else if (total>=4)
  601.                 break;
  602.             else
  603.                 total=0;
  604.             #ifdef GAMEBOARDCLASS_DEBUG
  605.             printf("NESW total=%d\n", total);
  606.             #endif
  607.         }
  608.  
  609.         diagrow++;
  610.     }
  611.  
  612.     if (total>=4)
  613.         return gb_data->current_player;
  614.     else
  615.         return -1;
  616. }
  617.  
  618. /* Test from current position->NorthWest and from current position->SouthEast
  619. **
  620. **                              \
  621. **                               +
  622. ++                                \
  623. **
  624. ** RESULT:
  625. **          red_player or yellow_player, or -1 if no-one has won
  626. */
  627. char testNWSE(struct gameboarddata *gb_data, int column, int row)
  628. {
  629.     char diagrow=0;
  630.     char total=0;
  631.     char diagcolumn;
  632.  
  633.     for (diagcolumn=column+row; diagrow<5; diagcolumn--)
  634.     {
  635.         if (diagcolumn>=0 && diagcolumn<=6)
  636.         {
  637.             if (gb_data->filled[diagcolumn][diagrow]==gb_data->current_player)
  638.                 total++;
  639.             else if (total>=4)
  640.                 break;
  641.             else
  642.                 total=0;
  643.             #ifdef GAMEBOARDCLASS_DEBUG
  644.             printf("NWSE total=%d\n", total);
  645.             #endif
  646.         }
  647.  
  648.         diagrow++;
  649.     }
  650.  
  651.     if (total>=4)
  652.         return gb_data->current_player;
  653.     else
  654.         return -1;
  655.     
  656. }
  657.  
  658.  
  659. BOOL fullboard(struct gameboarddata *gb_data)
  660. {
  661.     char i;
  662.  
  663.     for (i=0; i<7; i++)
  664.     {
  665.         if (gb_data->filled[i][4]==-1)
  666.             return FALSE;
  667.     }
  668.     return TRUE;    // If we get to this, the board is full!
  669. }
  670.  
  671.  
  672.