/*************************************************************************** * * * 'Game of Life - Duo' - a "Game of Life" for 2 kinds of cells * * * *************************************************************************** * * * Created by * * Andreas Neubacher * * * * Hausleitnerweg 26 * * 4020 Linz * * Austria * * * * E-mail: aneubach@risc.uni-linz.ac.at (Internet) * * k318577@alijku11 (Bitnet) * * * *************************************************************************** * * * Copyright notice: * * I don't claim any copyright and put this code into the public domain. * * * *************************************************************************** * * * 92-01-23 AN : Finished release version * * * ***************************************************************************/ #include #include #include #include "functions.h" #ifdef _DCC void wbmain() { main(); } /* DICE needs this for Workbench startup. */ #endif extern void SetCell(struct BitMap*,short,short,short), ScanAgar(char*,char*,char*,short,short,short), ChangeAgar(struct BitMap*,char*,char*,short,short,short,short), DisplayAgar(struct BitMap*,char*,short,short,short,short), CountCells(char*,short*,short*,unsigned short); #define XSIZE 162 /* No. of columns + 2 */ #define YSIZE 62 /* No. of rows + 2 */ #define AGARLE 0 /* Coordinates of the left upper corner */ #define AGARTE 25 /* of the 'Agar' output area. */ #define MAXCELL 3 /* No. of cell types (dead, red, blue) */ #define MAXVAL 16 /* 8 * (MAXCELL-1) */ #define NULLCODE 1 /* Code for dead cells */ #define P1CODE 0 /* Code for Strain 1 cells */ #define P2CODE 2 /* Code for Strain 2 cells */ #define NOCODE 3 /* Code for 'cell remains unchanges' */ #define NULLPEN 0 /* Color for dead cells */ #define P1PEN 2 /* Color for Strain 1 cells */ #define P2PEN 1 /* Color for Strain 2 cells */ #define GRIDPEN MAXCELL /* Color for grid */ #define FGPEN MAXCELL + 1L /* Textcolor */ /*************************************************************************** * * MENUS * ***************************************************************************/ #define EDITITEMWID 100 + COMMWIDTH #define PITEMWID 60 struct IntuiText ClearText = { 0,0,JAM1, 8,1, NULL, "Clear Agar", NULL }; struct MenuItem ClearItem = { NULL, 0,10,EDITITEMWID,10, ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ, 0, (APTR)&ClearText, NULL, 'c', NULL,0 }; struct IntuiText UndoText = { 0,0,JAM1, 8,1, NULL, "Undo", NULL }; struct MenuItem UndoItem = { &ClearItem, 0,0,EDITITEMWID,10, ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ, 0, (APTR)&UndoText, NULL, 'u', NULL,0 }; struct Menu EditMenu = { NULL, 75,0,40,0, MENUENABLED, "Edit", &UndoItem }; struct IntuiText QuitText = { 0,0,JAM1, 8,1, NULL, "Quit", NULL }; struct MenuItem QuitItem = { NULL, 0,36,PITEMWID,10, ITEMTEXT | ITEMENABLED | HIGHCOMP, 0, (APTR)&QuitText, NULL,0,NULL,0 }; struct IntuiText ResetText = { 0,0,JAM1, 8,1, NULL, "Reset", NULL }; struct MenuItem ResetItem = { &QuitItem, 0,24,PITEMWID,10, ITEMTEXT | ITEMENABLED | HIGHCOMP, 0, (APTR)&ResetText, NULL,0,NULL,0 }; struct IntuiText RulesText = { 0,0,JAM1, 8,1, NULL, "Rules", NULL }; struct MenuItem RulesItem = { &ResetItem, 0,12,PITEMWID,10, ITEMTEXT | ITEMENABLED | HIGHCOMP, 0, (APTR)&RulesText, NULL,0,NULL,0 }; struct IntuiText AboutText = { 0,0,JAM1, 8,1, NULL, "About", NULL }; struct MenuItem AboutItem = { &RulesItem, 0,0,PITEMWID,10, ITEMTEXT | ITEMENABLED | HIGHCOMP, 0, (APTR)&AboutText, NULL,0,NULL,0 }; struct Menu ProjectMenu = { &EditMenu, 0,0,PITEMWID,0, MENUENABLED, "Project", &AboutItem }; /*************************************************************************** * * GADGETS * ***************************************************************************/ #define P1ID 1 #define P2ID 2 #define GROWID 3 #define AGARID 4 #define CS1ID 8 #define CS2ID 9 #define GS1ID 10 #define GS2ID 11 #define ROKID 12 #define RCANID 13 #define UOKID 14 #define UCANID 15 #define AOKID 16 #define UX0ID 32 short PnXY[] = { 0,0, 67,0, 67,11, 0,11, 0,0 }; struct Border PnBorder = { -1,-1, 0,0,JAM1, 5,PnXY, NULL }; struct Border P2Border = { -1,-1, P2PEN,0,JAM1, 5,PnXY, NULL }; struct IntuiText P2Text = { P2PEN,0,JAM2, 1,1, NULL, "Strain 2", NULL }; struct Gadget P2Gadget = { NULL, 520,13,66,10, GADGHIMAGE, TOGGLESELECT | RELVERIFY, BOOLGADGET, (APTR)&PnBorder, (APTR)&P2Border, &P2Text, 0,NULL, P2ID, NULL }; struct Border P1Border = { -1,-1, P1PEN,0,JAM1, 5,PnXY, NULL }; struct IntuiText P1Text = { P1PEN,0,JAM2, 1,1, NULL, "Strain 1", NULL }; struct Gadget P1Gadget = { &P2Gadget, 55,13,66,10, GADGHIMAGE | SELECTED, TOGGLESELECT | RELVERIFY, BOOLGADGET, (APTR)&PnBorder, (APTR)&P1Border, &P1Text, 0,NULL, P1ID, NULL }; short GrowXY[] = { 0,0, 35,0, 35,11, 0,11, 0,0 }; struct Border GrowBorder = { -1,-1, FGPEN,0,JAM1, 5,GrowXY, NULL }; struct IntuiText GrowText = { FGPEN,0,JAM2, 1,1, NULL, "Grow", NULL }; struct Gadget GrowGadget = { &P1Gadget, 302,30,34,10, GADGHCOMP, GADGIMMEDIATE | RELVERIFY, BOOLGADGET, (APTR)&GrowBorder, NULL, &GrowText, 0,NULL, GROWID, NULL }; struct Gadget AgarGadget = { &GrowGadget, 4 * AGARLE,3 * AGARTE, 4 * XSIZE - 9,3 * YSIZE - 7, GADGHNONE, GADGIMMEDIATE | RELVERIFY, BOOLGADGET, NULL,NULL,NULL,0,NULL, AGARID, NULL }; SHORT RReqGXY[] = { 0,0, 51,0, 51,11, 0,11, 0,0 }; struct Border RReqGBorder = { -2,-2, GRIDPEN,0,JAM1, 5,RReqGXY, NULL }; char CS1Buffer[7] = { '0',0 }; struct StringInfo CS1SInfo = { CS1Buffer, NULL, 0,7,0, 0,0,0,0,0,NULL,0L,NULL }; struct Gadget CS1Gadget = { NULL, 146,30,50,10, GADGHCOMP, RELVERIFY | LONGINT, STRGADGET | REQGADGET, (APTR)&RReqGBorder, NULL,NULL,0L, (APTR)&CS1SInfo, CS1ID, NULL }; char CS2Buffer[7] = { '0',0 }; struct StringInfo CS2SInfo = { CS2Buffer, NULL, 0,7,0, 0,0,0,0,0,NULL,0L,NULL }; struct Gadget CS2Gadget = { &CS1Gadget, 218,30,50,10, GADGHCOMP, RELVERIFY | LONGINT, STRGADGET | REQGADGET, (APTR)&RReqGBorder, NULL,NULL,0L, (APTR)&CS2SInfo, CS2ID, NULL }; char GS1Buffer[7] = { '0',0 }; struct StringInfo GS1SInfo = { GS1Buffer, NULL, 0,7,0, 0,0,0,0,0,NULL,0L,NULL }; struct Gadget GS1Gadget = { &CS2Gadget, 146,44,50,10, GADGHCOMP, RELVERIFY | LONGINT, STRGADGET | REQGADGET, (APTR)&RReqGBorder, NULL,NULL,0L, (APTR)&GS1SInfo, GS1ID, NULL }; char GS2Buffer[7] = { '0',0 }; struct StringInfo GS2SInfo = { GS2Buffer, NULL, 0,7,0, 0,0,0,0,0,NULL,0L,NULL }; struct Gadget GS2Gadget = { &GS1Gadget, 218,44,50,10, GADGHCOMP, RELVERIFY | LONGINT, STRGADGET | REQGADGET, (APTR)&RReqGBorder, NULL,NULL,0L, (APTR)&GS2SInfo, GS2ID, NULL }; struct IntuiText ROKText = { GRIDPEN,0,JAM1, 0,0, NULL, " OK ", NULL }; struct Gadget ROKGadget = { &GS2Gadget, 45,65,48,8, GADGHCOMP, RELVERIFY | ENDGADGET, BOOLGADGET | REQGADGET, (APTR)&RReqGBorder, NULL, &ROKText, 0L,NULL, ROKID, NULL }; struct IntuiText RCanText = { GRIDPEN,0,JAM1, 0,0, NULL, "CANCEL", NULL }; struct Gadget RCanGadget = { &ROKGadget, 185,65,48,8, GADGHCOMP, RELVERIFY | ENDGADGET, BOOLGADGET | REQGADGET, (APTR)&RReqGBorder, NULL, &RCanText, 0L,NULL, RCANID, NULL }; SHORT UXXY[] = { 0,0, 15,8, 15,0, 0,8, 0,0 }; struct Border BlackXBorder = { 0,0, 0,0,JAM1, 5,UXXY, NULL }; struct Border P1XBorder = { 0,0, P1PEN,0,JAM1, 5,UXXY, NULL }; struct Border P2XBorder = { 0,0, P2PEN,0,JAM1, 5,UXXY, NULL }; struct Gadget UXGadget[MAXCELL][MAXVAL+1] = { { NULL, 6,26,15,9, GADGHCOMP, RELVERIFY, BOOLGADGET | REQGADGET, (APTR)&BlackXBorder, NULL,NULL,0L,NULL, UX0ID, NULL } }; struct Gadget UOKGadget = { UXGadget, 45,65,48,8, GADGHCOMP, RELVERIFY | ENDGADGET, BOOLGADGET | REQGADGET, (APTR)&RReqGBorder, NULL, &ROKText, 0L,NULL, UOKID, NULL }; struct Gadget UCanGadget = { &UOKGadget, 185,65,48,8, GADGHCOMP, RELVERIFY | ENDGADGET, BOOLGADGET | REQGADGET, (APTR)&RReqGBorder, NULL, &RCanText, 0L,NULL, UCANID, NULL }; SHORT AOKGXY[] = { 0,0, 51,0, 51,11, 0,11, 0,0 }; struct Border AOKGBorder = { -2,-2, P2PEN,0,JAM1, 5,AOKGXY, NULL }; struct IntuiText AOKText = { P1PEN,0,JAM1, 0,0, NULL, "Great!", NULL }; struct Gadget AOKGadget = { NULL, 100,76,48,8, GADGHCOMP, RELVERIFY | ENDGADGET, BOOLGADGET | REQGADGET, (APTR)&AOKGBorder, NULL, &AOKText, 0L,NULL, AOKID, NULL }; /*************************************************************************** * * REQUESTERS * ***************************************************************************/ #define RREQWID 280 #define RREQHEI 78 SHORT RReqXY[] = { 1,13, RREQWID-2,13, RREQWID-2,RREQHEI-2, 1,RREQHEI-2, 1,1, RREQWID-2,1, RREQWID-2,13 }; struct Border RReqBorder = { 0,0, 0,0,JAM1, 7,RReqXY, NULL }; struct IntuiText RReqText1 = { P1PEN,0,JAM1, 138,18, NULL, "Strain 1", NULL }; struct IntuiText RReqText2 = { P2PEN,0,JAM1, 210,18, NULL, "Strain 2", &RReqText1 }; struct IntuiText RReqText3 = { GRIDPEN,0,JAM1, 6,4, NULL, "Reset initial values", &RReqText2 }; struct IntuiText RReqText4 = { GRIDPEN,0,JAM1, 10,30, NULL, "Cells in Freezer", &RReqText3 }; struct IntuiText RReqText5 = { GRIDPEN,0,JAM1, 6,44, NULL, "Growth in Freezer", &RReqText4 }; struct Requester ResetReq = { NULL, 180,121,RREQWID,RREQHEI, 0,0, &RCanGadget, &RReqBorder, &RReqText5, 0,FGPEN, NULL,{0},NULL,NULL,{0} }; #define UREQWID 284 #define UREQHEI 78 SHORT UReqXY2[] = { 0,0, 273,0, 273,10, 0,10, 0,0 }; struct Border UReqBorder4 = { 5,49, P2PEN,0,JAM1, 5,UReqXY2, NULL }; struct Border UReqBorder3 = { 5,37, 0,0,JAM1, 5,UReqXY2, &UReqBorder4 }; struct Border UReqBorder2 = { 5,25, P1PEN,0,JAM1, 5,UReqXY2, &UReqBorder3 }; SHORT UReqXY1[] = { 1,13, UREQWID-2,13, UREQWID-2,UREQHEI-2, 1,UREQHEI-2, 1,1, UREQWID-2,1, UREQWID-2,13 }; struct Border UReqBorder1 = { 0,0, 0,0,JAM1, 7,UReqXY1, &UReqBorder2 }; struct IntuiText UReqText4 = { P2PEN,0,JAM1, 150,16, NULL, "+1+2+3+4+5+6+7+8", NULL }; struct IntuiText UReqText3 = { GRIDPEN,0,JAM1, 134,16, NULL, "±0", &UReqText4 }; struct IntuiText UReqText2 = { P1PEN,0,JAM1, 6,16, NULL, "-8-7-6-5-4-3-2-1", &UReqText3 }; struct IntuiText UReqText1 = { GRIDPEN,0,JAM1, 6,4, NULL, "Define rules", &UReqText2 }; struct Requester RulesReq = { NULL, 180,121,UREQWID,UREQHEI, 0,0, &UCanGadget, &UReqBorder1, &UReqText1, 0,FGPEN, NULL,{0},NULL,NULL,{0} }; #define AREQWID 158L #define AREQHEI 90L SHORT AReqXY[] = { 0,0, AREQWID-5,0, AREQWID-5,AREQHEI-3, 0,AREQHEI-3, 0,0 }; struct Border AReqBorder = { 2,1, P2PEN,0,JAM1, 5,AReqXY, NULL }; struct IntuiText AReqText1 = { P1PEN,0,JAM1, 6,4, NULL, "GAME OF LIFE - DUO", NULL }; struct IntuiText AReqText2 = { P1PEN,0,JAM1, 6,20, NULL, "(C)reated 1992 by", &AReqText1 }; struct IntuiText AReqText3 = { P1PEN,0,JAM1, 6,34, NULL, "Andreas Neubacher", &AReqText2 }; struct IntuiText AReqText4 = { P1PEN,0,JAM1, 6,48, NULL, "Hausleitnerweg 26", &AReqText3 }; struct IntuiText AReqText5 = { P1PEN,0,JAM1, 6,58, NULL, "4020 Linz", &AReqText4 }; struct IntuiText AReqText6 = { P1PEN,0,JAM1, 6,68, NULL, "Austria", &AReqText5 }; struct Requester AboutReq = { NULL, 244,81,AREQWID,AREQHEI, 0,0, &AOKGadget, &AReqBorder, &AReqText6, 0,FGPEN, NULL,{0},NULL,NULL,{0} }; /*************************************************************************** * * POINTER * ***************************************************************************/ #define PTRWIDTH 9L #define PTRHEIGHT 8L #define PTRXOFFSET -5L #define PTRYOFFSET -4L USHORT PointerData[] = { 0x0000,0x0000, 0x8080,0x0000, 0x4100,0x0000, 0x2200,0x0000, 0x0000,0x0000, 0x0000,0x0000, 0x2200,0x0000, 0x4100,0x0000, 0x8080,0x0000, 0x0000,0x0000 }; /*************************************************************************** * * SCREEN UND WINDOW * ***************************************************************************/ #define SCRWID 642L #define SCRHEI 254L struct NewScreen ns = { 0,0, SCRWID,SCRHEI, 3, 0,FGPEN, HIRES,CUSTOMSCREEN, 0,0,0,0 }; struct NewWindow nw = { 0,0, SCRWID,SCRHEI, 0,FGPEN, GADGETDOWN | GADGETUP | MENUPICK | MENUVERIFY | MOUSEBUTTONS, SMART_REFRESH | NOCAREREFRESH | BACKDROP | BORDERLESS | ACTIVATE, &AgarGadget, 0,0,0,0,0,0,SCRWID,SCRHEI, CUSTOMSCREEN }; /*************************************************************************** * * Main routine * ***************************************************************************/ char AgarMem[2][YSIZE][XSIZE]; /* Agar, Undo Agar */ char (*Agar)[XSIZE]; /* Current Agar */ short AgarNum; /* Index of current Agar (0,1) */ char AuxAgar[YSIZE][XSIZE]; /* Auxiliary Agar */ char NewCT[MAXCELL][MAXVAL+1]; /* Backup for 'CellTrans' */ char CellTrans[MAXCELL][MAXVAL+1] = { /* Table for transformation rules */ 1,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1, 3,3,3,3,3,0,3,3,3,3,3,2,3,3,3,3,3, 1,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,1 }; struct StrainData { short LCells; /* No. of cells of this Strain on the Agar */ short SCells; /* No. of cells in freezer */ short GRate; /* Growth of cells in freezer */ short ox,oy; /* Left upper corner of output area */ short CellCode; /* Code of this Strain */ short CellPen; /* Color of this Strain */ } pd[2]; struct StrainData *actp; /* Pointer to active Strain */ struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Screen *sc; struct Window *wd; struct RastPort *rp; struct BitMap *bm; USHORT *PointerCMem; main() { void ProcessMenu(),ProcessGadgetUp(),ProcessGadgetDown(),ProcessRMB(); void ClearAgar(),SumOut(),CleanUp(); APTR XBorder(); struct IntuiMessage *Msg; USHORT MClass,MCode; APTR MAddress; struct ViewPort *vp; short i,j,c; /*** * * OPEN LIBRARIES, SCREEN AND WINDOW; INITIALISE GRAPHICS * ***/ IntuitionBase = GfxBase = sc = wd = PointerCMem = NULL; if (! (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L))) CleanUp(NULL); if (! (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L))) CleanUp(NULL); if (!(sc = OpenScreen(&ns))) CleanUp("GoLD: Couldn't open screen!"); nw.Screen = sc; if (!(wd = OpenWindow(&nw))) CleanUp("GoLD: Couldn't open window!"); ShowTitle(sc,FALSE); vp = &(sc->ViewPort); rp = wd->RPort; bm = rp->BitMap; SetRGB4(vp,0L,0L,0L,0L); SetRGB4(vp,1L,15L,0L,0L); SetRGB4(vp,2L,0L,7L,15L); SetRGB4(vp,(long)MAXCELL,3L,3L,3L); SetRGB4(vp,(long)FGPEN,12L,12L,12L); SetRGB4(vp,5L,0L,0L,15L); SetRGB4(vp,6L,8L,0L,0L); SetRGB4(vp,7L,15L,15L,15L); SetRGB4(vp,16L,0L,15L,0L); if (!(PointerCMem = (USHORT *)AllocMem((long)sizeof(PointerData),MEMF_CHIP))) CleanUp("GoLD: No ChipMem for pointer!\n"); for (i=0;i<2*PTRHEIGHT+4;i++) PointerCMem[i] = PointerData[i]; SetPointer(wd,PointerCMem,PTRHEIGHT,PTRWIDTH,PTRXOFFSET,PTRYOFFSET); SetMenuStrip(wd,&ProjectMenu); SetAPen(rp,(long)GRIDPEN); RectFill(rp,0L,74L,SCRWID-1L,SCRHEI-1L); SetAPen(rp,(long)FGPEN); /*** * * INITIALISE GADGETS IN 'UXGadget' * ***/ c = UX0ID; for (i=0;iLCells = 0; actp->SCells = 100; actp->GRate = 0; actp->ox = 458; actp->oy = 40; actp->CellCode = P2CODE; actp->CellPen = P2PEN; Move(rp,(long)actp->ox,(long)actp->oy); Text(rp," Cells on Agar:",17L); Move(rp,(long)actp->ox,(long)(actp->oy+15)); Text(rp,"Cells in Freezer:",17L); actp = &(pd[0]); actp->LCells = 0; actp->SCells = 100; actp->GRate = 0; actp->ox = 4; actp->oy = 40; actp->CellCode = P1CODE; actp->CellPen = P1PEN; Move(rp,(long)actp->ox,(long)actp->oy); Text(rp," Cells on Agar:",17L); Move(rp,(long)actp->ox,(long)(actp->oy+15)); Text(rp,"Cells in Freezer:",17L); ClearAgar(AgarMem[0]); ClearAgar(AgarMem[1]); ClearAgar(AuxAgar); Agar = AgarMem[0]; AgarNum = 0; /*** * * MAIN LOOP * ***/ SumOut(&(pd[0])); SumOut(&(pd[1])); DisplayAgar(bm,Agar,XSIZE,YSIZE,AGARLE,AGARTE); Request(&AboutReq,wd); for (;;) { Wait(1L << wd->UserPort->mp_SigBit); while (Msg = (struct IntuiMessage *)GetMsg(wd->UserPort)) { MClass = Msg->Class; MCode = Msg->Code; MAddress = Msg->IAddress; if (MClass != MENUVERIFY) ReplyMsg(Msg); switch (MClass) { case MENUVERIFY: if (MCode == MENUHOT) ProcessRMB(Msg); else ReplyMsg(Msg); break; case MENUPICK: ProcessMenu(MCode); break; case GADGETUP: ProcessGadgetUp(MAddress); break; case GADGETDOWN: ProcessGadgetDown(MAddress); break; case MOUSEBUTTONS: break; default: CleanUp("GoLD: Unknown message!"); } } } } /*************************************************************************** * * SUBROUTINES * ***************************************************************************/ APTR XBorder(a,i,j) /* Returns a pointer to the 'XBorder'-structure */ /* for 'a[i][j]'. */ char a[MAXCELL][MAXVAL+1]; short i,j; { switch (a[i][j]) { case P1CODE: return(&P1XBorder); case NULLCODE: return(&BlackXBorder); case P2CODE: return(&P2XBorder); case NOCODE: if (i == P1CODE) return(&P1XBorder); else if (i == NULLCODE) return(&BlackXBorder); else if (i == P2CODE) return(&P2XBorder); default: return(NULL); } } APTR NextXBorder(a,i,j) /* Toggles 'a[i][j]' and returns a pointer to the */ /* the 'XBorder'-structure for 'a[i][j]'. */ char a[MAXCELL][MAXVAL+1]; short i,j; { switch (a[i][j]) { case P1CODE: if (i == NULLCODE) a[i][j] = NOCODE; else a[i][j] = NULLCODE; return(&BlackXBorder); case NULLCODE: if (i == P2CODE) a[i][j] = NOCODE; else a[i][j] = P2CODE; return(&P2XBorder); case P2CODE: if (i == P1CODE) a[i][j] = NOCODE; else a[i][j] = P1CODE; return(&P1XBorder); case NOCODE: switch (i) { case P1CODE: a[i][j] = NULLCODE; return(&BlackXBorder); case NULLCODE: a[i][j] = P2CODE; return(&P2XBorder); case P2CODE: a[i][j] = P1CODE; return(&P1XBorder); } default: return(NULL); } } char TxtBuf[6]; void SumOut(pptr) /* Prints the values for "Cells on Agar" and "Cells */ /* in Freezer". */ register struct StrainData *pptr; { SetDrMd(rp,JAM2); SetAPen(rp,(long)pptr->CellPen); Move(rp,(long)(pptr->ox+138),(long)pptr->oy); sprintf(TxtBuf,"%5d",pptr->LCells); Text(rp,TxtBuf,5L); Move(rp,(long)(pptr->ox+138),(long)(pptr->oy+15)); sprintf(TxtBuf,"%5d",pptr->SCells); Text(rp,TxtBuf,5L); SetAPen(rp,(long)FGPEN); } void ClearAgar(a) /* Sets all cells in the Agar to type 'dead'. */ register char *a; { register USHORT i; for (i=XSIZE*YSIZE;i!=0;i--,a++) *a = NULLCODE; } void SaveAgar() /* Copies the current Agar to the Undo Agar. */ { register char *a,*aa; register USHORT i; a = Agar; AgarNum = 1 - AgarNum; Agar = AgarMem[AgarNum]; aa = Agar; for (i=XSIZE*YSIZE;i!=0;i--,a++,aa++) *aa = *a; } void ProcessMenu(mnum) /* Does exactly that. */ USHORT mnum; { register short i,j; if (mnum != MENUNULL) switch (MENUNUM(mnum)) { case 0: /* 'Project'-Menu */ switch (ITEMNUM(mnum)) { case 0: /* About */ if (!Request(&AboutReq,wd)) DisplayBeep(sc); break; case 1: /* Rules */ for (i=0;iGadgetID) { case P1ID: /* 'Strain 1'-Gadget */ if (gptr->Flags & SELECTED) actp = &(pd[0]); else actp = &(pd[1]); P2Gadget.Flags ^= SELECTED; RefreshGadgets(&P2Gadget,wd,NULL); return; case P2ID: /* 'Strain 2'-Gadget */ if (gptr->Flags & SELECTED) actp = &(pd[1]); else actp = &(pd[0]); P1Gadget.Flags ^= SELECTED; RefreshGadgets(&P1Gadget,wd,NULL); return; case ROKID: /* 'OK' in 'Reset'-Req */ pd[0].LCells = pd[1].LCells = 0; pd[0].SCells = CS1SInfo.LongInt; pd[1].SCells = CS2SInfo.LongInt; pd[0].GRate = GS1SInfo.LongInt; pd[1].GRate = GS2SInfo.LongInt; SumOut(&(pd[0])); SumOut(&(pd[1])); ClearAgar(AgarMem[0]); ClearAgar(AgarMem[1]); DisplayAgar(bm,Agar,XSIZE,YSIZE,AGARLE,AGARTE); return; case RCANID: /* 'CANCEL' in 'Reset'-Requester */ return; case UOKID: /* 'OK' in 'Rules'-Requester */ for (i=0;iGadgetID - UX0ID; if (id >= 0) { i = id / (MAXVAL+1); j = id % (MAXVAL+1); UXGadget[i][j].GadgetRender = NextXBorder(NewCT,i,j); } RefreshGadgets(gptr,wd,&RulesReq); return; } } void ProcessGadgetDown(gptr) /* Gadget pressed (and held?) */ struct Gadget *gptr; { register struct IntuiMessage *Msg; ULONG IDCMPFlags; register short i,j; SaveAgar(); switch (gptr->GadgetID) { case GROWID: /* 'Grow'-Gadget */ for (;;) { ScanAgar(Agar,AuxAgar,CellTrans,XSIZE,YSIZE,MAXVAL+1); ChangeAgar(bm,Agar,AuxAgar,XSIZE,YSIZE,AGARLE,AGARTE); pd[0].SCells += pd[0].GRate; pd[1].SCells += pd[1].GRate; CountCells(Agar,&(pd[0].LCells),&(pd[1].LCells),XSIZE*YSIZE-1); SumOut(&(pd[0])); SumOut(&(pd[1])); if (Msg = (struct IntuiMessage *)GetMsg(wd->UserPort)) { i = Msg->Class; j = Msg->Code; ReplyMsg(Msg); if ((i == GADGETUP) || (j == SELECTUP)) break; } } break; case AGARID: /* Agar */ for (;;) { i = wd->MouseY/3 - AGARTE + 1; j = wd->MouseX/4 - AGARLE + 1; if ((i > 0) && (i < YSIZE-1) && (j > 0) && (j < XSIZE-1)) if ((Agar[i][j] == 1) && (actp->SCells != 0)) { Agar[i][j] = actp->CellCode; actp->LCells ++; actp->SCells --; SetCell(bm,j+AGARLE-1,i+AGARTE-1,actp->CellPen); SumOut(actp); } if (Msg = (struct IntuiMessage *)GetMsg(wd->UserPort)) { i = Msg->Class; j = Msg->Code; ReplyMsg(Msg); if ((i == GADGETUP) || (j == SELECTUP)) break; } } break; } return; } void ProcessRMB(msg) /* Right mouse button */ struct IntuiMessage *msg; { register struct IntuiMessage *Msg; ULONG IDCMPFlags; register short i,j; i = wd->MouseY/3 - AGARTE + 1; j = wd->MouseX/4 - AGARLE + 1; if ((i < 1) || (i > YSIZE-2) || (j < 1) || (j > XSIZE-2)) { ReplyMsg(msg); return; } SaveAgar(); msg->Code = MENUCANCEL; ReplyMsg(msg); for (;;) { i = wd->MouseY/3 - AGARTE + 1; j = wd->MouseX/4 - AGARLE + 1; if ((i > 0) && (i < YSIZE-1) && (j > 0) && (j < XSIZE-1)) if (Agar[i][j] == actp->CellCode) { Agar[i][j] = 1; actp->LCells --; actp->SCells ++; SetCell(bm,j+AGARLE-1,i+AGARTE-1,NULLPEN); SumOut(actp); } if (Msg = (struct IntuiMessage *)GetMsg(wd->UserPort)) { j = Msg->Code; ReplyMsg(Msg); if (j == MENUUP) break; } } return; } #define ERRLEN 70 char ErrorString[ERRLEN]; void CleanUp(txt) char *txt; { short i; if (PointerCMem) { ClearPointer(wd); FreeMem(PointerCMem,(long)sizeof(PointerData)); } if (wd) { ClearMenuStrip(wd); CloseWindow(wd); } if (sc) CloseScreen(sc); if (IntuitionBase) CloseLibrary(IntuitionBase); if (GfxBase) CloseLibrary(GfxBase); if (txt != NULL) { for(i=3;(i < ERRLEN-2) && (txt[i-3] != 0);i++) ErrorString[i] = txt[i-3]; *((short *)ErrorString) = 308 - 4*i; ErrorString[2] = 15; ErrorString[i] = ErrorString[i+1] = 0; DisplayAlert(RECOVERY_ALERT,ErrorString,30L); } exit(0L); }