/* AmiGo Interface. Started 4/7/88 by Todd R. Johnson */ /* 8/8/89 Cleaned up for first release */ /* Version 1.0 */ /* Public Domain */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "go.h" #include "menus.h" extern UWORD BlackStoneData[], WhiteStoneData[], IntersectData[], starPointData[], ULIntersectData[], UMIntersectData[], URIntersectData[], LCIntersectData[], RMIntersectData[], LLIntersectData[], LMIntersectData[], LRIntersectData[]; extern struct Menu game; extern short showTrees, playLevel, showMoveReason, groupInfo, computerBlack, computerWhite; extern enum bVal color; /* Procedures from this file */ void amigainit(); void PrintBoard(); void amigaexit(); void getinput( short *, short *, short *, short ); void processMenuItem( int, short *); short Intersection( short, short, short *, short * ); void removestone( short, short ); void intrMoveReport( enum bVal, char *, char * ); void intrPass( enum bVal ); void intrPrisonerReport( short, short ); void intrInitScratchArea(); void intrPuts( char * ); void intrPutLn(); void intrPutshort( short ); void intrCredits(); /* Amiga display vars */ struct GfxBase *GfxBase; struct Screen *Screen; struct NewWindow nw; struct Window *window; struct RastPort *rp; struct ViewPort *vp; struct IntuiMessage *message; short sx, sy; /* Scratch area line pointers */ struct NewScreen NewScreen = { 0, 0, /* LeftEdge, TopEdge */ 640, 200, /* Width, Height */ 4, /* Depth */ 0, 0, /* DetailPen, BlockPen */ HIRES, /* ViewModes */ CUSTOMSCREEN, /* Type */ NULL, /* Font */ NULL, /* DefaultTitle */ NULL, /* Gadgets */ NULL, /* CustomBitMap */ }; USHORT NullColorTable[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; USHORT ColorTable[] = { 0x148, /* Screen background */ 0xFFF, 0xD95, /* Board background */ 0x000, /* Board Lines */ 0x000, /* Black stone */ 0xFFF, /* White stone */ 0x5D0, 0x7DF, 0x0ED, 0x7DF, 0xC0E, 0x000, 0xF2E, 0xF7D, 0xFDD, 0x000, }; struct Image BlackStoneImage = { -7, -3, /* left top */ 15, 7, 2, /* width, height, depth */ BlackStoneData, /* Image data */ 0x6, 0x0, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image WhiteStoneImage = { -7, -3, /* left top */ 15, 7, 3, /* width, height, depth */ WhiteStoneData, /* Image data */ 0x7, 0x0, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image IntersectImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ IntersectData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image ULIntersectImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ ULIntersectData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image UMIntersectImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ UMIntersectData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image URIntersectImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ URIntersectData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image LCIntersectImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ LCIntersectData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image RMIntersectImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ RMIntersectData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image LLIntersectImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ LLIntersectData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image LMIntersectImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ LMIntersectData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image LRIntersectImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ LRIntersectData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; struct Image starPointImage = { -7, -3, /* left top */ 15, 7, 1, /* width, height, depth */ starPointData, /* Image data */ 0x1, 0x2, /* PlanePick, PlaneOnOff */ NULL, /* NextImage */ }; short starPoint[] = { 3, 9, 15 }; #define linecolor 3 #define boardcolor 2 #define bxoffset 28 #define byoffset 5 #define xedge 10 /* Width of the x border */ #define yedge 5 /* Width of the y border */ #define bxmin 0 + bxoffset #define bxmax 396 + bxoffset #define bymin 0 + byoffset #define bymax 180 + byoffset #define ylinestretch 10 #define xlinestretch 22 #define BLACKCOLOR 4 #define WHITECOLOR 5 #define titleX bxmax + 63 #define titleY bymin + 5 #define bprisonerX bxmax + 15 #define bprisonerY bymin + 15 #define wprisonerX bprisonerX #define wprisonerY bprisonerY + 10 #define REPLEN 25 /* Line length of report area */ #define reportX bxmax + 15 #define reportY wprisonerY + 10 #define reasonX reportX #define reasonY reportY + 10 #define scratchX reasonX #define scratchY reasonY + 10 #define scratchLines 14 #define minStack 21000L void amigainit() { ULONG stacksize; struct Process *Process; char *mem; /* Check stack size */ Process = (struct Process *)FindTask(0L); stacksize = *((ULONG *)Process->pr_ReturnAddr); if (stacksize < minStack) { printf("Stack size is %ld\n",stacksize); printf("Stack must be at least %ld to run AmiGo\n", minStack); exit(1); } if (!(GfxBase = (struct GfxBase*)OpenLibrary("graphics.library", 1))) { printf("no graphic library"); exit(1); } if (!(IntuitionBase = (struct IntuitionBase*)OpenLibrary("intuition.library", 1))) { CloseLibrary(GfxBase); printf( "no intuition here\n" ); exit(1); } /* Open the screen */ if ((Screen = (struct Screen *)OpenScreen(&NewScreen)) == NULL) exit(FALSE); nw.LeftEdge = 0; nw.TopEdge = 0; nw.Width = 640; nw.Height = 200; nw.DetailPen = 15; nw.BlockPen = 5; nw.Flags = SMART_REFRESH | ACTIVATE | BORDERLESS; nw.IDCMPFlags = MOUSEBUTTONS | MENUPICK; nw.FirstGadget = NULL; /* Add this below */ nw.CheckMark = NULL; nw.Title = NULL; nw.Screen = Screen; nw.BitMap = NULL; nw.Type = CUSTOMSCREEN; /* Open the window */ if ((window = (struct Window*)OpenWindow(&nw)) == NULL) exit (FALSE); vp = (struct ViewPort*)ViewPortAddress(window); rp = window->RPort; LoadRGB4( vp, &ColorTable, 16 ); PrintBoard(); Move( rp, titleX, titleY ); Text( rp, "AmiGo 1.0", 9 ); SetMenuStrip( window, &game ); } void PrintBoard() { short x, y, i = 0; char *horizontal = "19181716151413121110 9 8 7 6 5 4 3 2 1"; char *vertical = "ABCDEFGHJKLMNOPQRST"; SetAPen( rp, boardcolor ); RectFill( rp, bxmin - xedge, bymin - yedge, bxmax + xedge, bymax + yedge ); SetAPen( rp, linecolor ); for (y = bymin; y <= bymax; y = y + ylinestretch ) { Move( rp, bxmin, y ); Draw( rp, bxmax, y ); /* Print the algebraic label */ Move( rp, bxmin - xedge - 18, y + 3); Text( rp, horizontal + i, 2 ); i += 2; } i = 0; for (x = bxmin; x <= bxmax; x = x + xlinestretch ) { Move( rp, x, bymin ); Draw( rp, x, bymax ); Move( rp, x - 3, bymax + 13 ); Text( rp, vertical + i, 1 ); i++; } /* Draw the star points */ for (y = 0; y <= 2; y++) for (x = 0; x <= 2; x++) DrawImage( rp, &starPointImage, starPoint[x] * xlinestretch + bxoffset, starPoint[y] * ylinestretch + byoffset); } void amigaexit() { #ifdef DEBUG printf( "Freeing image data\n" ); #endif /* FreeMem( BlackStoneImage.ImageData, sizeof(USHORT) * 14l ); FreeMem( WhiteStoneImage.ImageData, sizeof(USHORT) * 21l ); FreeMem( IntersectImage.ImageData, sizeof(USHORT) * 7l ); */ CloseWindow(window); CloseScreen(Screen); #ifdef DEBUG printf( "Closing intuition\n" ); #endif /* CloseLibrary((struct IntuitionBase *)IntuitionBase); */ #ifdef DEBUG printf( "Closing Gfx\n"); #endif CloseLibrary(GfxBase); } /* Get input from the user */ /* msg = type of input */ /* xstone ystone is location where user wants to put a stone */ /* if continue is true, the routine will return if no message is present */ void getinput(msg, xstone, ystone, cont) short *msg, *xstone, *ystone, cont; { struct IntuiMessage *imsg; struct MenuItem *item; int class, code; short xlast, ylast, oldx, oldy, newx, newy, mousex, mousey; *msg = NULL; while( TRUE ) { if (((imsg = (struct IntuiMessage*)GetMsg(window->UserPort)) == NULL) && cont) return; if (imsg == NULL) while ((imsg = (struct IntuiMessage*)GetMsg(window->UserPort)) == NULL) Wait(1<UserPort->mp_SigBit); class = imsg->Class; code = imsg->Code; mousex = imsg->MouseX - bxoffset; mousey = imsg->MouseY - byoffset; ReplyMsg( imsg ); switch( class ) { case MOUSEBUTTONS: if (code == SELECTDOWN) { /* Save mouse position for possible move */ xlast = mousex; ylast = mousey; } if (code == SELECTUP) { if (! Intersection( xlast, ylast, &oldx, &oldy )) continue; if (! Intersection( mousex, mousey, &newx, &newy )) continue; /* two valid intersections were selected */ /* are they the same? */ if ((oldx == newx) && (oldy == newy)) { /* They are the same */ *msg = INTERSECTIONMSG; *xstone = newx; *ystone = newy; return; } } break; case CLOSEWINDOW: *msg = QUITMSG; return; case MENUPICK: /* Process Menu selections */ while (code != MENUNULL) { item = ItemAddress( &game, code ); processMenuItem( code, msg ); code = item->NextSelect; } if (*msg) return; break; } /* switch */ } /* while */ } /* getinput */ void processMenuItem( num, msg ) int num; short *msg; { switch (MENUNUM(num)) { case GAME: switch (ITEMNUM(num)) { case PLAY: { OffMenu( window, GAME | SHIFTITEM(PLAY) ); OffMenu( window, OPTION | SHIFTITEM(BLACKTOPLAY) ); OffMenu( window, OPTION | SHIFTITEM(WHITETOPLAY) ); OnMenu( window, GAME | SHIFTITEM(RESTART) ); OnMenu( window, MOVE | SHIFTITEM(PASS) ); *msg = PLAYMSG; return; } case RESTART: { OffMenu( window, GAME | SHIFTITEM(RESTART) ); OffMenu( window, MOVE | SHIFTITEM(PASS) ); OnMenu( window, GAME | SHIFTITEM(PLAY) ); OnMenu( window, OPTION | SHIFTITEM(BLACKTOPLAY) ); OnMenu( window, OPTION | SHIFTITEM(WHITETOPLAY) ); *msg = RESTARTMSG; return; } case QUIT: { *msg = QUITMSG; return; } } case OPTION: switch(ITEMNUM(num)) { case SETPLAYLEVEL: { playLevel = SUBNUM(num) + 1; return; } case HUMANVSHUMAN: { computerBlack = FALSE; computerWhite = FALSE; OffMenu( window, OPTION | SHIFTITEM(AMIGAPLAYSBLACK) ); OffMenu( window, OPTION | SHIFTITEM(AMIGAPLAYSWHITE) ); OffMenu( window, OPTION | SHIFTITEM(SETPLAYLEVEL) | SHIFTSUB(NOSUB) ); return; } case AMIGAVSAMIGA: { computerBlack = TRUE; computerWhite = TRUE; OffMenu( window, OPTION | SHIFTITEM(AMIGAPLAYSBLACK) ); OffMenu( window, OPTION | SHIFTITEM(AMIGAPLAYSWHITE) ); OnMenu( window, OPTION | SHIFTITEM(SETPLAYLEVEL) | SHIFTSUB(NOSUB) ); return; } case AMIGAVSHUMAN: { computerBlack = TRUE; computerWhite = FALSE; OnMenu( window, OPTION | SHIFTITEM(AMIGAPLAYSBLACK) ); OnMenu( window, OPTION | SHIFTITEM(AMIGAPLAYSWHITE) ); OnMenu( window, OPTION | SHIFTITEM(SETPLAYLEVEL) | SHIFTSUB(NOSUB) ); return; } case AMIGAPLAYSBLACK: { computerBlack = TRUE; computerWhite = FALSE; return; } case AMIGAPLAYSWHITE: { computerBlack = FALSE; computerWhite = TRUE; return; } case BLACKTOPLAY: { color = BLACK; return; } case WHITETOPLAY: { color = WHITE; return; } } case MOVE: switch (ITEMNUM(num)) { case PASS: { *msg = PASSMSG; return; } } case INFO: switch (ITEMNUM(num)) { case SHOWLOOKAHEAD: { showTrees = ! showTrees; return; } case MOVEREASON: { showMoveReason = ! showMoveReason; return; } case GROUPINFO: { groupInfo = ! groupInfo; return; } } } } short Intersection( mx, my, ix, iy ) short mx, my, *ix, *iy; { short rem; if ((bxmin - 2 <= mx + bxoffset) && (bxmax + 2 >= mx + bxoffset) && (bymin - 2 <= my + byoffset) && (bymax + 2 >= my + byoffset)) { /* Calculate closest intersection */ *ix = mx / xlinestretch; rem = mx % xlinestretch; if ((rem == (xlinestretch - 1)) || (rem == xlinestretch - 2)) *ix = *ix + 1; else if ((rem != xlinestretch) && (! (rem <= 3))) return FALSE; /* Too far from intersection */ /* ix is correct */ *iy = my / ylinestretch; rem = my % ylinestretch; if ((rem == (ylinestretch - 1)) || (rem == ylinestretch - 2)) *iy = *iy + 1; else if ((rem != ylinestretch) && (! (rem <= 3))) return FALSE; /* Too far from intersection */ /* iy is correct */ return TRUE; } return FALSE; } /* Print a stone of color at x, y intersection */ void placestone(color, x, y) enum bVal color; short x, y; { if (color == BLACK) DrawImage( rp, &BlackStoneImage, x * xlinestretch + bxoffset, y * ylinestretch + byoffset ); else DrawImage( rp, &WhiteStoneImage, x * xlinestretch + bxoffset, y * ylinestretch + byoffset ); } /* Remove a stone from an intersection */ void removestone( x, y ) short x, y; { short sx, sy, starX = FALSE, starY = FALSE; unsigned short i; sx = x * xlinestretch + bxoffset; sy = y * ylinestretch + byoffset; /* Is it a star point? */ for (i = 0; i <= 2; i++) { if (x == starPoint[i]) starX = TRUE; if (y == starPoint[i]) starY = TRUE; } if (starX && starY) DrawImage( rp, &starPointImage, sx, sy ); else /* Determine type of regular intersection */ if (x == 0) if (y == 0) DrawImage( rp, &ULIntersectImage, sx, sy ); else if (y == 18) DrawImage( rp, &LLIntersectImage, sx, sy ); else DrawImage( rp, &LCIntersectImage, sx, sy ); else if (y == 0) if (x == 18) DrawImage( rp, &URIntersectImage, sx, sy ); else DrawImage( rp, &UMIntersectImage, sx, sy ); else if (y == 18) if (x == 18) DrawImage( rp, &LRIntersectImage, sx, sy ); else DrawImage( rp, &LMIntersectImage, sx, sy ); else if (x == 18) DrawImage( rp, &RMIntersectImage, sx, sy ); else DrawImage( rp, &IntersectImage, sx, sy ); } /* Report on a move */ void intrMoveReport( color, coord, reason ) enum bVal color; char *coord, *reason; { char *spaces = " "; int len; Move( rp, reportX, reportY ); Text( rp, spaces, REPLEN ); Move( rp, reportX, reportY ); if (color == BLACK) Text( rp, "Black at ", 9 ); else Text( rp, "White at ", 9 ); Text( rp, coord, 3 ); if (! showMoveReason) return; len = strlen( reason ); Move( rp, reasonX, reasonY ); Text( rp, spaces, REPLEN ); Move( rp, reasonX, reasonY ); Text( rp, reason, len ); } void intrPass( color ) enum bVal color; { Move( rp, reportX, reportY ); if (color == BLACK) Text( rp, "Black Passes ", REPLEN ); else Text( rp, "White Passes ", REPLEN ); } void intrPrisonerReport( blackcnt, whitecnt ) short blackcnt, whitecnt; { char *num = " ", *spaces = " "; int len; Move( rp, bprisonerX, bprisonerY ); Text( rp, spaces, 20 ); Move( rp, bprisonerX, bprisonerY ); Text( rp, "Black: ", 7 ); len = stci_d( num, (int)blackcnt ); Text( rp, num, len ); Move( rp, wprisonerX, wprisonerY ); Text( rp, spaces, 20 ); Move( rp, wprisonerX, wprisonerY ); Text( rp, "White: ", 7 ); len = stci_d( num, (int)whitecnt ); Text( rp, num, len ); } void intrInitScratchArea() { short i; char *spaces = " "; sx = scratchX; sy = scratchY; for (i = 0; i < scratchLines; i++) { Move( rp, sx, sy ); Text( rp, spaces, REPLEN ); sy += 10; } sx = scratchX; sy = scratchY; Move( rp, sx, sy ); } void intrPuts( s ) char *s; { int len; len = strlen( s ); if (len > REPLEN) len = REPLEN; Text( rp, s, len ); } void intrPutLn() { sx = scratchX; sy += 10; Move( rp, sx, sy ); } void intrPutshort( n ) short n; { int len; char *num = " "; len = stci_d( num, (short)n ); Text( rp, num, len ); } void intrCredits() { intrPuts( "Player by Stoney Ballard" ); intrPutLn(); intrPuts( "C port and interface"); intrPutLn(); intrPuts( "by Todd R. Johnson"); intrPutLn(); intrPutLn(); intrPuts( "To place handicap or" ); intrPutLn(); intrPuts( "set up a position use" ); intrPutLn(); intrPuts( "the mouse to cycle the" ); intrPutLn(); intrPuts( "contents of a location" ); intrPutLn(); intrPuts( "from empty to black to" ); intrPutLn(); intrPuts( "white to empty." ); intrPutLn(); intrPutLn(); intrPuts( "Use menus to set options." ); intrPutLn(); intrPuts( "Select the Play menu" ); intrPutLn(); intrPuts( "item to begin play." ); }