home *** CD-ROM | disk | FTP | other *** search
- /* Connect4.C - A simulation
- *
- * Mitchell/Ware Version 2.05 12/6/87
- *
- * Graphics included:
- * rc4c_Image - Red Chip
- * bc4c_Image - Blue Chip
- * bc4b_Image - Background part of 'Board'
- * bc4f_Image - ForeGround part of 'Board'
- * Play_Image - The Play Gadget
- * Level_Image - The Level Gadget
- * Info_Image - Information about game
- * Back_Image - Icon to put this screen to back
- * Quit_Image - End Game
- *
- *
- * NOTE: UserData on gadgets will point to routines to be called
- * in case of gadget activation. They will return something.
- */
-
- #include "exec/types.h"
- #include "exec/memory.h"
- #include "exec/tasks.h"
- #include "intuition/intuition.h"
- #include "graphics/gfx.h"
- #include "graphics/gfxmacros.h"
- #include "graphics/display.h"
- #include "graphics/rastport.h"
- #include "graphics/gels.h"
- #include "clib/macros.h"
- #include <stdio.h>
- #include <setjmp.h>
- #include <ascii.h>
- #include <math.h>
- #include <Iff.h>
- #include <Tools.h>
- #include <connect4.h>
-
- #define MAGIC_LOCKOUT 666
-
- #define STACK 6000 /* size to allocate stacks of tasks */
-
- #define CHIP (MEMF_CHIP | MEMF_CLEAR)
- #define PUB (MEMF_PUBLIC | MEMF_CLEAR)
-
- #define NBOBS 3 /* number of BOBS in system */
- #define RED 0 /* RED chip (HUMAN) */
- #define BLUE 1 /* BLUE chip (COMPUTER) */
- #define BOARD 2 /* BOARD bob */
-
- #define NGADS 5 /* Number of control gadgets */
- #define PLAY 0 /* PLAY gadget */
- #define LEVEL 1
- #define BACK 2
- #define INFO 3
- #define QUIT 4
-
- #define RED_CHIP_IMAGE rc4c_Image
- #define BLUE_CHIP_IMAGE bc4c_Image
- #define BACK_BOARD_IMAGE bc4b_Image
- #define FORE_BOARD_IMAGE bc4f_Image
-
- #define GADR (-Play_Image->Width)
- #define GADT(_x) (20 + (_x) * Play_Image->Height)
-
- #define BTOP 30 /* distance of board from top */
- #define BLEFT -10 /* distance of board from left */
- #define BS_TOP 24 /* board starts relative to BTOP */
- #define BS_LEFT 28 /* board starts relative to BLEFT */
- #define BWIDTH 27 /* board width of one chip */
- #define BHEIGHT 23 /* board height of one chip */
-
- #define IDCMP_SET (REQCLEAR | MOUSEBUTTONS | GADGETUP | INTUITICKS | MOUSEMOVE)
-
- extern struct Screen *OpenScreen();
- extern struct Window *OpenWindow();
-
- struct Image *rc4c_Image;
- struct Image *bc4c_Image;
- struct Image *bc4b_Image;
- struct Image *bc4f_Image;
-
- struct Image *Play_Image;
- struct Image *Level_Image;
- struct Image *Back_Image;
- struct Image *Info_Image;
- struct Image *Quit_Image;
-
- RTGLIST info_list[] =
- {
- { 26, 76, 25, 17, 0, GADGHCOMP, ENDGADGET },
- { 0 }
- };
-
- RTGLIST level_list[] =
- {
- /* list of the 16 levels comes first, followed by OK-WHO-CANCEL
- and the the (useless) TREE and LINEAR. */
- { 26, 97, 22, 14, 1, GADGHCOMP, TOGGLESELECT }, /* 1 */
- { 50, 97, 22, 14, 2, GADGHCOMP, TOGGLESELECT }, /* 2 */
- { 74, 97, 22, 14, 3, GADGHCOMP, TOGGLESELECT }, /* 3 */
- { 98, 97, 22, 14, 4, GADGHCOMP, TOGGLESELECT }, /* 4 */
- { 122, 97, 22, 14, 5, GADGHCOMP, TOGGLESELECT }, /* 5 */
- { 146, 97, 22, 14, 6, GADGHCOMP, TOGGLESELECT }, /* 6 */
- { 170, 97, 22, 14, 7, GADGHCOMP, TOGGLESELECT }, /* 7 */
- { 194, 97, 22, 14, 8, GADGHCOMP, TOGGLESELECT }, /* 8 */
-
- { 26, 113, 22, 14, 9, GADGHCOMP, TOGGLESELECT }, /* 9 */
- { 50, 113, 22, 14, 10, GADGHCOMP, TOGGLESELECT }, /* 10 */
- { 74, 113, 22, 14, 11, GADGHCOMP, TOGGLESELECT }, /* 11 */
- { 98, 113, 22, 14, 12, GADGHCOMP, TOGGLESELECT }, /* 12 */
- { 122, 113, 22, 14, 13, GADGHCOMP, TOGGLESELECT }, /* 13 */
- { 146, 113, 22, 14, 14, GADGHCOMP, TOGGLESELECT }, /* 14 */
- { 170, 113, 22, 14, 15, GADGHCOMP, TOGGLESELECT }, /* 15 */
- { 194, 113, 22, 14, 16, GADGHCOMP, TOGGLESELECT }, /* 16 */
-
- { 32, 138, 32, 6, 0, GADGHCOMP, ENDGADGET | TOGGLESELECT }, /* OK */
- { 103, 138, 32, 6, 0, GADGHCOMP, GADGIMMEDIATE }, /* WHO */
- { 176, 138, 32, 6, 0, GADGHCOMP, ENDGADGET | TOGGLESELECT }, /* CANCEL */
-
- { 22, 44, 42, 15, 0, GADGHCOMP | SELECTED, TOGGLESELECT, NULL, TRUE }, /* TREE */
- { 168, 44, 51, 15, 0, GADGHCOMP | GADGDISABLED, TOGGLESELECT }, /* LINEAR */
-
- { 0 }
- };
-
- RTGLIST who_list[] =
- {
- { 19, 47, 56, 14, 0, GADGHCOMP, TOGGLESELECT }, /* left HUMAN */
- { 19, 72, 56, 14, 0, GADGHCOMP, TOGGLESELECT }, /* left COMPUTER */
- { 131, 47, 56, 14, 0, GADGHCOMP, TOGGLESELECT }, /* right HUMAN */
- { 131, 72, 56, 14, 0, GADGHCOMP, TOGGLESELECT }, /* right COMPUTER */
-
- { 65, 97, 32, 6, 0, GADGHCOMP, TOGGLESELECT | ENDGADGET }, /* OK */
- { 113, 97, 32, 6, 0, GADGHCOMP, TOGGLESELECT | ENDGADGET }, /* CANCEL */
- { 0 }
- };
-
- struct NewScreen NewHS =
- {
- 0, 0, 320, 200, 5, /* left, right, width, height, depth */
- 1, 30, /* Detail pen & Block pen */
- NULL, /* View modes */
- CUSTOMSCREEN, /* Type */
- NULL, /* Font */
- "Connect-4 (c) 1987-88 Mitchell/Ware", /* Title Bar */
- NULL, /* Gadgets - not used at this time */
- NULL /* Custom BitMap */
- };
-
- struct NewWindow NewWin =
- {
- 0, 0, /* Leftedge, Topedge */
- 320, 200, /* Width, Height */
- -1, -1, /* DetailPen, BlockPen - default to customscr */
- IDCMP_SET, /* IDCMPflags */
- BACKDROP | BORDERLESS | ACTIVATE | RMBTRAP | SMART_REFRESH
- | REPORTMOUSE, /* flags */
- NULL, /* First Gadget */
- NULL, /* Check Mark */
- NULL, /* Title */
- NULL, /* Screen - to be inited during runtime */
- NULL, /* BitMap */
- 0, 0, 0, 0, /* MinWidth & Height, MaxWidth & Height */
- CUSTOMSCREEN /* Type */
- };
-
- static struct Screen *screen = NULL;
- static struct Window *window = NULL;
- struct TmpRas tmpras;
- struct AreaInfo areainfo;
- WORD areabuffer[250];
- struct Remember *key = 0;
-
- int game_level = 1;
- int debug_state = 0;
- LONG IntuitionBase = 0;
- LONG GfxBase = 0;
-
- static jmp_buf save;
-
- static struct GelsInfo GInfo;
- static struct Bob *bob[NBOBS];
- static struct VSprite *vsp[NBOBS];
- static struct DBufPacket db[NBOBS];
- static struct Image **im[NBOBS] =
- { &RED_CHIP_IMAGE, &BLUE_CHIP_IMAGE, &FORE_BOARD_IMAGE };
-
- static struct Gadget *gad[NGADS];
-
- static struct Image **ig[NGADS] = {
- &Play_Image, &Level_Image, &Back_Image, &Info_Image, &Quit_Image };
-
- int PlayCommand(), LevelCommand(), BackCommand(),
- InfoCommand(), QuitCommand(),
- FallTask(), PlayTask(), LeviTask();
-
- static int (*command[NGADS])() = {
- PlayCommand, LevelCommand, BackCommand, InfoCommand, QuitCommand };
-
- /* MainTask Globals ******************************
- */
- WORD MTsig;
- struct Task *ptrMainTask = NULL;
- C4BOARD C4Template; /* blank template with borders set */
- char dstring[100]; /* debug string */
- BOOL dprint = FALSE; /* true if printing */
-
- /* PlayTask Globals ******************************
- */
- struct Task *ptrPlayTask = NULL; /* NULL if not active */
- WORD PTsig; /* signal number */
- C4BOARD MasterBoard; /* board of current game - diff. configuration */
- int winner[4][2]; /* winning location of chips 0=c,1=r */
-
- /* FallTask Globals ******************************
- */
- struct Task *ptrFallTask = NULL; /* NULL if not active */
- WORD FTsig; /* signal number */
- int FallSlot = -1; /* becomes 0-5 when decided, or -2 if error */
- BOOL DoneFalling = FALSE; /* set to TRUE when done */
-
- /* LeviTask Globals ******************************
- */
- struct Task *ptrLeviTask = NULL;
- int LTsig;
- int LTwhere = -1; /* where to put the chip. Levitate if -1 */
-
- #
- /* Generic Main Graphics Initer
- */
-
- main(ac, av)
- int ac;
- char **av;
- {
- char *s;
- int i, j;
-
- if (ac == 2)
- debug_state = 1;
-
- if (!(IntuitionBase = OpenLibrary("intuition.library", 0)))
- {
- printf("Cant open intuition library");
- MainShutdown(10);
- }
-
- if (!(GfxBase = OpenLibrary("graphics.library", 0)))
- {
- printf("Cant open graphics library");
- MainShutdown(20);
- }
-
- if (!(NewWin.Screen = screen = OpenScreen(&NewHS)))
- {
- printf("Cant open Screen");
- MainShutdown(30);
- }
-
- if (!(window = OpenWindow(&NewWin)))
- {
- printf("Cant open backdrop window");
- MainShutdown(40);
- }
-
- InitArea(&areainfo, areabuffer, 100);
- window->RPort->AreaInfo = &areainfo;
- window->RPort->TmpRas = (struct TmpRas *)
- InitTmpRas(&tmpras, AllocRaster(320, 400), RASSIZE(320, 400));
- if (!tmpras.RasPtr)
- {
- printf("Out of Memory (45)");
- MainShutdown(45);
- }
-
- /* if (!Icircle(512))
- {
- printf("Out of memory (50)");
- MainShutdown(50);
- } */
-
- setmem(&C4Template, sizeof(C4BOARD), NULL);
- setmem(C4Template.border1, sizeof(C4Template.border1), -2);
- setmem(C4Template.border2, sizeof(C4Template.border2), -2);
- for (i = 0; i < 7; ++i)
- for (j = 6; j < 9; ++j)
- C4Template.b[i][j] = -2;
-
- if (!(s = setjmp(save)))
- {
- Startup();
- Connect4();
- s = "return from Connect4()";
- }
-
- printf("Exit reason: <%s>\n", s);
- MainShutdown(0);
- }
-
- Startup () /* window graphics routine */
- {
- struct RastPort *rp = window->RPort;
- struct ViewPort *vp = &screen->ViewPort;
- struct Gadget *g;
- int i;
- USHORT *cm, *MakeColorMap();
- int ncolors;
- IFF *iff; /* display bit2 */
- struct Image *title;
-
- ShowTitle(screen, FALSE);
- ScreenToBack(screen);
- InitDoubleBuffering();
-
- /* Read in title page and display it */
- if ((iff = IffRead("Title.Page")) && (title = MakeImage(&key, iff, NULL)))
- {
- if (cm = MakeColorMap(key, iff, &ncolors))
- LoadRGB4(vp, cm, ncolors);
- else
- longjmp(save, "Title.Page ColorMap problem");
- SwapBitMaps();
- DrawImage(rp, title, 0, 0);
- SwapBitMaps();
- DrawImage(rp, title, 0, 0);
- ScreenToFront(screen);
- }
-
-
- /* Read in images, and create the IMAGE */
- ForgetAllOfIt();
- if (!(iff = IffRead("Blue.c4.Chip"))) longjmp(save, "bc4c not found");
- if (!(bc4c_Image = MakeImage(&key, iff, NULL))) longjmp(save, "bc4c - not ILBM");
-
- ForgetAllOfIt();
- if (!(iff = IffRead("Board.c4.Back"))) longjmp(save, "bc4b.pic not found");
- if (!(bc4b_Image = MakeImage(&key, iff, NULL))) longjmp(save, "bc4b - not ILBM");
-
- ForgetAllOfIt();
- if (!(iff = IffRead("Board.c4.Front"))) longjmp(save, "bc4f.pic not found");
- if (!(bc4f_Image = MakeImage(&key, iff, NULL))) longjmp(save, "bc4f - not ILBM");
-
- ForgetAllOfIt();
- if (!(iff = IffRead("Level.Gadget"))) longjmp(save, "Level.Gadget not found");
- if (!(Level_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Level - not ILBM");
-
- ForgetAllOfIt();
- if (!(iff = IffRead("Back.Gadget"))) longjmp(save, "Back.Gadget not found");
- if (!(Back_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Back - not ILBM");
-
- ForgetAllOfIt();
- if (!(iff = IffRead("Info.Gadget"))) longjmp(save, "Info.Gadget not found");
- if (!(Info_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Info - not ILBM");
-
- ForgetAllOfIt();
- if (!(iff = IffRead("Quit.Gadget"))) longjmp(save, "Quit.Gadget not found");
- if (!(Quit_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Quit - not ILBM");
-
- ForgetAllOfIt();
- if (!(iff = IffRead("Red.c4.Chip"))) longjmp(save, "rc4c.pic not found");
- if (!(rc4c_Image = MakeImage(&key, iff, NULL))) longjmp(save, "rc4c - not ILBM");
-
- ForgetAllOfIt();
- if (!(iff = IffRead("Play.Gadget"))) longjmp(save, "Play.Gadget not found");
- if (!(Play_Image = MakeImage(&key, iff, NULL))) longjmp(save, "Play - not ILBM");
-
- if (cm = MakeColorMap(key, iff, &ncolors))
- {
- LoadRGB4(vp, cm, ncolors);
- }
- else longjmp(save, "ColorMap problem");
-
- ForgetAllOfIt();
-
- /* Set background */
- SetRast(rp, 0);
- DrawImage(rp, bc4b_Image, BLEFT, BTOP);
- SwapBitMaps();
- SetRast(rp, 0);
- DrawImage(rp, bc4b_Image, BLEFT, BTOP);
-
- /* Init Gels System */
- if (ReadyGels(&key, &GInfo, rp))
- longjmp(save, "ReadyGels failed");
-
- /* Init Bobs & AninObs */
- for (i = 0; i < NBOBS; ++i)
- {
- if (!(bob[i] = MakeBob(&key, *im[i], SAVEBACK | OVERLAY)))
- longjmp(save, "MakeBob Failed");
- DoubleBob(&key, bob[i]);
- AddBob(bob[i], rp);
- vsp[i] = bob[i]->BobVSprite;
- }
-
- vsp[BOARD]->X = BLEFT;
- vsp[BOARD]->Y = BTOP;
- vsp[RED]->X = 230;
- vsp[RED]->Y = 20;
- vsp[BLUE]->X = 230;
- vsp[BLUE]->Y = 100;
- bob[BOARD]->Flags |= SAVEBOB;
- TimeAdvance(rp, vp);
-
- /* Install Gadgets */
- for (i = 0; i < 5; ++i)
- {
- gad[i] = g = MakeBGadget(&key, *ig[i], NULL,
- GADR, GADT(i), GRELRIGHT, NULL);
- if (!g)
- longjmp(save, "MakeBGadget failed");
- g->UserData = command[i];
- AddGadget(window, g, -1);
- gad[i] = g;
- SwapBitMaps();
- DrawImage(rp, *ig[i], GADR + 319, GADT(i));
- SwapBitMaps();
- DrawImage(rp, *ig[i], GADR + 319, GADT(i));
- }
- RefreshGadgets(gad[0], window, NULL);
- ScreenToFront(screen);
- }
-
- static BOOL alternate = NULL;
- static struct BitMap *bit1, *bit2;
-
- InitDoubleBuffering()
- {
- struct RastPort *rp = window->RPort;
- struct ViewPort *vp = &screen->ViewPort;
- struct RasInfo *ri = vp->RasInfo;
- struct BitMap *bit;
- int i;
-
- /* 1. init a bitmap */
- bit = AllocRemember(&key, sizeof(*bit), CHIP);
- if (!bit)
- longjmp(save, "Out of memory");
-
- InitBitMap(bit, 5, 320, 200);
- for (i = 0; i < 5; ++i)
- bit->Planes[i] = AllocRemember(&key, RASSIZE(320, 200), CHIP);
-
- bit1 = rp->BitMap;
- bit2 = bit;
- }
-
- SwapBitMaps()
- {
- struct RastPort *rp = window->RPort;
- struct ViewPort *vp = &screen->ViewPort;
- struct RasInfo *ri = vp->RasInfo;
- struct BitMap *bit;
-
- alternate ^= 1;
-
- if (alternate)
- {
- /* display bit2 */
- ri->BitMap = bit2;
- WaitTOF();
- MakeScreen(screen);
- RethinkDisplay();
- rp->BitMap = bit1;
- }
- else
- {
- /* display bit1 */
- ri->BitMap = bit1;
- WaitTOF();
- MakeScreen(screen);
- RethinkDisplay();
- rp->BitMap = bit2;
- }
- }
-
- ShutDownDB() /* shut down double-buffering */
- {
- /* WARNING: Do Not SwapBitMaps after this!!!! */
-
- if (!bit1 || !bit2)
- return; /* don't attempt to shutdowm if not up */
-
- if (!alternate)
- SwapBitMaps(); /* make intuition kill its own bitmap */
-
- }
-
- MainShutdown(n) /* shutdown procedure */
- int n;
- {
- switch (n)
- {
- case 0:
- ForgetAllOfIt();
- Dinit();
- ShutDownDB();
-
- case 50:
- if (tmpras.RasPtr)
- FreeRaster(tmpras.RasPtr, 320, 400);
- case 45:
- if (window)
- CloseWindow(window);
- case 40:
- if (screen)
- CloseScreen(screen);
- case 30:
- if (GfxBase)
- CloseLibrary(GfxBase);
- case 20:
- if (IntuitionBase)
- CloseLibrary(IntuitionBase);
- case 10:
- FreeRemember(&key, TRUE);
- break;
- default:
- printf("??? Shutdown Error %d\n", n);
- MainShutdown(0);
- break;
- }
- exit(n);
- }
-
- #
- /*****************************************************************************
- The Actual Connect-4 code
- *****************************************************************************/
-
- Connect4() /* the connect 4 game */
- {
- struct IntuiMessage *m, cm;
- struct RastPort *rp = window->RPort;
- struct ViewPort *vp = &screen->ViewPort;
- int class, code;
-
- while (1)
- {
- WaitPort(window->UserPort);
- while (m = GetMsg(window->UserPort))
- {
- cm = *m;
- ReplyMsg(m);
-
- switch (cm.Class)
- {
- case GADGETUP:
- ProcessGadget(&cm);
- RefreshGadgets(gad[0], window, NULL);
- break;
-
- case MOUSEMOVE:
- ProcessMouse(&cm);
- break;
-
- case MOUSEBUTTONS:
- if (cm.Code == SELECTUP || cm.Code == MENUUP)
- ProcessRelease();
- break;
-
- case INTUITICKS:
- TimeAdvance(rp, vp);
- ProcessTime();
- break;
-
- default:
- break;
- }
- }
- }
- }
-
- /* Processing
- */
-
- TimeAdvance(rp, vp) /* advance bobs to new posistion */
- struct RastPort *rp;
- struct ViewPort *vp;
- {
- SortGList(rp);
- DrawGList(rp, vp);
- SwapBitMaps();
- }
-
- ProcessTime() /* Signal children that a time event has been received */
- {
- if (dprint)
- {
- printf(dstring);
- dprint = FALSE;
- }
- Forbid();
- if (ptrFallTask)
- Signal(ptrFallTask, 1<<FTsig);
- if (ptrPlayTask)
- Signal(ptrPlayTask, 1<<PTsig);
- if (ptrLeviTask)
- Signal(ptrLeviTask, 1<<LTsig);
- Permit();
- }
-
- ProcessGadget(m)
- struct IntuiMessage *m;
- {
- int (*funct)();
- struct Gadget *g;
-
- g = m->IAddress;
- funct = g->UserData;
- (*funct)(window->RPort, &screen->ViewPort);
- }
-
- /* Mouse attached to peice
- */
-
- BOOL peicemove = FALSE;
- int peice;
-
- ProcessMouse(m) /* move the RED peice - human */
- struct IntuiMessage *m;
- {
- if (peicemove)
- {
- vsp[peice]->X += ((m->MouseX - BWIDTH) - vsp[peice]->X)/2;
- vsp[peice]->Y += ((m->MouseY - BHEIGHT) - vsp[peice]->Y)/2;
- }
- }
-
- ProcessRelease() /* The Chip has been released, so turn off mouse movements */
- {
- peicemove = FALSE;
- FallSlot = -1;
- DoneFalling = FALSE;
- if (!CreateTask( "fall.task", 0, FallTask, STACK ))
- longjmp(save, "fall.task creation failed");
- }
- #
- /****************************************************************************
- Command Routines
- ****************************************************************************/
-
- PlayCommand() /* initiate play task */
- {
- Forbid();
- if (!ptrPlayTask)
- {
- if (!CreateTask("play.task", 0, PlayTask, STACK))
- {
- Permit();
- longjmp(save, "play.task creation failed");
- }
- }
- Permit();
- }
-
- LevelCommand()
- {
- struct RastPort *rp = window->RPort;
- struct ViewPort *vp = &screen->ViewPort;
- IFF *iff, *bmhd;
- struct BitMap *bit;
- struct Requester *req;
- struct Remember *lkey = NULL;
- BitMapHeader *bh;
- RTGLIST *l;
- int i;
-
- if ((iff = IffRead("Level.Requester"))
- && (bit = MakeBitMap(&lkey, iff, NULL)))
- {
- bmhd = IffFind(iff, BMHD, NULL, IF_FRONT);
- if (!bmhd)
- longjmp(save, "Iff BMHD NOT FOUND??@@!!");
- bh = bmhd->info;
- screen->ViewPort.RasInfo->BitMap = screen->RastPort.BitMap;
- WaitTOF(); /* shut down double buffering */
- MakeScreen(screen);
- RethinkDisplay();
-
-
- if (DoCustomRequest(&key, bit, level_list, window,
- 10, 20, bh->w, bh->h))
- {
- for (l = level_list, i=0; i < 16; ++l, ++i)
- {
- if (l->selected)
- {
- game_level = l->userid;
- printf("changed to level %d\n", game_level);
- break;
- }
- }
- }
- else
- {
- printf("/* Level Requester Failure */");
- }
- SwapBitMaps();
- FreeRemember(&lkey, TRUE);
- }
- ForgetAllOfIt();
- }
-
- BackCommand()
- {
- ScreenToBack(screen);
- }
-
- InfoCommand()
- {
- struct RastPort *rp = window->RPort;
- struct ViewPort *vp = &screen->ViewPort;
- IFF *iff, *bmhd;
- struct BitMap *bit;
- struct Requester *req;
- struct Remember *key = NULL;
- BitMapHeader *bh;
-
- if ((iff = IffRead("Info.Requester"))
- && (bit = MakeBitMap(&key, iff, NULL)))
- {
- bmhd = IffFind(iff, BMHD, NULL, IF_FRONT);
- if (!bmhd)
- longjmp(save, "Iff BMHD NOT FOUND??@@!!");
- bh = bmhd->info;
- screen->ViewPort.RasInfo->BitMap = screen->RastPort.BitMap;
- WaitTOF(); /* shut down double buffering */
- MakeScreen(screen);
- RethinkDisplay();
- if (!DoCustomRequest(NULL, bit, info_list, window,
- 10, 20, bh->w, bh->h))
- printf("/* Info Requester Failure */");
- SwapBitMaps();
- FreeRemember(&key, TRUE);
- }
- ForgetAllOfIt();
- }
-
- QuitCommand()
- {
- longjmp(save, "user exit");
- }
- #
- /****************************************************************************
- The Play Task
- ****************************************************************************/
-
- PlayTask()
- {
- struct RastPort *rp = window->RPort;
- struct ViewPort *vp = &screen->ViewPort;
- int time, i, j;
- C4BOARD b;
-
- PTsig = AllocSignal(-1);
- ptrPlayTask = FindTask();
- peicemove = FALSE;
-
- DrawImage(rp, BACK_BOARD_IMAGE, BLEFT, BTOP);
- Wait(1<<PTsig);
- DrawImage(rp, BACK_BOARD_IMAGE, BLEFT, BTOP);
- Wait(1<<PTsig);
-
- movmem(&C4Template, &MasterBoard, sizeof(C4BOARD));
- for (i = 0; i < 7; ++i)
- for (j = 0; j < 6; ++j)
- MasterBoard.b[i][j] = -1;
- /* MasterBoard: -1 is unoccupied, RED is red, BLUE is blue */
- /* other boards: BLUE is 1 (computer), RED is -1 (human) */
-
- /* initialize bob positions */
- vsp[BOARD]->X = BLEFT;
- vsp[BOARD]->Y = BTOP;
- vsp[RED]->X = 230;
- vsp[RED]->Y = 20;
- vsp[BLUE]->X = 230;
- vsp[BLUE]->Y = 100;
-
- Wait(1<<PTsig);
-
- for (i = 0; i < 21; ++i)
- {
- LetHumanMove();
- if (WhoWon(&MasterBoard, -1) != -1)
- {
- /* Human has won */
- DisplayBeep(0);
- break;
- }
- ConvertBoard(&b);
- MakeComputerMove(-1); /* start the gyrations */
- MakeComputerMove(Analyze(&b, 1, game_level)); /* 1 for computer */
- if (WhoWon(&MasterBoard, -1) != -1)
- {
- /* Computer has won */
- DisplayBeep(0);
- break;
- }
- }
-
- ptrPlayTask = NULL; /* before winking out */
- }
-
- WhoWon(b, space) /* returns chip or space */
- C4BOARD *b;
- int space; /* value of unoccupied space */
- {
- int c, r, chip, cc, rr, cnt, i;
-
- for (c = 0; c < 7; ++c)
- for (r = 0; r < 6; ++r)
- {
- if ((chip = b->b[c][r]) != space)
- {
- for (cc = -1; cc <= 1; ++cc)
- for (rr = -1; rr <= 1; ++rr)
- {
- if (!cc && !rr)
- break;
- for (i=0, cnt=0; i<4; ++i)
- {
- if (b->b[c+cc*i][r+rr*i] == chip)
- {
- ++cnt;
- winner[i][0] = c+cc*i;
- winner[i][1] = r+rr*i;
- }
- else
- break;
- }
- if (cnt == 4)
- return chip;
-
- }
-
- }
- }
- return space;
- }
-
- LetHumanMove() /* allow human to make his move */
- {
- while (!DoneFalling)
- Wait(1<<PTsig);
-
- Forbid();
- FallSlot = -1;
- peice = RED;
- vsp[RED]->X = 230;
- vsp[RED]->Y = 20;
- DoneFalling = FALSE;
- Permit();
-
- do
- {
- FallSlot = -1;
- peicemove = TRUE;
- while (FallSlot == -1)
- Wait(1<<PTsig);
- } while (FallSlot == -2);
- }
-
- MakeComputerMove(slot) /* make computer's move. slot is -1 if undecided */
- int slot;
- {
- while (!DoneFalling)
- Wait(1<<PTsig);
-
- Forbid();
- LTwhere = slot;
- peice = BLUE;
- peicemove = FALSE;
- if (!ptrLeviTask)
- {
- vsp[BLUE]->X = 230;
- vsp[BLUE]->Y = 100;
- CreateTask("levi.task", 0, LeviTask, STACK);
- }
- if (slot != -1)
- DoneFalling = FALSE;
- Permit();
- if (slot != -1)
- while (!DoneFalling)
- Wait(1<<PTsig);
- /* bob[BLUE]->Flags &= ~SAVEBOB; */
- }
-
- ConvertBoard(b) /* converts MasterBoard to AnalBoard */
- C4BOARD *b;
- {
- C4BOARD *o = &MasterBoard;
- int c, r;
-
- movmem(&C4Template, b, sizeof(C4BOARD));
- movmem(o->pos, b->pos, sizeof(b->pos));
- for (c = 0; c < 7; ++c)
- for (r = 0; r < 6; ++r)
- if (o->b[c][r] != -1)
- b->b[c][r] = (o->b[c][r] == RED) ? -1 : 1;
-
- }
- #
- /****************************************************************************
- The Fall Task
-
- Must determine location of [peice]
- Must calculate where it will fall - which slot
- Must know how far it will fall and where to stop it.
- Must return somewhere which slot (0-6) chip fell in.
- ****************************************************************************/
-
- FallTask()
- {
- int l, t, col, row, x, y, a, v; /* t has two uses */
- struct RastPort *rp = window->RPort;
-
- FallSlot = -1, DoneFalling = FALSE; /* to be sure */
- FTsig = AllocSignal(-1);
- ptrFallTask = FindTask(NULL);
-
- /* Which slot will it fall in? Is it high enough ? Over the board? */
- l = vsp[peice]->X - BLEFT + BWIDTH/2; /* middle top instead of left top */
- t = vsp[peice]->Y - BTOP;
- if ((t < BS_TOP) && (l > BS_LEFT) && (l < BS_LEFT + BWIDTH * 7))
- {
- /* calculate which column and adjust for alingment*/
- col = (l - BS_LEFT) / BWIDTH;
- x = vsp[peice]->X = xcoor(col);
- Wait(1<<FTsig);
-
- /* find row it must fall to */
- row = MasterBoard.pos[col];
- /* row is either 6 (full), or 0-5 */
-
- if (row >= 6)
- FallSlot = -2;
- else /* there exist an empty slot. */
- {
- DoMove(&MasterBoard, col, peice);
- FallSlot = col;
- peicemove = FALSE;
- y = ycoor(row); /* where to fall to */
- a = 600;
- v = 0;
- t = vsp[peice]->Y * 1000;
- while (t/1000 < y)
- {
- v += a;
- t += v;
- vsp[peice]->Y = t / 1000;
- Wait(1<<FTsig);
- }
- vsp[peice]->X = 230;
- vsp[peice]->Y = 100;
- Wait(1<<FTsig); /* do it twice to clear double buffer */
- DrawImage(rp, *im[peice], x, y);
- Wait(1<<FTsig);
- DrawImage(rp, *im[peice], x, y);
- Wait(1<<FTsig); /* do it again for double buffering */
- DrawImage(rp, *im[peice], x, y);
- }
- }
- else /* out of range */
- {
- FallSlot = -2;
- }
- DoneFalling = TRUE;
- ptrFallTask = NULL;
- }
-
- xcoor(col) /* compute the x coordiante from the given col slot */
- int col;
- {
- return BLEFT + BS_LEFT + col * BWIDTH;
- }
-
- ycoor(row) /* compute the y coordinate from the given row slot */
- int row;
- {
- return (5-row) * BHEIGHT + BS_TOP + BTOP;
- }
-
- #
- /***************************************************************************
-
- The Levi Task
-
- Used by Computer to make its move.
- peice = peice to be moved
- LTwhere = where to move it (-1 if undecided)
-
- Conjurs up the FallTask to drop it in!
-
- ****************************************************************************/
-
- LeviTask()
- {
- int goalx, goaly, dx, dy, gyrate = 0;
-
- LTsig = AllocSignal(-1);
- ptrLeviTask = FindTask(NULL);
-
- /* move peice to top of screen, 2 chips above BS_TOP */
- goaly = BTOP + BS_TOP - 2*BHEIGHT;
- while (dy = (goaly - vsp[peice]->Y))
- {
- if (dy/5)
- dy /= 5;
- vsp[peice]->Y += dy;
- Wait(1<<LTsig);
- }
-
- /* now that the peice is up there, either move it in place, or
- gyrate back and forth until the proper value comes in. */
-
- while (LTwhere == -1)
- {
- if (!gyrate)
- {
- gyrate = BS_LEFT + BLEFT + rand()%(BWIDTH * 7);
- gyrate -= vsp[peice]->X; /* displacement */
- }
- dx = gyrate / 5;
- if (!dx)
- dx = gyrate;
- else if (ABS(dx) < 5)
- dx = (dx * 5) / ABS(dx);
-
- vsp[peice]->X += dx;
- gyrate -= dx;
- Wait(1<<LTsig);
- }
- /* LTwhere now contains a goal, so.... */
- goalx = LTwhere * BWIDTH + BS_LEFT + BLEFT;
- while (dx = goalx - vsp[peice]->X)
- {
- if (dx / 5)
- dx /= 5;
- else
- dx /= ABS(dx);
- vsp[peice]->X += dx;
- Wait(1<<LTsig);
- }
-
- /* Conjur up the FallTask */
- LTwhere = -1;
- FallTask();
- ptrLeviTask = NULL;
- }
- #
- /*****************************************************************************
- The ANALYZE Brain (not a task unto itself, but called by PlayTask)
-
- The board is represented by +/- 1, 0 being unoccupied.
- The results are in nextmove array. For each recursion,
- a pro move and an anti move is analyzed.
- *****************************************************************************/
-
- int decide[4][4] = /* 1 - good move, 0 - bad move [him][me] */
- {
- { 1, 1, 1, 1 },
- { 0, 1, 1, 1 },
- { 0, 0, 0, 1 },
- { 0, 0, 0, 0 }
- };
-
- Analyze (b, who, depth, pwin) /* analyze board to depth, return the best move */
- C4BOARD *b;
- int depth, /* search depth */
- who, /* who moves next */
- *pwin; /* place to return the winning status (if non-zero) */
- {
- int move, nextmove, counter, winner, i;
- int grade[7];
-
- Grade(b, who, grade);
- if (!depth)
- {
- tprintf("%d->", depth);
- for (i =0; i < 7; ++i)
- tprintf("(%d)", grade[i]);
- move = PickAGrade(b, grade, who);
- tprintf(" pick=%d\n", move);
- if (pwin)
- *pwin = WhoWon(b, 0);
- return move;
- }
-
- for (i = 0; i < 7; ++i)
- {
- move = PickAGrade(b, grade, who);
- if (!DoMove(b, move, who))
- {
- grade[move] = MAGIC_LOCKOUT;
- continue;
- }
-
- if (WhoWon(b, 0) == who)
- {
- UndoMove(b, move);
- if (pwin)
- *pwin = who;
- return move;
- }
-
- /* since this move is not a definite win, check it out */
- counter = Analyze(b, -who, depth-1, &winner);
- if (winner)
- {
- if (pwin)
- *pwin = winner;
-
- UndoMove(b, move); /* we're hopping somewhere else */
-
- if (winner == who)
- {
- return move;
- }
- else /* winner == -who, the other guy */
- {
- grade[move] = MAGIC_LOCKOUT;
- continue;
- }
- }
- UndoMove(b, move);
- break;
- }
- return move;
- }
-
- Highest (grade, who) /* pick highest entry and return it AS A POSITIVE */
- int grade[];
- int who;
- {
- int i;
- int h;
-
- for (i = 0, h = -999; i < 7; ++i)
- if (grade[i] * who > h)
- h = grade[i] * who;
-
- return (h > 0) ? h : 0;
- }
-
- Lowest (grade, who) /* pick lowest entry and return it AS A POSITIVE */
- int grade[];
- int who;
- {
- int i;
- int h;
-
- for (i = 0, h = 999; i < 7; ++i)
- if (grade[i] * who < h)
- h = grade[i] * who;
-
- return (h > 0) ? h : 0;
- }
-
- PickAGrade(b, grade, who) /* pick a grade based on priority calculation */
- C4BOARD *b;
- int grade[]; /* ptr to 7-element array to choose from */
- int who; /* in favor of */
- {
- int ic, g, gic, pro;
-
- for (ic = 0, g=-1000; ic < 7; ++ic)
- {
- if (grade[ic] == MAGIC_LOCKOUT)
- continue;
-
- pro = (grade[ic]*who > 0) ? grade[ic] * who * 2 + 1
- : -grade[ic] * who * 2;
- if ((pro > g) && (b->pos[ic] < 6))
- {
- g = pro;
- gic = ic;
- }
- }
- return gic;
- }
-
- DoMove(b, col, who) /* move the peice there, return FALSE if failed */
- C4BOARD *b;
- int col;
- int who;
- {
- int pos;
-
- if ((pos = b->pos[col]) >= 6)
- return FALSE;
- ++b->pos[col];
- b->b[col][pos] = who;
- return TRUE;
- }
-
- UndoMove(b, col) /* undo the previous move. Will not work with MASTERBOARD */
- C4BOARD *b;
- int col;
- {
- int pos;
-
- pos = --b->pos[col];
- b->b[col][pos] = 0;
- }
-
- int sx[8] = {-1, 0, 1, -1, 1, -1, 0, 1}; /* x component directions */
- int sy[8] = {-1, -1, -1, 0, 0, 1, 1, 1}; /* y component directions */
- int xy[4][2] = {0, 7, 5, 2, 1, 6, 3, 4}; /* directional paring */
- int gr[7] = {0, 1, 5, 100, 1000, 1000, 1000};
-
- /* Grading had been ambiguous before, but now it's done on the basis
- of who moves next. The next move is posulated for all 7 possibilities
- and a grade is computed for each position.
- */
- Grade(b, who, arr)
- C4BOARD *b;
- int who; /* who moves next */
- int *arr; /* score of each indiv. column returned (if non-z) */
- {
- int grade[7], i;
-
- _Grade(b, who, arr, 0);
- _Grade(b, who, grade, 1);
-
- for (i = 0; i < 7; ++i)
- {
- if (sgn(grade[i]) == -who)
- if (sgn(arr[i]) == who)
- if (ABS(grade[i]) > ABS(arr[i]))
- arr[i] = 0;
- }
- }
-
- _Grade(b, who, arr, phantom) /* Grade the board, return the results */
- C4BOARD *b;
- int who; /* who moves next */
- int *arr; /* score of each indiv. column returned (if non-z) */
- int phantom; /* posistion offset - either 0 or 1 */
- {
- int c, g, i, j, d, pos, p, q, e, ppro, pant;
- int score[8]; /* ...for the 8 directions */
- int emp[8]; /* ...for the empty areas following the chip */
- int cso[7]; /* score for the seven columns */
-
- for (c = 0, ppro=pant=0; c < 7; ++c) /* for the seven columns */
- {
- pos = b->pos[c] + phantom;
- if (pos >= 6)
- {
- cso[c] = 0;
- continue;
- }
-
- for (d = 0; d < 8; ++d) /* for the eight directions */
- {
- for (i = 1, p = b->b[c+sx[d]][pos+sy[d]],
- score[d]=emp[d]=0; i < 4; ++i)
- {
- q = b->b[c+sx[d]*i][pos+sy[d]*i];
- if (q == -2)
- break;
- else if (q == p)
- {
- if (p)
- score[d] += p;
- else
- ++emp[d];
- }
- else if (!q)
- {
- if (d != 1 && d != 6)
- if (!b->b[c+sx[d]*i][pos+sy[d]*(i-1)])
- break;
-
- p = 0;
- ++emp[d];
- }
- else
- break;
- }
- }
- /* 8 directional score has been computed. */
- /* Now sift through it to find the most relavant score. */
-
- /* do a directional paring sweep... */
- for (i = 0; i < 4; ++i)
- {
- p = score[xy[i][0]];
- q = score[xy[i][1]];
- if (!p && !q) /* if both are empty */
- {
- /* skip */
- }
- else if (sgn(p) == sgn(q)) /* if chips match... */
- {
- score[xy[i][0]] += q;
- score[xy[i][1]] = 0;
- emp[xy[i][0]] += emp[xy[i][1]];
- emp[xy[i][1]] = 0;
- }
- else if (!p)
- {
- emp[xy[i][1]] += emp[xy[i][0]];
- emp[xy[i][0]] = 0;
- }
- else if (!q)
- {
- emp[xy[i][0]] += emp[xy[i][1]];
- emp[xy[i][1]] = 0;
- }
- else /* p and q are opposite chips */
- {
- if (ABS(p) == ABS(q))
- {
- if (who == p) /* if chip p goes next */
- {
- score[xy[i][1]] = 0;
- emp[xy[i][1]] = 0;
- }
- else /* q goes next */
- {
- score[xy[i][0]] = 0;
- emp[xy[i][0]] = 0;
- }
- }
- }
- } /* end of paring sweep. Now pick the most significant. */
-
- /* scan for most sig. EMP is not being made use of yet. */
- for (i = 0, j = 0; i < 8; ++i) /* j is used as place holder */
- {
- if (ABS(j) < ABS(score[i]))
- {
- j = score[i];
- e = emp[i];
- }
- else if (ABS(j) == ABS(score[i]))
- {
- if (who != sgn(j)) /* was != */
- {
- j = score[i];
- e = emp[i];
- }
- }
- } /* meaningful score has been sifted. */
- cso[c] = (pos < 6) ? j : 0;
- }
- if (arr)
- movmem(cso, arr, sizeof(cso));
- /* Now cso contains the most meaningful score for the 7 cols */
- /* Now do the grading. */
- for (i = 0, g = 0; i < 7; ++i) /* g is used as place holder */
- {
- if (ABS(g) < ABS(cso[i]))
- g = cso[i];
- else if (ABS(g) == ABS(cso[i]))
- {
- if (who != sgn(g))
- g = cso[i];
- }
- }
- return g;
- }
-
- tprintf(s, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
- char *s;
- LONG p1, p2, p3, p4, p5, p6, p7, p8, p9, p10;
- {
- if (!debug_state)
- return;
-
- while (dprint)
- Wait(-1); /* wait for any signal */
- Forbid();
- sprintf(dstring, s, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
- dprint = TRUE;
- Permit();
- }