/********************************************************************/ /* */ /* Hoser BackGammon version 1.0 */ /* */ /* Robert Pfister */ /* */ /* Rfd#3 Box 2340 home:(207)-873-3520 */ /* Waterville, Maine 04901 */ /* */ /* Pfister_rob%dneast@dec.decwrl */ /* */ /* */ /* Copyright June,1987 all rights reserved. */ /* */ /* This program will play a game of backgammon at the novice level */ /* */ /* The code is in 4 parts... */ /* */ /* 1) back.c - main driver */ /* / 2) eval.c - evaluation of moves */ /* \/ 3) backscn.c - screen stuff.. */ /* 4) backmenu.c - menu stuff, help text, and ``decoder'' */ /* */ /* this was compiled under Manx 3.20a, using long integers */ /* */ /********************************************************************/ extern int Uside,Cside; #include #include #include #include #include #include #include #undef NULL #define NULL ((void *) 0) #define NL 0 /* color index's */ #define tm1 0L #define tm2 1L #define back 2L #define spike1 3L #define spike2 4L #define peice1 5L #define peice2 6L #define dice 7L /* now define those colors */ #define backc 0x0F0L #define spike1c 0xFF0L #define spike2c 0xF00L #define peice1c 0x000L #define peice2c 0x00FL #define dicec 0xFFFL #define tm1c 0x606L #define tm2c 0xDDDL static UWORD colors[8]; /* describe the playing field */ #define maxX 637L #define minX 3L #define maxY 189L #define minY 25L #define PerSpike 6L #define MyTitle "Hoser BackGammon Copyright June 1987 Robert Pfister" struct GfxBase *GfxBase; struct IntuitionBase *IntuitionBase; static struct RastPort *rp; static struct ViewPort *vp; static struct Window *w; static struct Screen *screen; extern struct Menu *MyMenu; /* get the menu somewhere else */ struct NewScreen ns = { 0L,0L,640L,200L,3L, 0,1,HIRES, CUSTOMSCREEN,NULL, (UBYTE *)MyTitle, NULL,NULL }; struct NewWindow nw = { 0L,10L,640L,190L,0L,1L, CLOSEWINDOW|MOUSEBUTTONS|MENUPICK, SMART_REFRESH|ACTIVATE|WINDOWDRAG|WINDOWDEPTH, NULL,NULL, (UBYTE *)"BackGammon anyone?", NULL,NULL, 0L,0L,640L,200L,CUSTOMSCREEN }; struct NewWindow crnw = { 20L,20L,600L,170L,0L,1L, CLOSEWINDOW|MOUSEBUTTONS|MENUPICK, WINDOWCLOSE|SMART_REFRESH|ACTIVATE|WINDOWDRAG|WINDOWDEPTH, NULL,NULL, (UBYTE *)"BackGammon credits", NULL,NULL, 0L,0L,640L,200L,CUSTOMSCREEN }; static UWORD AreaBuf[1000]; static PLANEPTR TBuf; static struct TmpRas TRas; static struct AreaInfo AInfo; Gsetup() { long x,size; int i; GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L); if (GfxBase == NULL) Gerror("no graphics lib"); IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L); if (IntuitionBase == NULL) { CloseLibrary(GfxBase); Gerror("no intuition"); } screen = (struct Screen *)OpenScreen(&ns); if (screen == NULL) { CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); Gerror("no screen"); } nw.Screen = screen; w = (struct Window *)OpenWindow(&nw); if (w == NULL) { CloseScreen(screen); CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); Gerror("no window"); } vp = &screen->ViewPort; rp = w->RPort; /* intialize temporary area space */ InitArea(&AInfo,AreaBuf,200L); rp->AreaInfo=&AInfo; TBuf=(PLANEPTR)AllocRaster(640L,200L); if (TBuf==NULL) { ClearMenuStrip(w); /* do this to avoid nasty's */ CloseWindow(w); CloseScreen(screen); CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); Gerror("no raster"); } SetMenuStrip(w,MyMenu); size=RASSIZE(640L,200L); rp->TmpRas=(struct TmpRas *)InitTmpRas(&TRas,TBuf,size); /* load in the colors */ colors[back] =backc; colors[spike1]=spike1c; colors[spike2]=spike2c; colors[peice1]=peice1c; colors[peice2]=peice2c; colors[tm1] =tm1c; colors[tm2] =tm2c; colors[dice] =dicec; for (i=0;i<8;i++) { SetRGB4(vp,(long) i,(long)((colors[i] >>8) & 0xF), (long)((colors[i] >>4) & 0xF), (long)((colors[i] ) & 0xF)); } SetDrMd(rp,JAM1); SetAPen(rp,back); RectFill(rp,minX,minY,maxX,maxY); for (i=1;i<=24;i++) { PutSpike(i,0); } x=((maxX+minX)/2); SetAPen(rp,tm1); RectFill(rp,(long)(x-2),minY,(long)(x+2),maxY); Move(rp,4L,(long)minY-6); SetAPen(rp,peice1); Text(rp,(char *)"Number of Moves Evaluated",25L); } int l1,l2,r1,r2; /* saved dice positions */ /* swap the dice positions on the screen */ SwapDice() { int di[4]; int sr1,sr2; di[0]=l1; di[1]=l2; sr1 =r1; sr2 =r2; Uside=-Uside; Cside=-Cside; ShowDice(di,Cside); di[0]=sr1; di[1]=sr2; ShowDice(di,Uside); } /* put dice on the screen */ ShowDice(d,c) int d[4],c; { int y,x1,x2; char Line[6]; y =(maxY+minY)/2; if (c==Cside) { l1=d[0]; l2=d[1]; x1=40+(maxX+minX)/2; x2=30+x1; } else { r1=d[0]; r2=d[1]; x1=-40+(maxX+minX)/2; x2=-30+x1; } /* cover up dice with dice color */ SetAPen(rp,dice); RectFill(rp,(long) x2-12,(long) y-4,(long) x2+12,(long) y+4); RectFill(rp,(long) x1-12,(long) y-4,(long) x1+12,(long) y+4); if ( (d[0]!=0) && (d[1]!=0)) { /* put in the numbers for the left and right die */ if (c==Uside) SetAPen(rp,peice1); else SetAPen(rp,peice2); Move(rp,(long) x2,(long) y+3); Line[0]='0'+d[0]; Line[1]='\0'; Text(rp,Line,1L); Move(rp,(long) x1,(long) y+3); Line[0]='0'+d[1]; Line[1]='\0'; Text(rp,Line,1L); } } i2s(n1,Line) int n1; char Line[6]; { int i,n; n=n1; for(i=0;i<=4;i++) Line[i]=' '; Line[5]='/0'; Line[4]='0'; /* convert into a string */ for(i=4;(i>=0)&&(n>0);i--) { Line[i]=(n % 10) + '0'; n/=10; } } PutMoveNumber(Number) int Number; { char Line[6]; long x,y; y= minY-6; x= 210; SetAPen(rp,tm1); RectFill(rp,x,(long) y-6,(long) x+40,(long) y+4); i2s(Number,Line); SetAPen(rp,dice); Move(rp,x,y); Text(rp,Line,5L); } static struct IntuiMessage *message; /* return any interesting input from the mouse...note that the window close is automatic */ Whats_up(x) int *x; { unsigned long Class; unsigned short Code; char code; int xm,ym; for (;;) { Wait(1L<< w->UserPort->mp_SigBit); message=(struct IntuiMessage *) GetMsg(w->UserPort); Code =message->Code; Class=message->Class; ReplyMsg(message); if (Class==MENUPICK) { if (Code!=MENUNULL) { *x=(MENUNUM(Code)*100)+(ITEMNUM(Code)*10)+SUBNUM(Code); return('C'); } return(' '); /* aint nothing, better reset */ } /* check if mouse pressed..... */ if ((Class==MOUSEBUTTONS)&& (Code==SELECTDOWN)) { xm=(w->MouseX); ym=(w->MouseY); *x=decode(xm,ym); if (*x==-1) return('D'); else return('P'); } } /* end for ever */ } /* end main */ finit() { FreeRaster(TBuf,640L,200L); CloseWindow(w); CloseScreen(screen); CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); } /* return the 'spike' number given the screen point relative to upper left corner of the window */ decode(x,y) int x,y; { int peice,mid,midy,height,disp; mid=(minX+maxX)/2; if (x>mid) disp=8; else disp=0; height=(maxY-minY)/2.5; midy=(minY+maxY)/2; /* check if dice 'clicked'...indicates unusual end of turn */ if ((y>midy-5)&&(ymid-82)) return(-1); /* check if 'bar' selected */ if ( (x>(mid-10)) && (x<(mid+10)) && (y>height) && (y<(maxY-height)) ) peice=0; else peice= 1+(12*(x+disp))/(maxX-minX); if ( y < (maxY+minY)/2) peice=25-peice; return(peice); } static int ErrSet=FALSE; DoMenuStrip(errmsg) char errmsg[]; { ErrSet=TRUE; SetWindowTitles(w,-1L,errmsg); } UnDoMenuStrip() { if (ErrSet==TRUE) { SetWindowTitles(w,-1L,MyTitle); ErrSet=FALSE; } } /* put up a plain old requestor given 3 strings name...the question/statement of the requestor yes....the positive response no.....the negative response this returns 'true' for the yes, 'false' for the no */ static struct IntuiText RB = {tm1 ,tm2 ,JAM2, 50, 10,NL,(UBYTE *)" ",NL}; static struct IntuiText RY = {spike2,spike1,JAM1, 8, 3,NL,(UBYTE *)"Yes",NL}; static struct IntuiText RN = {spike2,spike1,JAM1, 8, 3,NL,(UBYTE *)"No ",NL}; requestor(name,yes,no) char name[],yes[],no[]; { RB.IText=(UBYTE *)name; RY.IText=(UBYTE *)yes; RN.IText=(UBYTE *)no; return(AutoRequest(w,&RB,&RY,&RN,NULL,NULL,300L,90L)); } Gerror(msg) char *msg; { if (msg) { puts("ERROR: "); puts(msg); puts("\n"); } if (msg) exit(-1); else exit(0); } PutSpike(spk,peices) int spk,peices; { long color,x,y,x1,y1,x2,y2,x3; int disp,n,i,sign; char line[10]; /* pick color of the peices */ if (peices<0) color=peice1; else color=peice2; /* plot the ones on the 'bar' */ x1=-20+(minX+maxX)/2; x2=x1+40; y1=(maxY+minY)/2; if (spk==0) { SetAPen(rp,back); RectFill(rp,x1,y1,x2,(long)(y1+20)); x=((maxX+minX)/2); SetAPen(rp,tm1); RectFill(rp,(long)(x-2),y1,(long)(x+2),maxY); if (peices>0) { PutPeice((long)(x1+20),(long)(y1+10),color); line[0]=('0'+peices); line[1]='\0'; Move(rp,(long)(x1+18),(long)(y1+12)); SetAPen(rp,dice); Text(rp,line,1L); } return(0); } if (spk==25) { SetAPen(rp,back); RectFill(rp,x1,(long)(y1-20),x2,y1); SetAPen(rp,tm1); x=((maxX+minX)/2); RectFill(rp,(long)(x-2),minY,(long)(x+2),y1); if (peices<0) { PutPeice((long)(x1+20),(long)(y1-10),color); line[0]=('0'-peices); line[1]='\0'; Move(rp,(long)(x1+18),(long)(y1-8)); SetAPen(rp,dice); Text(rp,line,1L); } return(0); } n=(maxX-minX)/ 12; y=(maxY-minY)/ 2.5; x=spk; if (x>12) x=25-x; if (x>6) disp=8; else disp=0; x1=(x*n) -(n/2)+minX+disp; x2=(x*n) +minX+disp; x3=((x-1)*n) +minX+disp; /* box in the area around the spike with background color...*/ SetAPen(rp,(long)back); if (spk<13) { sign=-1; y1=maxY-y; y2=maxY; RectFill(rp,x3,y1,x2,y2); } else { sign=1; y1=minY+y; y2=minY; RectFill(rp,x3,y2,x2,y1); } /* color in spike */ if (spk%2 ==1) SetAPen(rp,(long)spike1); else SetAPen(rp,(long)spike2); AreaMove(rp,x1,y1); AreaDraw(rp,x2,y2); AreaDraw(rp,x3,y2); AreaDraw(rp,x1,y1); AreaEnd(rp); if (peices<0) peices=-peices; /* go through number of peices, up to "PerSpike" */ for(i=0;(iPerSpike peices */ if (peices>=PerSpike) { line[0]=('0'+peices); line[1]='\0'; if (spk<13) y2=y2-3; else y2=y2+9; Move(rp,x1,y2); SetAPen(rp,dice); Text(rp,line,1L); } } /* end of PutSpike */ BlinkPeice(board,pos) int board[26],pos; { int part,n,x1,y,disp,sign,i; PutSpike(pos,board[pos]); if (board[pos]==0) return(0); /* Dont bother if nothing there */ part=(maxX-minX)/ 12; n=board[pos]; if (n<0) n=0-n; if (n>PerSpike) n=PerSpike; if (pos<13) { i=pos; sign=+1; y=maxY-(n*10)+4; } else { i=25-pos; y=minY+(n*10)-4; } if (i>6) disp=8; else disp=0; /* this is the x-coord */ x1=(i*part) - (part/2)+minX+disp; /* if the bar, do something different */ if (pos==0) { y=((maxY+minY)/2)+10; x1=((maxX+minX)/2); } if (pos==25) { y=((maxY+minY)/2)-10; x1=((maxX+minX)/2); } if (board[pos]<0) n=peice1; else n=peice2; for(i=1;i<=5;i++) { Delay(1); PutPeice(x1,y,dice); Delay(1); PutPeice(x1,y,n); } } static WORD shapeX[9]={15,15,4,-4,-15,-15,-4,4,15}; static WORD shapeY[9]={-2,2,4,4,2,-2,-4,-4,-2}; PutPeice(x,y,color) long x,y,color; { int i; long x1,y1; SetAPen(rp,color); AreaMove(rp,(long)(x+shapeX[0]),(long)(y+shapeY[0])); for (i=1;i<=8;i++) { x1=x+shapeX[i]; y1=y+shapeY[i]; AreaDraw(rp,x1,y1); } AreaEnd(rp); } TextScreen(stuff,num) char *stuff[]; int num; { int i; unsigned long Class; unsigned short Code; struct IOStdReq *re ,*wr; struct MsgPort *rep,*wrp; struct RastPort *crp; struct Window *crw; crnw.Screen=screen; crnw.Title=(UBYTE *) stuff[0]; crw = (struct Window *)OpenWindow(&crnw); if (crw != NULL) { crp=w->RPort; rep=CreatePort("my.con.read",0); re=CreateStdIO(rep); wrp=CreatePort("my.con.write",0); wr=CreateStdIO(wrp); wr->io_Data=(APTR) crw; wr->io_Length=sizeof(*crw); if (OpenDevice("console.device",0,wr,0)==0) { re->io_Device = wr->io_Device; re->io_Unit = wr->io_Unit; /* loop through all the stuff and put it to the open'd console */ for (i=1;i<=num; i++) { wr->io_Command=CMD_WRITE; wr->io_Data =(UBYTE *) stuff[i]; wr->io_Length =-1; DoIO(wr); } /* close the console up */ DeleteStdIO(re); DeletePort(rep); DeleteStdIO(wr); DeletePort(wrp); }/* end-if console created */ for (;;) { Wait(1L<< crw->UserPort->mp_SigBit); message=(struct IntuiMessage *) GetMsg(crw->UserPort); Code =message->Code; Class=message->Class; ReplyMsg(message); if (Class==CLOSEWINDOW) break; } CloseWindow(crw); } /* end-if window opened */ return; }