home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 248.lha / Connect_4 / Connect4.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-29  |  45.4 KB  |  1,379 lines

  1. /*      Connect4.C - A simulation
  2. *
  3. *       Mitchell/Ware           Version 2.05            12/6/87
  4. *
  5. *       Graphics included:
  6. *               rc4c_Image      -       Red Chip
  7. *               bc4c_Image      -       Blue Chip
  8. *               bc4b_Image      -       Background part of 'Board'
  9. *               bc4f_Image      -       ForeGround part of 'Board'
  10. *               Play_Image      -       The Play Gadget
  11. *               Level_Image     -       The Level Gadget
  12. *               Info_Image      -       Information about game
  13. *               Back_Image      -       Icon to put this screen to back
  14. *               Quit_Image      -       End Game
  15. *
  16. *
  17. *       NOTE: UserData on gadgets will point to routines to be called
  18. *               in case of gadget activation. They will return something.
  19. */
  20.  
  21. #include "exec/types.h"
  22. #include "exec/memory.h"
  23. #include "exec/tasks.h"
  24. #include "intuition/intuition.h"
  25. #include "graphics/gfx.h"
  26. #include "graphics/gfxmacros.h"
  27. #include "graphics/display.h"
  28. #include "graphics/rastport.h"
  29. #include "graphics/gels.h"
  30. #include "clib/macros.h"
  31. #include <stdio.h>
  32. #include <setjmp.h>
  33. #include <ascii.h>
  34. #include <math.h>
  35. #include <Iff.h>
  36. #include <Tools.h>
  37. #include <connect4.h>   
  38.  
  39. #define MAGIC_LOCKOUT   666
  40.  
  41. #define STACK   6000   /* size to allocate stacks of tasks */
  42.  
  43. #define CHIP    (MEMF_CHIP | MEMF_CLEAR)
  44. #define PUB     (MEMF_PUBLIC | MEMF_CLEAR)
  45.  
  46. #define NBOBS   3       /* number of BOBS in system     */
  47. #define RED     0       /* RED chip  (HUMAN)            */
  48. #define BLUE    1       /* BLUE chip (COMPUTER)         */
  49. #define BOARD   2       /* BOARD bob                    */
  50.  
  51. #define NGADS   5       /* Number of control gadgets    */
  52. #define PLAY    0       /* PLAY gadget */
  53. #define LEVEL   1
  54. #define BACK    2
  55. #define INFO    3
  56. #define QUIT    4
  57.  
  58. #define RED_CHIP_IMAGE        rc4c_Image
  59. #define BLUE_CHIP_IMAGE       bc4c_Image
  60. #define BACK_BOARD_IMAGE      bc4b_Image
  61. #define FORE_BOARD_IMAGE      bc4f_Image
  62.  
  63. #define GADR            (-Play_Image->Width)
  64. #define GADT(_x)        (20 + (_x) * Play_Image->Height)
  65.  
  66. #define BTOP    30      /* distance of board from top   */
  67. #define BLEFT   -10     /* distance of board from left */
  68. #define BS_TOP  24      /* board starts relative to BTOP */
  69. #define BS_LEFT 28      /* board starts relative to BLEFT */
  70. #define BWIDTH  27      /* board width of one chip      */
  71. #define BHEIGHT 23      /* board height of one chip     */
  72.  
  73. #define IDCMP_SET       (REQCLEAR | MOUSEBUTTONS | GADGETUP | INTUITICKS | MOUSEMOVE)
  74.  
  75. extern struct  Screen  *OpenScreen();
  76. extern struct  Window  *OpenWindow();
  77.  
  78. struct Image *rc4c_Image;
  79. struct Image *bc4c_Image;
  80. struct Image *bc4b_Image;
  81. struct Image *bc4f_Image;
  82.  
  83. struct Image *Play_Image;
  84. struct Image *Level_Image;
  85. struct Image *Back_Image;        
  86. struct Image *Info_Image;
  87. struct Image *Quit_Image;
  88.  
  89. RTGLIST info_list[] =
  90. {
  91.         { 26, 76, 25, 17, 0, GADGHCOMP, ENDGADGET  },
  92.         { 0  }
  93. };
  94.  
  95. RTGLIST level_list[] =
  96. {
  97.         /* list of the 16 levels comes first, followed by OK-WHO-CANCEL
  98.                 and the the (useless) TREE and LINEAR. */
  99.         { 26, 97, 22, 14, 1, GADGHCOMP, TOGGLESELECT },         /* 1 */
  100.         { 50, 97, 22, 14, 2, GADGHCOMP, TOGGLESELECT },         /* 2 */
  101.         { 74, 97, 22, 14, 3, GADGHCOMP, TOGGLESELECT },         /* 3 */
  102.         { 98, 97, 22, 14, 4, GADGHCOMP, TOGGLESELECT },         /* 4 */
  103.         { 122, 97, 22, 14, 5, GADGHCOMP, TOGGLESELECT },        /* 5 */
  104.         { 146, 97, 22, 14, 6, GADGHCOMP, TOGGLESELECT },        /* 6 */
  105.         { 170, 97, 22, 14, 7, GADGHCOMP, TOGGLESELECT },        /* 7 */
  106.         { 194, 97, 22, 14, 8, GADGHCOMP, TOGGLESELECT },        /* 8 */
  107.  
  108.         { 26, 113, 22, 14, 9, GADGHCOMP, TOGGLESELECT },        /* 9 */
  109.         { 50, 113, 22, 14, 10, GADGHCOMP, TOGGLESELECT },        /* 10 */
  110.         { 74, 113, 22, 14, 11, GADGHCOMP, TOGGLESELECT },        /* 11 */
  111.         { 98, 113, 22, 14, 12, GADGHCOMP, TOGGLESELECT },        /* 12 */
  112.         { 122, 113, 22, 14, 13, GADGHCOMP, TOGGLESELECT },       /* 13 */
  113.         { 146, 113, 22, 14, 14, GADGHCOMP, TOGGLESELECT },       /* 14 */
  114.         { 170, 113, 22, 14, 15, GADGHCOMP, TOGGLESELECT },       /* 15 */
  115.         { 194, 113, 22, 14, 16, GADGHCOMP, TOGGLESELECT },       /* 16 */
  116.         
  117.         { 32, 138, 32, 6, 0, GADGHCOMP, ENDGADGET | TOGGLESELECT }, /* OK */
  118.         { 103, 138, 32, 6, 0, GADGHCOMP, GADGIMMEDIATE }, /* WHO */
  119.         { 176, 138, 32, 6, 0, GADGHCOMP, ENDGADGET | TOGGLESELECT }, /* CANCEL */
  120.         
  121.         { 22, 44, 42, 15, 0, GADGHCOMP | SELECTED, TOGGLESELECT, NULL, TRUE }, /* TREE */
  122.         { 168, 44, 51, 15, 0, GADGHCOMP | GADGDISABLED, TOGGLESELECT }, /* LINEAR */
  123.         
  124.         { 0 }        
  125. };
  126.  
  127. RTGLIST who_list[] =
  128. {
  129.         { 19, 47, 56, 14, 0, GADGHCOMP, TOGGLESELECT }, /* left HUMAN */
  130.         { 19, 72, 56, 14, 0, GADGHCOMP, TOGGLESELECT }, /* left COMPUTER */
  131.         { 131, 47, 56, 14, 0, GADGHCOMP, TOGGLESELECT }, /* right HUMAN */
  132.         { 131, 72, 56, 14, 0, GADGHCOMP, TOGGLESELECT }, /* right COMPUTER */
  133.         
  134.         { 65, 97, 32, 6, 0, GADGHCOMP, TOGGLESELECT | ENDGADGET }, /* OK */
  135.         { 113, 97, 32, 6, 0, GADGHCOMP, TOGGLESELECT | ENDGADGET }, /* CANCEL */
  136.         { 0 }        
  137. };
  138.  
  139. struct NewScreen       NewHS =
  140. {
  141.         0, 0, 320, 200, 5,      /* left, right, width, height, depth */
  142.         1, 30,                  /* Detail pen & Block pen       */
  143.         NULL,              /* View modes   */
  144.         CUSTOMSCREEN,           /* Type         */
  145.         NULL,                   /* Font         */
  146.         "Connect-4 (c) 1987-88 Mitchell/Ware",  /* Title Bar */
  147.         NULL,                   /* Gadgets - not used at this time      */
  148.         NULL                    /* Custom BitMap        */      
  149. };
  150.  
  151. struct NewWindow       NewWin  =
  152. {
  153.         0, 0,                   /* Leftedge, Topedge    */
  154.         320, 200,               /* Width, Height        */
  155.         -1, -1,                 /* DetailPen, BlockPen - default to customscr */
  156.         IDCMP_SET,              /* IDCMPflags   */
  157.         BACKDROP | BORDERLESS | ACTIVATE | RMBTRAP | SMART_REFRESH 
  158.                  | REPORTMOUSE, /* flags */
  159.         NULL,                   /* First Gadget */
  160.         NULL,                   /* Check Mark   */
  161.         NULL,                   /* Title        */
  162.         NULL,                   /* Screen - to be inited during runtime */
  163.         NULL,                   /* BitMap       */
  164.         0, 0, 0, 0,             /* MinWidth & Height, MaxWidth & Height */
  165.         CUSTOMSCREEN            /* Type */
  166. };
  167.  
  168. static struct  Screen  *screen = NULL;
  169. static struct  Window  *window = NULL;
  170. struct TmpRas  tmpras;
  171. struct AreaInfo areainfo;
  172. WORD   areabuffer[250];
  173. struct Remember *key = 0;
  174.  
  175. int    game_level = 1;
  176. int    debug_state = 0;
  177. LONG   IntuitionBase = 0;
  178. LONG   GfxBase = 0;
  179.  
  180. static jmp_buf save;
  181.  
  182. static struct GelsInfo GInfo;  
  183. static struct Bob *bob[NBOBS];
  184. static struct VSprite *vsp[NBOBS];
  185. static struct DBufPacket db[NBOBS];
  186. static struct Image **im[NBOBS] =
  187.         { &RED_CHIP_IMAGE, &BLUE_CHIP_IMAGE, &FORE_BOARD_IMAGE };
  188.         
  189. static struct Gadget *gad[NGADS];
  190.  
  191. static struct Image **ig[NGADS] = { 
  192.         &Play_Image, &Level_Image, &Back_Image, &Info_Image, &Quit_Image };
  193.  
  194. int     PlayCommand(), LevelCommand(), BackCommand(), 
  195.         InfoCommand(), QuitCommand(), 
  196.         FallTask(), PlayTask(), LeviTask();
  197.         
  198. static int (*command[NGADS])() = {
  199.         PlayCommand, LevelCommand, BackCommand, InfoCommand, QuitCommand   };
  200.  
  201. /*      MainTask Globals        ******************************
  202. */
  203. WORD    MTsig;
  204. struct  Task *ptrMainTask = NULL;
  205. C4BOARD C4Template;     /* blank template with borders set */
  206. char    dstring[100];        /* debug string */
  207. BOOL    dprint = FALSE;         /* true if printing */
  208.  
  209. /*      PlayTask Globals        ******************************
  210. */
  211. struct Task *ptrPlayTask = NULL;        /* NULL if not active */
  212. WORD    PTsig;                          /* signal number */
  213. C4BOARD MasterBoard;    /* board of current game - diff. configuration */
  214. int winner[4][2];     /* winning location of chips 0=c,1=r  */
  215.  
  216. /*      FallTask Globals        ******************************
  217. */
  218. struct  Task *ptrFallTask = NULL;        /* NULL if not active */
  219. WORD    FTsig;                  /* signal number */
  220. int     FallSlot = -1;      /* becomes 0-5 when decided, or -2 if error */
  221. BOOL    DoneFalling = FALSE; /* set to TRUE when done */
  222.  
  223. /*      LeviTask Globals    ******************************
  224. */
  225. struct  Task    *ptrLeviTask = NULL;
  226. int     LTsig;
  227. int     LTwhere = -1;   /* where to put the chip. Levitate if -1 */
  228.  
  229. #
  230. /*     Generic Main Graphics Initer
  231. */
  232.  
  233. main(ac, av)
  234. int ac;
  235. char **av;
  236. {
  237.         char *s;
  238.         int i, j;
  239.         
  240.         if (ac == 2)
  241.                 debug_state = 1;
  242.         
  243.         if (!(IntuitionBase = OpenLibrary("intuition.library", 0)))
  244.         {
  245.                 printf("Cant open intuition library");
  246.                 MainShutdown(10);
  247.         }
  248.  
  249.         if (!(GfxBase = OpenLibrary("graphics.library", 0)))
  250.         {
  251.                 printf("Cant open graphics library");
  252.                 MainShutdown(20);
  253.         }
  254.  
  255.         if (!(NewWin.Screen = screen = OpenScreen(&NewHS)))
  256.         {
  257.                 printf("Cant open Screen");
  258.                 MainShutdown(30);
  259.         }
  260.  
  261.         if (!(window = OpenWindow(&NewWin)))
  262.         {
  263.                 printf("Cant open backdrop window");
  264.                 MainShutdown(40);
  265.         }
  266.  
  267.         InitArea(&areainfo, areabuffer, 100);
  268.         window->RPort->AreaInfo = &areainfo;
  269.         window->RPort->TmpRas = (struct TmpRas *) 
  270.                 InitTmpRas(&tmpras, AllocRaster(320, 400), RASSIZE(320, 400));
  271.         if (!tmpras.RasPtr)
  272.         {
  273.                 printf("Out of Memory (45)");
  274.                 MainShutdown(45);
  275.         }
  276.  
  277. /*        if (!Icircle(512))
  278.         {
  279.                 printf("Out of memory (50)");
  280.                 MainShutdown(50);
  281.         }       */
  282.  
  283.         setmem(&C4Template, sizeof(C4BOARD), NULL);
  284.         setmem(C4Template.border1, sizeof(C4Template.border1), -2);
  285.         setmem(C4Template.border2, sizeof(C4Template.border2), -2);
  286.         for (i = 0; i < 7; ++i)
  287.                 for (j = 6; j < 9; ++j)
  288.                         C4Template.b[i][j] = -2;
  289.         
  290.         if (!(s = setjmp(save)))
  291.         {
  292.                 Startup();
  293.                 Connect4();
  294.                 s = "return from Connect4()";
  295.         }
  296.         
  297.         printf("Exit reason: <%s>\n", s);
  298.         MainShutdown(0);
  299. }
  300.  
  301. Startup ()          /* window graphics routine */
  302. {
  303.         struct  RastPort *rp = window->RPort;
  304.         struct  ViewPort *vp = &screen->ViewPort;
  305.         struct  Gadget *g;
  306.         int i;
  307.         USHORT *cm, *MakeColorMap();
  308.         int ncolors;
  309.         IFF *iff;                /* display bit2 */
  310.         struct Image *title;
  311.         
  312.         ShowTitle(screen, FALSE);
  313.         ScreenToBack(screen);
  314.         InitDoubleBuffering();
  315.         
  316.         /* Read in title page and display it */
  317.         if ((iff = IffRead("Title.Page")) && (title = MakeImage(&key, iff, NULL))) 
  318.         {
  319.                 if (cm = MakeColorMap(key, iff, &ncolors))  
  320.                         LoadRGB4(vp, cm, ncolors);
  321.                 else 
  322.                         longjmp(save, "Title.Page ColorMap problem");
  323.                 SwapBitMaps();
  324.                 DrawImage(rp, title, 0, 0);
  325.                 SwapBitMaps();
  326.                 DrawImage(rp, title, 0, 0);
  327.                 ScreenToFront(screen);
  328.         }
  329.         
  330.         
  331.         /* Read in images, and create the IMAGE */
  332.         ForgetAllOfIt();
  333.         if (!(iff = IffRead("Blue.c4.Chip"))) longjmp(save, "bc4c not found");
  334.         if (!(bc4c_Image = MakeImage(&key, iff, NULL))) longjmp(save, "bc4c - not ILBM");
  335.  
  336.         ForgetAllOfIt();
  337.         if (!(iff = IffRead("Board.c4.Back"))) longjmp(save, "bc4b.pic not found");
  338.         if (!(bc4b_Image = MakeImage(&key, iff, NULL))) longjmp(save, "bc4b - not ILBM");
  339.  
  340.         ForgetAllOfIt();
  341.         if (!(iff = IffRead("Board.c4.Front"))) longjmp(save, "bc4f.pic not found");
  342.         if (!(bc4f_Image = MakeImage(&key, iff, NULL))) longjmp(save, "bc4f - not ILBM");
  343.  
  344.         ForgetAllOfIt();
  345.         if (!(iff = IffRead("Level.Gadget"))) longjmp(save, "Level.Gadget not found");
  346.         if (!(Level_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Level - not ILBM");
  347.  
  348.         ForgetAllOfIt();
  349.         if (!(iff = IffRead("Back.Gadget"))) longjmp(save, "Back.Gadget not found");
  350.         if (!(Back_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Back - not ILBM");
  351.  
  352.         ForgetAllOfIt();
  353.         if (!(iff = IffRead("Info.Gadget"))) longjmp(save, "Info.Gadget not found");
  354.         if (!(Info_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Info - not ILBM");
  355.  
  356.         ForgetAllOfIt();
  357.         if (!(iff = IffRead("Quit.Gadget"))) longjmp(save, "Quit.Gadget not found");
  358.         if (!(Quit_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Quit - not ILBM");
  359.         
  360.         ForgetAllOfIt();
  361.         if (!(iff = IffRead("Red.c4.Chip"))) longjmp(save, "rc4c.pic not found");
  362.         if (!(rc4c_Image = MakeImage(&key, iff, NULL))) longjmp(save, "rc4c - not ILBM");
  363.         
  364.         ForgetAllOfIt();
  365.         if (!(iff = IffRead("Play.Gadget"))) longjmp(save, "Play.Gadget not found");
  366.         if (!(Play_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Play - not ILBM");
  367.  
  368.         if (cm = MakeColorMap(key, iff, &ncolors))
  369.         {
  370.                 LoadRGB4(vp, cm, ncolors);
  371.         }
  372.         else longjmp(save, "ColorMap problem");
  373.         
  374.         ForgetAllOfIt();
  375.         
  376.         /* Set background */
  377.         SetRast(rp, 0);
  378.         DrawImage(rp, bc4b_Image, BLEFT, BTOP);
  379.         SwapBitMaps();
  380.         SetRast(rp, 0);
  381.         DrawImage(rp, bc4b_Image, BLEFT, BTOP);
  382.  
  383.         /* Init Gels System */
  384.         if (ReadyGels(&key, &GInfo, rp))
  385.                 longjmp(save, "ReadyGels failed");
  386.                 
  387.         /* Init Bobs & AninObs */
  388.         for (i = 0; i < NBOBS; ++i)
  389.         {
  390.                 if (!(bob[i] = MakeBob(&key, *im[i], SAVEBACK | OVERLAY)))
  391.                         longjmp(save, "MakeBob Failed");
  392.                 DoubleBob(&key, bob[i]);
  393.                 AddBob(bob[i], rp);
  394.                 vsp[i] = bob[i]->BobVSprite;
  395.         }
  396.         
  397.         vsp[BOARD]->X = BLEFT;
  398.         vsp[BOARD]->Y = BTOP;
  399.         vsp[RED]->X = 230;
  400.         vsp[RED]->Y = 20;
  401.         vsp[BLUE]->X = 230;
  402.         vsp[BLUE]->Y = 100;
  403.         bob[BOARD]->Flags |= SAVEBOB;   
  404.         TimeAdvance(rp, vp);
  405.         
  406.         /* Install Gadgets */
  407.         for (i = 0; i < 5; ++i)
  408.         {
  409.                 gad[i] = g = MakeBGadget(&key, *ig[i], NULL, 
  410.                                         GADR, GADT(i), GRELRIGHT, NULL);
  411.                 if (!g)
  412.                         longjmp(save, "MakeBGadget failed");
  413.                 g->UserData = command[i];
  414.                 AddGadget(window, g, -1);
  415.                 gad[i] = g;
  416.                 SwapBitMaps();
  417.                 DrawImage(rp, *ig[i], GADR + 319, GADT(i));
  418.                 SwapBitMaps();
  419.                 DrawImage(rp, *ig[i], GADR + 319, GADT(i));
  420.         }
  421.         RefreshGadgets(gad[0], window, NULL);
  422.         ScreenToFront(screen);
  423. }
  424.  
  425. static  BOOL   alternate = NULL;
  426. static  struct BitMap   *bit1, *bit2;
  427.  
  428. InitDoubleBuffering() 
  429. {
  430.         struct  RastPort *rp = window->RPort;
  431.         struct  ViewPort *vp = &screen->ViewPort;
  432.         struct  RasInfo *ri = vp->RasInfo;
  433.         struct  BitMap *bit;
  434.         int i;
  435.         
  436.         /* 1. init a bitmap */
  437.         bit = AllocRemember(&key, sizeof(*bit), CHIP);
  438.         if (!bit)
  439.                 longjmp(save, "Out of memory");
  440.         
  441.         InitBitMap(bit, 5, 320, 200);
  442.         for (i = 0; i < 5; ++i)
  443.                 bit->Planes[i] = AllocRemember(&key, RASSIZE(320, 200), CHIP);
  444.         
  445.         bit1 = rp->BitMap;
  446.         bit2 = bit;
  447. }
  448.  
  449. SwapBitMaps()
  450. {
  451.         struct  RastPort *rp = window->RPort;
  452.         struct  ViewPort *vp = &screen->ViewPort;
  453.         struct  RasInfo *ri = vp->RasInfo;
  454.         struct  BitMap *bit;
  455.         
  456.         alternate ^= 1;
  457.         
  458.         if (alternate)
  459.         {
  460.                 /* display bit2 */
  461.                 ri->BitMap = bit2;
  462.                 WaitTOF();
  463.                 MakeScreen(screen);
  464.                 RethinkDisplay();
  465.                 rp->BitMap = bit1;
  466.         }
  467.         else
  468.         {
  469.                 /* display bit1 */
  470.                 ri->BitMap = bit1;
  471.                 WaitTOF();
  472.                 MakeScreen(screen);
  473.                 RethinkDisplay();
  474.                 rp->BitMap = bit2;
  475.         }
  476. }
  477.  
  478. ShutDownDB()    /* shut down double-buffering */
  479. {
  480.         /* WARNING: Do Not SwapBitMaps after this!!!! */
  481.         
  482.         if (!bit1 || !bit2)
  483.                 return; /* don't attempt to shutdowm if not up */
  484.                 
  485.         if (!alternate) 
  486.                 SwapBitMaps();  /* make intuition kill its own bitmap */
  487.         
  488. }
  489.  
  490. MainShutdown(n)                /* shutdown procedure   */
  491. int    n;
  492. {
  493.         switch (n)
  494.         {
  495.                 case 0:
  496.                         ForgetAllOfIt();
  497.                         Dinit();
  498.                         ShutDownDB();
  499.                         
  500.                 case 50:
  501.                         if (tmpras.RasPtr)
  502.                                 FreeRaster(tmpras.RasPtr, 320, 400);
  503.                 case 45:
  504.                         if (window)
  505.                                 CloseWindow(window);
  506.                 case 40:
  507.                         if (screen)
  508.                                 CloseScreen(screen);
  509.                 case 30:
  510.                         if (GfxBase)
  511.                                 CloseLibrary(GfxBase);
  512.                 case 20:
  513.                         if (IntuitionBase)
  514.                                 CloseLibrary(IntuitionBase);
  515.                 case 10:
  516.                         FreeRemember(&key, TRUE);
  517.                         break;
  518.                 default:
  519.                         printf("??? Shutdown Error %d\n", n);
  520.                         MainShutdown(0);
  521.                         break;
  522.         }
  523.         exit(n);
  524. }
  525.  
  526. #
  527. /*****************************************************************************
  528.         The Actual Connect-4 code
  529. *****************************************************************************/
  530.  
  531. Connect4()       /* the connect 4 game */
  532. {
  533.         struct  IntuiMessage *m, cm;
  534.         struct  RastPort *rp = window->RPort;
  535.         struct  ViewPort *vp = &screen->ViewPort;
  536.         int class, code;
  537.         
  538.         while (1)
  539.         {
  540.                 WaitPort(window->UserPort);
  541.                 while (m = GetMsg(window->UserPort))
  542.                 {
  543.                         cm = *m;
  544.                         ReplyMsg(m);
  545.                         
  546.                         switch (cm.Class)
  547.                         {
  548.                         case GADGETUP:
  549.                                 ProcessGadget(&cm);
  550.                                 RefreshGadgets(gad[0], window, NULL);
  551.                                 break;
  552.                         
  553.                         case MOUSEMOVE:
  554.                                 ProcessMouse(&cm);
  555.                                 break;
  556.                         
  557.                         case MOUSEBUTTONS:
  558.                                 if (cm.Code == SELECTUP || cm.Code == MENUUP)
  559.                                         ProcessRelease();
  560.                                 break;
  561.                         
  562.                         case INTUITICKS:
  563.                                 TimeAdvance(rp, vp);
  564.                                 ProcessTime();
  565.                                 break;
  566.                         
  567.                         default:
  568.                                 break;
  569.                         }
  570.                 }
  571.         }
  572. }
  573.  
  574. /*      Processing
  575. */
  576.  
  577. TimeAdvance(rp, vp)     /* advance bobs to new posistion */
  578. struct RastPort *rp;
  579. struct ViewPort *vp;
  580. {
  581.         SortGList(rp);
  582.         DrawGList(rp, vp);
  583.         SwapBitMaps();
  584. }
  585.  
  586. ProcessTime()   /* Signal children that a time event has been received */
  587. {
  588.         if (dprint)
  589.         {
  590.                 printf(dstring);
  591.                 dprint = FALSE;
  592.         }
  593.         Forbid();
  594.         if (ptrFallTask)
  595.                 Signal(ptrFallTask, 1<<FTsig);
  596.         if (ptrPlayTask)
  597.                 Signal(ptrPlayTask, 1<<PTsig);
  598.         if (ptrLeviTask)
  599.                 Signal(ptrLeviTask, 1<<LTsig);
  600.         Permit();
  601. }
  602.  
  603. ProcessGadget(m)
  604. struct IntuiMessage *m;
  605. {
  606.         int (*funct)();
  607.         struct Gadget *g;
  608.         
  609.         g = m->IAddress;
  610.         funct = g->UserData;
  611.         (*funct)(window->RPort, &screen->ViewPort);
  612. }
  613.  
  614. /*      Mouse attached to peice
  615. */
  616.  
  617. BOOL    peicemove = FALSE;
  618. int     peice;
  619.  
  620. ProcessMouse(m)         /* move the RED peice - human */
  621. struct IntuiMessage *m;
  622. {
  623.         if (peicemove)
  624.         {
  625.                 vsp[peice]->X += ((m->MouseX - BWIDTH) - vsp[peice]->X)/2;
  626.                 vsp[peice]->Y += ((m->MouseY - BHEIGHT) - vsp[peice]->Y)/2;
  627.         }
  628. }
  629.  
  630. ProcessRelease()        /* The Chip has been released, so turn off mouse movements */
  631. {
  632.         peicemove = FALSE;
  633.         FallSlot = -1;
  634.         DoneFalling = FALSE;
  635.         if (!CreateTask( "fall.task", 0, FallTask, STACK ))
  636.                 longjmp(save, "fall.task creation failed");
  637. }
  638. #
  639. /****************************************************************************
  640.         Command Routines
  641. ****************************************************************************/
  642.  
  643. PlayCommand()   /* initiate play task */
  644. {
  645.         Forbid();
  646.         if (!ptrPlayTask)
  647.         {
  648.                 if (!CreateTask("play.task", 0, PlayTask, STACK))
  649.                 {        
  650.                         Permit();
  651.                         longjmp(save, "play.task creation failed");
  652.                 }
  653.         }
  654.         Permit();
  655. }
  656.  
  657. LevelCommand()
  658. {
  659.         struct  RastPort *rp = window->RPort;
  660.         struct  ViewPort *vp = &screen->ViewPort;
  661.         IFF *iff, *bmhd;
  662.         struct BitMap *bit;
  663.         struct Requester *req;
  664.         struct Remember *lkey = NULL;
  665.         BitMapHeader *bh;
  666.         RTGLIST *l;
  667.         int i;
  668.         
  669.         if ((iff = IffRead("Level.Requester")) 
  670.                 && (bit = MakeBitMap(&lkey, iff, NULL)))
  671.         {
  672.                 bmhd = IffFind(iff, BMHD, NULL, IF_FRONT);
  673.                 if (!bmhd)
  674.                         longjmp(save, "Iff BMHD NOT FOUND??@@!!");
  675.                 bh = bmhd->info;
  676.                 screen->ViewPort.RasInfo->BitMap = screen->RastPort.BitMap;
  677.                 WaitTOF();      /* shut down double buffering */
  678.                 MakeScreen(screen);
  679.                 RethinkDisplay();
  680.                 
  681.                 
  682.                 if (DoCustomRequest(&key, bit, level_list, window, 
  683.                                         10, 20, bh->w, bh->h))
  684.                 {
  685.                         for (l = level_list, i=0; i < 16; ++l, ++i)
  686.                         {
  687.                                 if (l->selected)
  688.                                 {
  689.                                         game_level = l->userid;
  690.                                         printf("changed to level %d\n", game_level);
  691.                                         break;
  692.                                 }
  693.                         }
  694.                 }
  695.                 else
  696.                 {
  697.                         printf("/* Level Requester Failure */");
  698.                 }
  699.                 SwapBitMaps();
  700.                 FreeRemember(&lkey, TRUE);
  701.         }
  702.         ForgetAllOfIt();
  703. }
  704.  
  705. BackCommand()
  706. {
  707.         ScreenToBack(screen);
  708. }
  709.  
  710. InfoCommand()
  711. {
  712.         struct  RastPort *rp = window->RPort;
  713.         struct  ViewPort *vp = &screen->ViewPort;
  714.         IFF *iff, *bmhd;
  715.         struct BitMap *bit;
  716.         struct Requester *req;
  717.         struct Remember *key = NULL;
  718.         BitMapHeader *bh;
  719.  
  720.         if ((iff = IffRead("Info.Requester")) 
  721.                 && (bit = MakeBitMap(&key, iff, NULL)))
  722.         {
  723.                 bmhd = IffFind(iff, BMHD, NULL, IF_FRONT);
  724.                 if (!bmhd)
  725.                         longjmp(save, "Iff BMHD NOT FOUND??@@!!");
  726.                 bh = bmhd->info;
  727.                 screen->ViewPort.RasInfo->BitMap = screen->RastPort.BitMap;
  728.                 WaitTOF();      /* shut down double buffering */
  729.                 MakeScreen(screen);
  730.                 RethinkDisplay();
  731.                 if (!DoCustomRequest(NULL, bit, info_list, window, 
  732.                                 10, 20, bh->w, bh->h))
  733.                         printf("/* Info Requester Failure */");
  734.                 SwapBitMaps();
  735.                 FreeRemember(&key, TRUE);
  736.         }
  737.         ForgetAllOfIt();
  738. }
  739.  
  740. QuitCommand()
  741. {
  742.         longjmp(save, "user exit");
  743. }
  744. #
  745. /****************************************************************************
  746.         The Play Task
  747. ****************************************************************************/
  748.  
  749. PlayTask()
  750. {
  751.         struct RastPort *rp = window->RPort;
  752.         struct ViewPort *vp = &screen->ViewPort;
  753.         int time, i, j;
  754.         C4BOARD b;
  755.         
  756.         PTsig = AllocSignal(-1);
  757.         ptrPlayTask = FindTask();
  758.         peicemove = FALSE;
  759.         
  760.         DrawImage(rp, BACK_BOARD_IMAGE, BLEFT, BTOP);
  761.         Wait(1<<PTsig);
  762.         DrawImage(rp, BACK_BOARD_IMAGE, BLEFT, BTOP);
  763.         Wait(1<<PTsig);
  764.         
  765.         movmem(&C4Template, &MasterBoard, sizeof(C4BOARD));
  766.         for (i = 0; i < 7; ++i)
  767.                 for (j = 0; j < 6; ++j)
  768.                         MasterBoard.b[i][j] = -1;
  769.         /* MasterBoard: -1 is unoccupied, RED is red, BLUE is blue */
  770.         /* other boards: BLUE is 1 (computer), RED is -1 (human) */
  771.         
  772.         /* initialize bob positions */
  773.         vsp[BOARD]->X = BLEFT;
  774.         vsp[BOARD]->Y = BTOP;
  775.         vsp[RED]->X = 230;
  776.         vsp[RED]->Y = 20;
  777.         vsp[BLUE]->X = 230;
  778.         vsp[BLUE]->Y = 100;
  779.         
  780.         Wait(1<<PTsig);
  781.         
  782.         for (i = 0; i < 21; ++i)
  783.         {
  784.                 LetHumanMove();
  785.                 if (WhoWon(&MasterBoard, -1) != -1)
  786.                 {
  787.                         /* Human has won */
  788.                         DisplayBeep(0);
  789.                         break;
  790.                 }
  791.                 ConvertBoard(&b);
  792.                 MakeComputerMove(-1);   /* start the gyrations */
  793.                 MakeComputerMove(Analyze(&b, 1, game_level)); /* 1 for computer */
  794.                 if (WhoWon(&MasterBoard, -1) != -1)
  795.                 {
  796.                         /* Computer has won */
  797.                         DisplayBeep(0);
  798.                         break;
  799.                 }
  800.         }
  801.         
  802.         ptrPlayTask = NULL; /* before winking out */
  803. }
  804.  
  805. WhoWon(b, space)        /* returns chip or space */
  806. C4BOARD *b;
  807. int space; /* value of unoccupied space */
  808. {
  809.         int c, r, chip, cc, rr, cnt, i;
  810.         
  811.         for (c = 0; c < 7; ++c)
  812.                 for (r = 0; r < 6; ++r)
  813.                 {
  814.                         if ((chip = b->b[c][r]) != space)
  815.                         {
  816.                                 for (cc = -1; cc <= 1; ++cc)
  817.                                         for (rr = -1; rr <= 1; ++rr)
  818.                                         {
  819.                                                 if (!cc && !rr)
  820.                                                         break;
  821.                                                 for (i=0, cnt=0; i<4; ++i)
  822.                                                 {
  823.                                                         if (b->b[c+cc*i][r+rr*i] == chip)
  824.                                                         {
  825.                                                                 ++cnt;
  826.                                                                 winner[i][0] = c+cc*i;
  827.                                                                 winner[i][1] = r+rr*i;
  828.                                                         }
  829.                                                         else
  830.                                                                 break;
  831.                                                 }
  832.                                                 if (cnt == 4)
  833.                                                         return chip;
  834.                                                 
  835.                                         }
  836.                                 
  837.                         }
  838.                 }
  839.         return space;
  840. }
  841.  
  842. LetHumanMove()  /* allow human to make his move */
  843. {
  844.         while (!DoneFalling)
  845.                 Wait(1<<PTsig);
  846.                 
  847.         Forbid();
  848.         FallSlot = -1;
  849.         peice = RED;
  850.         vsp[RED]->X = 230;
  851.         vsp[RED]->Y = 20;
  852.         DoneFalling = FALSE;
  853.         Permit();
  854.         
  855.         do
  856.         {
  857.                 FallSlot = -1;
  858.                 peicemove = TRUE;
  859.                 while (FallSlot == -1)
  860.                         Wait(1<<PTsig);
  861.         } while (FallSlot == -2);
  862. }
  863.  
  864. MakeComputerMove(slot)  /* make computer's move. slot is -1 if undecided */
  865. int slot;
  866. {
  867.         while (!DoneFalling)
  868.                 Wait(1<<PTsig);
  869.                 
  870.         Forbid();
  871.         LTwhere = slot;
  872.         peice = BLUE;
  873.         peicemove = FALSE;
  874.         if (!ptrLeviTask)
  875.         {
  876.                 vsp[BLUE]->X = 230;
  877.                 vsp[BLUE]->Y = 100;
  878.                 CreateTask("levi.task", 0, LeviTask, STACK);
  879.         } 
  880.         if (slot != -1)
  881.                 DoneFalling = FALSE;
  882.         Permit();
  883.         if (slot != -1)
  884.                 while (!DoneFalling)
  885.                         Wait(1<<PTsig);
  886. /*      bob[BLUE]->Flags &= ~SAVEBOB; */
  887. }
  888.  
  889. ConvertBoard(b) /* converts MasterBoard to AnalBoard */
  890. C4BOARD *b;
  891. {
  892.         C4BOARD *o = &MasterBoard;
  893.         int c, r;
  894.         
  895.         movmem(&C4Template, b, sizeof(C4BOARD));
  896.         movmem(o->pos, b->pos, sizeof(b->pos));
  897.         for (c = 0; c < 7; ++c)
  898.                 for (r = 0; r < 6; ++r)
  899.                         if (o->b[c][r] != -1)
  900.                                 b->b[c][r] = (o->b[c][r] == RED) ? -1 : 1;
  901.         
  902. }
  903. #
  904. /****************************************************************************
  905.         The Fall Task
  906.         
  907.         Must determine location of [peice]
  908.         Must calculate where it will fall - which slot
  909.         Must know how far it will fall and where to stop it.
  910.         Must return somewhere which slot (0-6) chip fell in.
  911. ****************************************************************************/
  912.  
  913. FallTask()
  914. {
  915.         int l, t, col, row, x, y, a, v; /* t has two uses */
  916.         struct RastPort *rp = window->RPort;
  917.         
  918.         FallSlot = -1, DoneFalling = FALSE; /* to be sure */
  919.         FTsig = AllocSignal(-1);
  920.         ptrFallTask = FindTask(NULL);
  921.         
  922.         /* Which slot will it fall in? Is it high enough ? Over the board? */
  923.         l = vsp[peice]->X - BLEFT + BWIDTH/2; /* middle top instead of left top */
  924.         t = vsp[peice]->Y - BTOP;
  925.         if ((t < BS_TOP) && (l > BS_LEFT) && (l < BS_LEFT + BWIDTH * 7))
  926.         {
  927.                 /* calculate which column and adjust for alingment*/
  928.                 col = (l - BS_LEFT) / BWIDTH;
  929.                 x = vsp[peice]->X = xcoor(col);
  930.                 Wait(1<<FTsig);
  931.                 
  932.                 /* find row it must fall to */
  933.                 row = MasterBoard.pos[col];
  934.                 /* row is either 6 (full), or 0-5 */
  935.                 
  936.                 if (row >= 6)
  937.                         FallSlot = -2;
  938.                 else /* there exist an empty slot. */ 
  939.                 {
  940.                         DoMove(&MasterBoard, col, peice);
  941.                         FallSlot = col;
  942.                         peicemove = FALSE;
  943.                         y = ycoor(row); /* where to fall to */
  944.                         a = 600;
  945.                         v = 0;
  946.                         t = vsp[peice]->Y * 1000; 
  947.                         while (t/1000 < y)
  948.                         {
  949.                                 v += a;
  950.                                 t += v;
  951.                                 vsp[peice]->Y = t / 1000;
  952.                                 Wait(1<<FTsig);
  953.                         }
  954.                         vsp[peice]->X = 230;
  955.                         vsp[peice]->Y = 100;
  956.                         Wait(1<<FTsig); /* do it twice to clear double buffer */
  957.                         DrawImage(rp, *im[peice], x, y);
  958.                         Wait(1<<FTsig);
  959.                         DrawImage(rp, *im[peice], x, y);
  960.                         Wait(1<<FTsig); /* do it again for double buffering */
  961.                         DrawImage(rp, *im[peice], x, y);
  962.                 }                
  963.         }
  964.         else /* out of range */
  965.         {
  966.                 FallSlot = -2;
  967.         }
  968.         DoneFalling = TRUE;
  969.         ptrFallTask = NULL;
  970. }
  971.  
  972. xcoor(col)      /* compute the x coordiante from the given col slot */
  973. int col;
  974. {
  975.         return BLEFT + BS_LEFT + col * BWIDTH;
  976. }
  977.  
  978. ycoor(row)      /* compute the y coordinate from the given row slot */
  979. int row;
  980. {
  981.         return (5-row) * BHEIGHT + BS_TOP + BTOP;
  982. }
  983.  
  984. #
  985. /***************************************************************************
  986.  
  987.         The Levi Task
  988.         
  989.         Used by Computer to make its move.
  990.         peice = peice to be moved
  991.         LTwhere = where to move it (-1 if undecided)
  992.         
  993.         Conjurs up the FallTask to drop it in!
  994.  
  995. ****************************************************************************/
  996.  
  997. LeviTask()
  998. {
  999.         int goalx, goaly, dx, dy, gyrate = 0;
  1000.         
  1001.         LTsig = AllocSignal(-1);
  1002.         ptrLeviTask = FindTask(NULL);
  1003.         
  1004.         /* move peice to top of screen, 2 chips above BS_TOP */
  1005.         goaly = BTOP + BS_TOP - 2*BHEIGHT;
  1006.         while (dy = (goaly - vsp[peice]->Y))
  1007.         {
  1008.                 if (dy/5)
  1009.                         dy /= 5;
  1010.                 vsp[peice]->Y += dy;
  1011.                 Wait(1<<LTsig);
  1012.         }
  1013.         
  1014.         /* now that the peice is up there, either move it in place, or
  1015.            gyrate back and forth until the proper value comes in. */
  1016.         
  1017.         while (LTwhere == -1)
  1018.         {
  1019.                 if (!gyrate)
  1020.                 {
  1021.                         gyrate = BS_LEFT + BLEFT + rand()%(BWIDTH * 7);
  1022.                         gyrate -= vsp[peice]->X; /* displacement */
  1023.                 }
  1024.                 dx = gyrate / 5;
  1025.                 if (!dx)
  1026.                         dx = gyrate;
  1027.                 else if (ABS(dx) < 5)
  1028.                         dx = (dx * 5) / ABS(dx);
  1029.                         
  1030.                 vsp[peice]->X += dx;
  1031.                 gyrate -= dx;
  1032.                 Wait(1<<LTsig);
  1033.         }
  1034.         /* LTwhere now contains a goal, so.... */
  1035.         goalx = LTwhere * BWIDTH + BS_LEFT + BLEFT;
  1036.         while (dx = goalx - vsp[peice]->X)
  1037.         {
  1038.                 if (dx / 5)
  1039.                         dx /= 5;
  1040.                 else
  1041.                         dx /= ABS(dx);
  1042.                 vsp[peice]->X += dx;
  1043.                 Wait(1<<LTsig);
  1044.         }
  1045.         
  1046.         /* Conjur up the FallTask */
  1047.         LTwhere = -1;
  1048.         FallTask();
  1049.         ptrLeviTask = NULL;
  1050. }
  1051. #
  1052. /*****************************************************************************
  1053.         The ANALYZE Brain (not a task unto itself, but called by PlayTask)
  1054.         
  1055.                 The board is represented by +/- 1, 0 being unoccupied.
  1056.                 The results are in nextmove array. For each recursion,
  1057.                 a pro move and an anti move is analyzed.
  1058. *****************************************************************************/
  1059.  
  1060. int decide[4][4] = /* 1 - good move, 0 - bad move [him][me] */
  1061. {
  1062.         {       1,      1,      1,      1       },
  1063.         {       0,      1,      1,      1       },
  1064.         {       0,      0,      0,      1       },
  1065.         {       0,      0,      0,      0       }
  1066. };
  1067.  
  1068. Analyze (b, who, depth, pwin)    /* analyze board to depth, return the best move */
  1069. C4BOARD *b;
  1070. int   depth,  /* search depth */ 
  1071.         who,    /* who moves next */
  1072.         *pwin;  /* place to return the winning status (if non-zero) */
  1073. {
  1074.         int move, nextmove, counter, winner, i;
  1075.         int grade[7];
  1076.         
  1077.         Grade(b, who, grade);
  1078.         if (!depth)
  1079.         {
  1080.                 tprintf("%d->", depth);
  1081.                 for (i =0; i < 7; ++i)
  1082.                         tprintf("(%d)", grade[i]);
  1083.                 move = PickAGrade(b, grade, who);
  1084.                 tprintf(" pick=%d\n", move);
  1085.                 if (pwin)
  1086.                         *pwin = WhoWon(b, 0);
  1087.                 return move;
  1088.         }
  1089.         
  1090.         for (i = 0; i < 7; ++i)
  1091.         {
  1092.                 move = PickAGrade(b, grade, who);
  1093.                 if (!DoMove(b, move, who))
  1094.                 {
  1095.                         grade[move] = MAGIC_LOCKOUT;
  1096.                         continue;
  1097.                 }
  1098.         
  1099.                 if (WhoWon(b, 0) == who)
  1100.                 {
  1101.                         UndoMove(b, move);
  1102.                         if (pwin)
  1103.                                 *pwin = who;
  1104.                         return move;
  1105.                 }
  1106.                 
  1107.                 /* since this move is not a definite win, check it out */
  1108.                 counter = Analyze(b, -who, depth-1, &winner);
  1109.                 if (winner)
  1110.                 {
  1111.                         if (pwin)
  1112.                                 *pwin = winner;
  1113.                                 
  1114.                         UndoMove(b, move); /* we're hopping somewhere else */
  1115.                         
  1116.                         if (winner == who)
  1117.                         {
  1118.                                 return move;
  1119.                         }
  1120.                         else /* winner == -who, the other guy */
  1121.                         {
  1122.                                 grade[move] = MAGIC_LOCKOUT;
  1123.                                 continue;
  1124.                         }
  1125.                 }
  1126.                 UndoMove(b, move);
  1127.                 break;
  1128.         }
  1129.         return move;
  1130. }
  1131.  
  1132. Highest (grade, who) /* pick highest entry and return it AS A POSITIVE */
  1133. int grade[];
  1134. int who;
  1135. {
  1136.         int i;
  1137.         int h;
  1138.         
  1139.         for (i = 0, h = -999; i < 7; ++i)
  1140.                 if (grade[i] * who > h)
  1141.                         h = grade[i] * who;
  1142.         
  1143.         return (h > 0) ? h : 0;
  1144. }
  1145.  
  1146. Lowest (grade, who) /* pick lowest entry and return it AS A POSITIVE */
  1147. int grade[];
  1148. int who;
  1149. {
  1150.         int i;
  1151.         int h;
  1152.         
  1153.         for (i = 0, h = 999; i < 7; ++i)
  1154.                 if (grade[i] * who < h)
  1155.                         h = grade[i] * who;
  1156.         
  1157.         return (h > 0) ? h : 0;
  1158. }
  1159.  
  1160. PickAGrade(b, grade, who)  /* pick a grade based on priority calculation */
  1161. C4BOARD *b;
  1162. int grade[];          /* ptr to 7-element array to choose from  */
  1163. int who;              /* in favor of */
  1164. {
  1165.         int ic, g, gic, pro;
  1166.         
  1167.         for (ic = 0, g=-1000; ic < 7; ++ic)
  1168.         {
  1169.                 if (grade[ic] == MAGIC_LOCKOUT)
  1170.                         continue;
  1171.                         
  1172.                 pro = (grade[ic]*who > 0) ? grade[ic] * who * 2 + 1 
  1173.                                           : -grade[ic] * who * 2;
  1174.                 if ((pro > g) && (b->pos[ic] < 6))
  1175.                 {
  1176.                         g = pro;
  1177.                         gic = ic;
  1178.                 }
  1179.         }
  1180.         return gic;
  1181. }
  1182.  
  1183. DoMove(b, col, who)     /* move the peice there, return FALSE if failed */
  1184. C4BOARD *b;
  1185. int col;
  1186. int who;
  1187. {
  1188.         int pos;
  1189.         
  1190.         if ((pos = b->pos[col]) >= 6)
  1191.                 return FALSE;
  1192.         ++b->pos[col];
  1193.         b->b[col][pos] = who;
  1194.         return TRUE;
  1195. }
  1196.  
  1197. UndoMove(b, col)  /* undo the previous move. Will not work with MASTERBOARD */
  1198. C4BOARD *b;
  1199. int col;
  1200. {
  1201.         int pos;
  1202.         
  1203.         pos = --b->pos[col];
  1204.         b->b[col][pos] = 0;
  1205. }
  1206.  
  1207. int sx[8] = {-1, 0, 1, -1, 1, -1, 0, 1};        /* x component directions */
  1208. int sy[8] = {-1, -1, -1, 0, 0, 1, 1, 1};        /* y component directions */
  1209. int xy[4][2] = {0, 7, 5, 2, 1, 6, 3, 4};        /* directional paring */
  1210. int gr[7] = {0, 1, 5, 100, 1000, 1000, 1000};
  1211.  
  1212. /*      Grading had been ambiguous before, but now it's done on the basis
  1213.         of who moves next. The next move is posulated for all 7 possibilities
  1214.         and a grade is computed for each position. 
  1215. */
  1216. Grade(b, who, arr)
  1217. C4BOARD *b;
  1218. int who;        /* who moves next */
  1219. int *arr;       /* score of each indiv. column returned (if non-z) */
  1220. {
  1221.         int grade[7], i;
  1222.         
  1223.         _Grade(b, who, arr, 0);
  1224.         _Grade(b, who, grade, 1);
  1225.         
  1226.         for (i = 0; i < 7; ++i)
  1227.         {
  1228.                 if (sgn(grade[i]) == -who)
  1229.                         if (sgn(arr[i]) == who)
  1230.                                 if (ABS(grade[i]) > ABS(arr[i]))
  1231.                                         arr[i] = 0;
  1232.         }
  1233. }
  1234.  
  1235. _Grade(b, who, arr, phantom)        /* Grade the board, return the results */
  1236. C4BOARD *b;
  1237. int who;        /* who moves next */
  1238. int *arr;       /* score of each indiv. column returned (if non-z) */
  1239. int phantom;    /* posistion offset - either 0 or 1 */
  1240. {
  1241.         int c, g, i, j, d, pos, p, q, e, ppro, pant;
  1242.         int score[8]; /* ...for the 8 directions */
  1243.         int emp[8]; /* ...for the empty areas following the chip */
  1244.         int cso[7]; /* score for the seven columns */
  1245.         
  1246.         for (c = 0, ppro=pant=0; c < 7; ++c) /* for the seven columns */
  1247.         {
  1248.                 pos = b->pos[c] + phantom;
  1249.                 if (pos >= 6)
  1250.                 {
  1251.                         cso[c] = 0;
  1252.                         continue;
  1253.                 }
  1254.                         
  1255.                 for (d = 0; d < 8; ++d) /* for the eight directions */
  1256.                 {
  1257.                         for (i = 1, p = b->b[c+sx[d]][pos+sy[d]], 
  1258.                                 score[d]=emp[d]=0; i < 4; ++i)
  1259.                         {
  1260.                                 q = b->b[c+sx[d]*i][pos+sy[d]*i];
  1261.                                 if (q == -2)
  1262.                                         break;
  1263.                                 else if (q == p)
  1264.                                 {
  1265.                                         if (p)
  1266.                                                 score[d] += p;
  1267.                                         else
  1268.                                                 ++emp[d];
  1269.                                 }
  1270.                                 else if (!q)
  1271.                                 {
  1272.                                         if (d != 1 && d != 6)
  1273.                                                 if (!b->b[c+sx[d]*i][pos+sy[d]*(i-1)])
  1274.                                                         break;
  1275.                                         
  1276.                                         p = 0;
  1277.                                         ++emp[d];
  1278.                                 }
  1279.                                 else
  1280.                                         break;
  1281.                         }
  1282.                 }
  1283.                 /* 8 directional score has been computed. */
  1284.                 /* Now sift through it to find the most relavant score. */
  1285.                 
  1286.                 /* do a directional paring sweep... */
  1287.                 for (i = 0; i < 4; ++i)
  1288.                 {
  1289.                         p = score[xy[i][0]];
  1290.                         q = score[xy[i][1]];
  1291.                         if (!p && !q)   /* if both are empty */
  1292.                         {
  1293.                                 /* skip */
  1294.                         }
  1295.                         else if (sgn(p) == sgn(q))   /* if chips match... */
  1296.                         {
  1297.                                 score[xy[i][0]] += q;
  1298.                                 score[xy[i][1]] = 0;
  1299.                                 emp[xy[i][0]] += emp[xy[i][1]];
  1300.                                 emp[xy[i][1]] = 0;
  1301.                         }
  1302.                         else if (!p)
  1303.                         {
  1304.                                 emp[xy[i][1]] += emp[xy[i][0]];
  1305.                                 emp[xy[i][0]] = 0;
  1306.                         }
  1307.                         else if (!q)
  1308.                         {
  1309.                                 emp[xy[i][0]] += emp[xy[i][1]];
  1310.                                 emp[xy[i][1]] = 0;
  1311.                         }
  1312.                         else /* p and q are opposite chips */
  1313.                         {
  1314.                                 if (ABS(p) == ABS(q))
  1315.                                 {
  1316.                                         if (who == p) /* if chip p goes next */
  1317.                                         {
  1318.                                                 score[xy[i][1]] = 0;
  1319.                                                 emp[xy[i][1]] = 0;
  1320.                                         }
  1321.                                         else /* q goes next */
  1322.                                         {
  1323.                                                 score[xy[i][0]] = 0;
  1324.                                                 emp[xy[i][0]] = 0;
  1325.                                         }
  1326.                                 }
  1327.                         }
  1328.                 } /* end of paring sweep. Now pick the most significant. */
  1329.                 
  1330.                 /* scan for most sig. EMP is not being made use of yet. */
  1331.                 for (i = 0, j = 0; i < 8; ++i) /* j is used as place holder */
  1332.                 {
  1333.                         if (ABS(j) < ABS(score[i]))
  1334.                         {
  1335.                                 j = score[i];
  1336.                                 e = emp[i];
  1337.                         }
  1338.                         else if (ABS(j) == ABS(score[i]))
  1339.                         {
  1340.                                 if (who != sgn(j))      /* was != */
  1341.                                 {
  1342.                                         j = score[i];
  1343.                                         e = emp[i];
  1344.                                 }
  1345.                         }
  1346.                 } /* meaningful score has been sifted. */
  1347.                 cso[c] = (pos < 6) ? j : 0;
  1348.         }
  1349.         if (arr)
  1350.                 movmem(cso, arr, sizeof(cso));
  1351.         /* Now cso contains the most meaningful score for the 7 cols */
  1352.         /* Now do the grading. */
  1353.         for (i = 0, g = 0; i < 7; ++i) /* g is used as place holder */
  1354.         {
  1355.                 if (ABS(g) < ABS(cso[i]))
  1356.                         g = cso[i];
  1357.                 else if (ABS(g) == ABS(cso[i]))
  1358.                 {
  1359.                         if (who != sgn(g))
  1360.                                g = cso[i];
  1361.                 } 
  1362.         }
  1363.         return g;
  1364. }
  1365.  
  1366. tprintf(s, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
  1367. char *s;
  1368. LONG p1, p2, p3, p4, p5, p6, p7, p8, p9, p10;
  1369. {
  1370.         if (!debug_state)
  1371.                 return;
  1372.                 
  1373.         while (dprint)
  1374.                 Wait(-1);       /* wait for any signal */
  1375.         Forbid();
  1376.         sprintf(dstring, s, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
  1377.         dprint = TRUE;
  1378.         Permit();
  1379. }