APP Chess TYPE 0 ICON "\OPD\CHESS.PIC" ENDA PROC chess: GLOBAL pb$(10),pw$(10),c$(6,1),l$(6,6),p%(64),f%,g%,q%,s%,t%,r%,w%,z%,c,m,sm%,cs%(4),g$(1) ESCAPE OFF vars: window: ONERR error DO players: start: r%=0 :g%=1 :z%=1 :c=1 :t%=20 :q%=0 DO cont:: IF z% :redraw: :f%=0 :sm%=0 :ELSE :z%=1 :ENDIF input: UNTIL q% IF q%<>1 :new: :ENDIF UNTIL 0 error:: ONERR OFF CLS PRINT "Unexpected error:",ERR$(ERR) PRINT "(C)ontinue or E(x)it?" DO :g$=LOWER$(GET$) :UNTIL g$="c" OR g$="x" IF g$="c" :z%=1 :CLS :ONERR error :GOTO cont :ENDIF ENDP PROC vars: c$(1)="P" :l$(1)="Pawn" c$(2)="R" :l$(2)="Rook" c$(3)="N" :l$(3)="Knight" c$(4)="B" :l$(4)="Bishop" c$(5)="Q" :l$(5)="Queen" c$(6)="K" :l$(6)="King" pw$="Player 1" pb$="Player 2" s%=2 ENDP PROC window: DEFAULTWIN 1 STATUSWIN ON,s% FONT 12,0 gBORDER $200 ENDP PROC players: dINIT "Players' names" dEDIT pw$,"White" dEDIT pb$,"Black" LOCK ON DIALOG LOCK OFF ENDP PROC start: LOCAL a% p%(1)=2 :p%(2)=3 :p%(3)=4 :p%(4)=6 p%(5)=5 :p%(6)=4 :p%(7)=3 :p%(8)=2 a%=9 DO :p%(a%)=1 :a%=a%+1 :UNTIL a%=17 DO :p%(a%)=0 :a%=a%+1 :UNTIL a%=49 DO :p%(a%)=11 :a%=a%+1 :UNTIL a%=57 p%(57)=12 :p%(58)=13 :p%(59)=14 :p%(60)=16 p%(61)=15 :p%(62)=14 :p%(63)=13 :p%(64)=12 cs%(1)=1 :cs%(2)=1 :cs%(3)=1 :cs%(4)=1 ENDP PROC redraw: LOCAL a%,x,y a%=1 :w%=gWIDTH/2-80 gUPDATE OFF clear: IF r%=1 :x=7 ELSEIF r%=2 :x=7 :y=7 ELSEIF r%=3 :y=7 ENDIF DO place:(x,y,a%) a%=a%+1 IF r%=0 :x=x+1 :IF x=8 :x=0 :y=y+1 :ENDIF ELSEIF r%=1 :y=y+1 :IF y=8 :y=0 :x=x-1 :ENDIF ELSEIF r%=2 :x=x-1 :IF x=-1 :x=7 :y=y-1 :ENDIF ELSEIF r%=3 :y=y-1 :IF y=-1 :y=7 :x=x+1 :ENDIF ENDIF UNTIL a%=65 gGREY 0 IF g%=1 :gSTYLE 36 :ELSE :gSTYLE 32 :ENDIF gAT 1,20 gPRINTB "White",w%-2,3 IF g%=2 :gSTYLE 36 :ELSE :gSTYLE 32 :ENDIF gAT w%+161,20 gPRINTB "Black",w%-2,3 IF g%=1 :gSTYLE 12 :ELSE :gSTYLE 8 :ENDIF gAT 1,50 gPRINTB pw$,w%-2,3 IF g%=2 :gSTYLE 12 :ELSE :gSTYLE 8 :ENDIF gAT w%+161,50 gPRINTB pb$,w%-2,3 IF g%>2 :hilite:(m) :ENDIF gUPDATE gSTYLE 0 ENDP PROC clear: gGREY 2 :gAT w%,0 :gFILL 160,160,1 gGREY 0 :gAT w%,0 :gBOX 160,160 ENDP PROC place:(x,y,a%) gGREY 1 IF ((x+y+r%+1)/2)=INT((x+y+r%+1)/2) gAT w%+x*20,y*20 gFILL 20,20,0 ENDIF IF p%(a%)>0 gAT w%+x*20+3,y*20+3 gFILL 14,14,1 gGREY 0 IF p%(a%)>9 gAT w%+x*20+4,y*20+4 gFILL 12,12,0 ELSE gAT w%+x*20+3,y*20+3 gBOX 14,14 ENDIF gTMODE 2 gAT w%+x*20+6,y*20+15 gPRINT c$(rem:(FLT(p%(a%)),10)) ENDIF ENDP PROC input: LOCAL e%(6),k%,m% IF TESTEVENT GETEVENT e%() k%=e%(1) m%=e%(2) AND $00ff IF k%=44 r%=r%-1 IF r%<0 :r%=3 :ENDIF ELSEIF k%=46 r%=r%+1 IF r%=4 :r%=0 :ENDIF ELSEIF k%=290 AND (m% AND 4) s%=s%-1 IF s%=-1 :s%=2 :ENDIF window: ELSEIF k%=256 IF sm% AND g%<3 :moves: :sm%=0 :ENDIF IF r%=0 AND c>8 :u: ELSEIF r%=1 AND (c-1)/8<>INT((c-1)/8) :l: ELSEIF r%=2 AND c<57 :d: ELSEIF r%=3 AND c/8<>INT(c/8) :r: ENDIF z%=0 ELSEIF k%=257 IF sm% AND g%<3 :moves: :sm%=0 :ENDIF IF r%=0 AND c<57 :d: ELSEIF r%=1 AND c/8<>INT(c/8) :r: ELSEIF r%=2 AND c>8 :u: ELSEIF r%=3 AND (c-1)/8<>INT((c-1)/8) :l: ENDIF z%=0 ELSEIF k%=258 IF sm% AND g%<3 :moves: :sm%=0 :ENDIF IF r%=0 AND c/8<>INT(c/8) :r: ELSEIF r%=1 AND c>8 :u: ELSEIF r%=2 AND (c-1)/8<>INT((c-1)/8) :l: ELSEIF r%=3 AND c<57 :d: ENDIF z%=0 ELSEIF k%=259 IF sm% AND g%<3 :moves: :sm%=0 :ENDIF IF r%=0 AND (c-1)/8<>INT((c-1)/8) :l: ELSEIF r%=1 AND c<57 :d: ELSEIF r%=2 AND c/8<>INT(c/8) :r: ELSEIF r%=3 AND c>8 :u: ENDIF z%=0 ELSEIF k%=13 OR k%=32 IF g%<3 choose: ELSE move: ENDIF ELSEIF k%=27 IF g%>2 IF sm% :moves: :sm%=0 :ENDIF g%=g%-2 hilite:(m) ENDIF z%=0 ELSEIF k%=290 menu: ELSEIF k%=291 help: z%=0 ELSEIF k%=621 OR k%=109 IF sm%=0 :moves: :ENDIF sm%=1 z%=0 ELSEIF k%=622 new2: ELSEIF k%=624 players: ELSEIF k%=632 exit: z%=0 ELSEIF k%=$404 IF LEFT$(GETCMD$,1)="X" :STOP :ENDIF ELSE z%=0 ENDIF ELSE IF t%=20 f%=1-f% t%=0 hilite:(c) ENDIF t%=t%+1 z%=0 ENDIF ENDP PROC choose: IF p%(c)=0 :GIPRINT "No piece chosen" ELSEIF g%=1 AND p%(c)>9 :GIPRINT "White's turn!" ELSEIF g%=2 AND p%(c)<9 :GIPRINT "Black's turn!" ELSE gAT (g%-1)*(w%+160)+1,80 gPRINTB l$(p%(c)-10*(g%-1)),w%-2,3 g%=g%+2 m=c hilite:(c) ENDIF z%=0 ENDP PROC move: LOCAL ok%,t IF (p%(c)=0) OR (g%=3 AND p%(c)>9) OR (g%=4 AND p%(c)<10) IF p%(m)=1 :ok%=pawnw:(1) ELSEIF p%(m)=11 :ok%=pawnb:(1) ELSEIF p%(m)=2 OR p%(m)=12 :ok%=rook:(1) ELSEIF p%(m)=3 OR p%(m)=13 :ok%=knight: ELSEIF p%(m)=4 OR p%(m)=14 :ok%=bishop: ELSEIF p%(m)=5 OR p%(m)=15 :ok%=queen: ELSEIF p%(m)=6 OR p%(m)=16 :ok%=king:(1) ENDIF IF ok% t=p%(c) p%(c)=p%(m) p%(m)=0 IF check:(g%-2) GIPRINT "Into check!" p%(m)=p%(c) p%(c)=t z%=0 ELSE g%=3-(g%-2) IF t>0 :GIPRINT l$(rem:(t,10))+" taken" :ENDIF IF check:(g%) :GIPRINT "Check" :ENDIF ENDIF ELSE GIPRINT "Bad move" z%=0 ENDIF ELSE GIPRINT "Bad move" z%=0 ENDIF ENDP PROC pawnw:(c%) IF (p%(c)=0 AND (c=m+8 OR (c=m+16 AND m<17 AND p%(m+8)=0))) OR (p%(c)<>0 AND (c=m+7 OR c=m+9)) IF c>55 AND c% :p%(m)=5 :ENDIF RETURN 1 ENDIF ENDP PROC pawnb:(c%) IF (p%(c)=0 AND (c=m-8 OR (c=m-16 AND m>47 AND p%(m-8)=0))) OR (p%(c)<>0 AND (c=m-7 OR c=m-9)) IF c<9 AND c% :p%(m)=15 :ENDIF RETURN 1 ENDIF ENDP PROC rook:(c%) LOCAL t IF c>(INT((m-1)/8)*8) AND c<(INT((m-1)/8)*8)+9 IF c0 :RETURN 0 :ENDIF t=t-1 UNTIL t=c ELSEIF c>m+1 t=m+1 DO IF p%(t)>0 :RETURN 0 :ENDIF t=t+1 UNTIL t=c ENDIF IF m=1 AND c% AND cs%(1) :cs%(1)=0 :ENDIF IF m=8 AND c% AND cs%(2) :cs%(2)=0 :ENDIF IF m=64 AND c% AND cs%(3) :cs%(3)=0 :ENDIF IF m=57 AND c% AND cs%(4) :cs%(4)=0 :ENDIF RETURN 1 ELSEIF rem:(c,8)=rem:(m,8) IF c0 :RETURN 0 :ENDIF t=t-8 UNTIL t=c ELSEIF c>m+8 t=m+8 DO IF p%(t)>0 :RETURN 0 :ENDIF t=t+8 UNTIL t=c ENDIF IF m=1 AND c% AND cs%(1) :cs%(1)=0 :ENDIF IF m=8 AND c% AND cs%(2) :cs%(2)=0 :ENDIF IF m=64 AND c% AND cs%(3) :cs%(3)=0 :ENDIF IF m=57 AND c% AND cs%(4) :cs%(4)=0 :ENDIF RETURN 1 ENDIF ENDP PROC knight: LOCAL x% x%=rem:(m,8) IF x%=0 :x%=8 :ENDIF IF ((c=m-17 OR c=m+15) AND x%>1) OR ((c=m-15 OR c=m+17) AND x%<8) OR ((c=m-10 OR c=m+6) AND x%>2) OR ((c=m-6 OR c=m+10) AND x%<7) RETURN 1 ENDIF ENDP PROC bishop: LOCAL c1%,c2%,r1%,r2%,t c1%=rem:(m,8) :r1%=(m-1)/8 c2%=rem:(c,8) :r2%=(c-1)/8 IF c1%=0 :c1%=8 :ENDIF IF c2%=0 :c2%=8 :ENDIF IF ABS(c2%-c1%)<>ABS(r2%-r1%) :RETURN 0 :ENDIF IF c=m-9 OR c=m-7 OR c=m+7 OR c=m+9 :RETURN 1 :ENDIF IF c2%0 :RETURN 0 :ENDIF t=t-9 UNTIL t=c ELSEIF c2%>c1% AND r2%0 :RETURN 0 :ENDIF t=t-7 UNTIL t=c ELSEIF c2%r1% t=m+7 DO IF p%(t)>0 :RETURN 0 :ENDIF t=t+7 UNTIL t=c ELSEIF c2%>c1% AND r2%>r1% t=m+9 DO IF p%(t)>0 :RETURN 0 :ENDIF t=t+9 UNTIL t=c ENDIF RETURN 1 ENDP PROC queen: IF rook:(0) OR bishop: :RETURN 1 :ENDIF ENDP PROC king:(c%) LOCAL x% x%=rem:(m,8) IF x%=0 :x%=8 :ENDIF IF ((c=m-9 OR c=m-1 OR c=m+7) AND x%>1) OR ((c=m-7 OR c=m+1 OR c=m+9) AND x%<8) OR c=m-8 OR c=m+8 IF m=4 AND c% AND (cs%(1) OR cs%(2)) :cs%(1)=0 :cs%(2)=0 :ENDIF IF m=60 AND c% AND (cs%(3) OR cs%(4)) :cs%(3)=0 :cs%(4)=0 :ENDIF RETURN 1 ELSEIF m=4 AND c=2 AND cs%(1) AND p%(2)=0 AND p%(3)=0 IF c% :p%(3)=p%(1) :p%(1)=0 :cs%(1)=0 :ENDIF RETURN 1 ELSEIF m=4 AND c=6 AND cs%(2) AND p%(5)=0 AND p%(6)=0 AND p%(7)=0 IF c% :p%(5)=p%(8) :p%(8)=0 :cs%(2)=0 :ENDIF RETURN 1 ELSEIF m=60 AND c=62 AND cs%(3) AND p%(61)=0 AND p%(62)=0 AND p%(63)=0 IF c% :p%(61)=p%(64) :p%(64)=0 :cs%(3)=0 :ENDIF RETURN 1 ELSEIF m=60 AND c=58 AND cs%(4) AND p%(58)=0 AND p%(59)=0 IF c% :p%(59)=p%(57) :p%(57)=0 :cs%(4)=0 :ENDIF RETURN 1 ENDIF ENDP PROC hilite:(c) LOCAL s%,x%,y% y%=c/8 x%=c-y%*8-1 IF x%=-1 :x%=7 :y%=y%-1 :ENDIF IF r%=1 s%=x% x%=7-y% y%=s% ELSEIF r%=2 x%=7-x% y%=7-y% ELSEIF r%=3 s%=x% x%=y% y%=7-s% ENDIF gGMODE 2 gAT w%+20*x%+1,20*y%+1 gBOX 18,18 gAT w%+20*x%+2,20*y%+2 gBOX 16,16 ENDP PROC menu: LOCAL k% mINIT mCARD "Chess board","Players",%p,"Possible moves",%m,"New game",-%n,"Exit",%x LOCK ON k%=MENU LOCK OFF IF k%=%x exit: z%=0 ELSEIF k%=%p players: ELSEIF k%=%n new2: ELSEIF k%=%m IF sm%=0 :moves: :ENDIF sm%=1 z%=0 ELSE z%=0 ENDIF ENDP PROC new: dINIT "New game" dBUTTONS "No",%N,"Yes",%Y LOCK ON IF DIALOG<>%y :STOP :ENDIF LOCK OFF ENDP PROC new2: dINIT "New game" dBUTTONS "No",%N,"Yes",%Y LOCK ON IF DIALOG=%y :q%=1 :ENDIF LOCK OFF ENDP PROC exit: dINIT "Confirm exit" dBUTTONS "Cancel",27,"Exit",13 LOCK ON IF DIALOG=13 :STOP :ENDIF LOCK OFF ENDP PROC moves: LOCAL a,ok% IF g%<3 :m=c :ENDIF IF p%(m)=0 :RETURN 0 :ENDIF BUSY "Busy" a=c c=1 gGREY 1 DO IF (p%(c)=0) OR ((g%=3 OR p%(m)<10) AND p%(c)>9) OR ((g%=4 OR p%(m)>9) AND p%(c)<10) IF p%(m)=1 :ok%=pawnw:(0) ELSEIF p%(m)=11 :ok%=pawnb:(0) ELSEIF p%(m)=2 OR p%(m)=12 :ok%=rook:(0) ELSEIF p%(m)=3 OR p%(m)=13 :ok%=knight: ELSEIF p%(m)=4 OR p%(m)=14 :ok%=bishop: ELSEIF p%(m)=5 OR p%(m)=15 :ok%=queen: ELSEIF p%(m)=6 OR p%(m)=16 :ok%=king:(0) ENDIF IF ok% :hilite:(c) :ENDIF ENDIF c=c+1 UNTIL c>64 gGREY 0 c=a BUSY OFF ENDP PROC check:(t%) LOCAL a,b,ok% BUSY "Busy" a=c :b=m c=0 DO :c=c+1 :UNTIL (t%=1 AND p%(c)=6) OR (t%=2 AND p%(c)=16) m=1 DO IF (t%=1 AND p%(m)>9) OR (t%=2 AND p%(m)<10) IF p%(m)=1 :ok%=pawnw:(0) ELSEIF p%(m)=11 :ok%=pawnb:(0) ELSEIF p%(m)=2 OR p%(m)=12 :ok%=rook:(0) ELSEIF p%(m)=3 OR p%(m)=13 :ok%=knight: ELSEIF p%(m)=4 OR p%(m)=14 :ok%=bishop: ELSEIF p%(m)=5 OR p%(m)=15 :ok%=queen: ELSEIF p%(m)=6 OR p%(m)=16 :ok%=king:(0) ENDIF IF ok% gGREY 0 c=a m=b BUSY OFF RETURN 1 ENDIF ENDIF m=m+1 UNTIL m>64 gGREY 0 c=a m=b BUSY OFF ENDP PROC help: dINIT "Help: Chess board" dTEXT "","Use the arrows and Enter/Space to choose a piece and again" dTEXT "","to move it. Press M to see all the possible moves for the" dTEXT "","current/selected piece. Use <> to rotate the board. Use" dTEXT "","'Players' to edit player names. Use 'New game' to start again." dTEXT "","Castling is implemented (move the king). En-passant is not" dTEXT "","implemented. Check is detected but checkmate is not detected." LOCK ON DIALOG LOCK OFF ENDP PROC u: IF f% :hilite:(c) :ENDIF :c=c-8 :f%=0 ENDP PROC d: IF f% :hilite:(c) :ENDIF :c=c+8 :f%=0 ENDP PROC r: IF f% :hilite:(c) :ENDIF :c=c+1 :f%=0 ENDP PROC l: IF f% :hilite:(c) :ENDIF :c=c-1 :f%=0 ENDP PROC rem:(a,b%) LOCAL c% c%=a/b% RETURN a-c%*b% ENDP