home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
618a.lha
/
GoLD
/
GoLD.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-02
|
29KB
|
1,403 lines
/***************************************************************************
* *
* '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 <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#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;i<MAXCELL;i++)
for (j=0;j<=MAXVAL;j++) {
UXGadget[i][j] = UXGadget[0][0];
UXGadget[i][j].GadgetID = c;
c++;
UXGadget[i][j].LeftEdge += (j * 16);
UXGadget[i][j].TopEdge += (i * 12);
UXGadget[i][j].GadgetRender = XBorder(CellTrans,i,j);
if (j == MAXVAL)
if (i == MAXCELL-1) UXGadget[i][j].NextGadget = NULL;
else UXGadget[i][j].NextGadget = &(UXGadget[i+1][0]);
else
UXGadget[i][j].NextGadget = &(UXGadget[i][j+1]);
}
/***
*
* INITIALISE PLAYER/STRAIN DATA
*
***/
actp = &(pd[1]);
actp->LCells = 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;i<MAXCELL;i++)
for (j=0;j<=MAXVAL;j++) {
NewCT[i][j] = CellTrans[i][j];
UXGadget[i][j].GadgetRender = XBorder(NewCT,i,j);
}
SetAPen(rp,(long)FGPEN);
SetDrMd(rp,JAM1);
if (!Request(&RulesReq,wd)) DisplayBeep(sc);
break;
case 2: /* Reset */
SetAPen(rp,(long)FGPEN);
SetDrMd(rp,JAM1);
if (!Request(&ResetReq,wd)) DisplayBeep(sc);
break;
case 3: /* Quit */
CleanUp(NULL);
break;
}
break;
case 1: /* 'Edit'-Menu */
switch (ITEMNUM(mnum)) {
case 0: /* Undo */
AgarNum = 1 - AgarNum;
Agar = AgarMem[AgarNum];
CountCells(Agar,&(pd[0].LCells),&(pd[1].LCells),XSIZE*YSIZE-1);
SumOut(&(pd[0]));
SumOut(&(pd[1]));
DisplayAgar(bm,Agar,XSIZE,YSIZE,AGARLE,AGARTE);
break;
case 1: /* Clear Agar */
pd[0].SCells += pd[0].LCells;
pd[1].SCells += pd[1].LCells;
pd[0].LCells = pd[1].LCells = 0;
SumOut(&(pd[0]));
SumOut(&(pd[1]));
AgarNum = 1 - AgarNum;
Agar = AgarMem[AgarNum];
ClearAgar(Agar);
DisplayAgar(bm,Agar,XSIZE,YSIZE,AGARLE,AGARTE);
break;
}
break;
}
}
void ProcessGadgetUp(gptr) /* Gadget clicked */
struct Gadget *gptr;
{
short i,j,id;
switch (gptr->GadgetID) {
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;i<MAXCELL;i++)
for (j=0;j<=MAXVAL;j++)
CellTrans[i][j] = NewCT[i][j];
return;
case UCANID: /* 'CANCEL' in 'Rules'-Requester */
return;
case AOKID: /* 'OK' in 'About'-Requester */
return;
default: /* an 'X' in 'Rules'-Requester */
id = gptr->GadgetID - 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);
}