Ace Mines
by Ricardo Lopes
|
Ace Mines by Ricardo Fernandes Lopes.
(c) 2004 GNU General Public License.
The object of Ace Mines is to find all the mines possible without uncovering any of them. If you find a mine, its all over! you lose. Keys I .. Move left P .. Move right A .. Move up Z .. Move down F .. to flag or mark a mine. O .. to open or uncover the cell. To Start a new game select, B .. for Beginner I .. for Intermediate E .. for Expert Move your cursor around the cells with keys I,P,A, and Z. To uncover or open a cell press O, if you find a bomb its Game over! If a number appears in the cell, it indicates how many mines are in the eight cells that surround the numbered one. To mark a cell you suspect contains a mine, press f to flag it. The listing below has a number of comments in it, give you a clear guide of what each AceForth word does. |
( ACE Mines listing ) CREATE TABLE 128 ALLOT ( Graphics ) : GR 8 * TABLE + DUP 8 + SWAP DO I C! LOOP ; 16 BASE C! 00 00 00 00 00 00 00 00 00 GR 00 1C 08 08 08 08 18 00 01 GR 00 7E 40 7E 02 02 7E 00 02 GR 00 7E 02 02 3E 02 7E 00 03 GR 00 04 04 7E 44 44 40 00 04 GR 00 7E 02 02 7E 40 7E 00 05 GR 00 7E 42 7E 40 40 7E 00 06 GR 00 02 02 02 02 02 7E 00 07 GR 00 7E 42 42 7E 24 3C 00 08 GR 00 02 02 02 7E 42 7E 00 09 GR 00 3c 7e 7e 7e 3c 08 06 0A GR ( BOMB ) 81 7E 5E 5E 42 42 7E 81 0B GR ( FLAG ) 00 7E 7E 7E 7E 7E 7E 00 0C GR ( TILE ) FF 81 81 81 81 81 81 FF 0D GR ( not used) 7E FF BD C3 FF 99 DB 7E 0E GR ( SAD ) 7E C3 81 FF 99 00 99 7E 0F GR ( SMILE ) DECIMAL : SETGR 128 0 DO TABLE I + C@ 10240 I + C! LOOP ; : 2DUP OVER OVER ; ( x1 x2 -- x1 x2 x1 x2 ) : 2DROP DROP DROP ; ( x1 x2 -- ) : BLIP 100 50 BEEP 50 25 BEEP ; : KEY ( -- c , wait for a keypress ) BEGIN INKEY 0= UNTIL BEGIN INKEY ?DUP UNTIL 223 AND ; ( random number generator) 0 VARIABLE RND : RANDOMIZE 15403 @ RND ! ; : RANDOM ( n1 -- n2 , generate a random number from 0 to n1-1) RND @ 31421 * 6927 + DUP RND ! U* SWAP DROP ; : MENU ( -- n , Print menu and wait user option ) CLS ." 2004 ACE MINES v1.0" 5 3 AT ." Choose: Beginner" 7 12 AT ." Intermediate" 9 12 AT ." Expert" 11 12 AT ." Quit" 19 0 AT ." 2004 (c) Ricardo Fernandes Lopes" CR ." - GNU General Public License -" KEY BLIP ; 8 VARIABLE XMAX 8 VARIABLE YMAX 10 VARIABLE BOMBS : LEVEL! BOMBS ! YMAX ! XMAX ! ; ( bombs height width -- ) : BEGINNER 8 8 10 ; : INTERMED 16 16 40 ; : EXPERT 30 16 99 ; : SETLEVEL DUP [ ASCII I ] LITERAL = IF INTERMED ELSE DUP [ ASCII E ] LITERAL = IF EXPERT ELSE BEGINNER THEN THEN LEVEL! DROP ; 10 CONSTANT BOMB 11 CONSTANT FLAG 12 CONSTANT TILE 0 VARIABLE X 0 VARIABLE Y 9216 CONSTANT SCREEN CREATE BOARD 30 16 * ALLOT : XY@ X @ Y @ ; ( -- x y , get cursor coord) : XY>BOARD XMAX @ * + BOARD + ; ( x y -- adr , convert coord to board address) : BOARD> XY@ XY>BOARD ; ( -- adr , get current board address) : XY>SCREEN 1+ 32 * 1+ + SCREEN + ; ( x y -- adr , convert coord to screen address) : SCREEN> XY@ XY>SCREEN ; ( -- adr , get current screen address) : CLRBOARD ( Clear Board) BOARD XMAX @ YMAX @ * + BOARD DO 0 I C! LOOP ; : XY-OK? ( x y -- x y f , check for valid coord) 2DUP OVER XMAX @ < OVER YMAX @ < AND SWAP 0< 0= AND SWAP 0< 0= AND ; ( Toogle screen cursor inverse/normal) : .CURSOR SCREEN> DUP C@ 128 XOR SWAP C! ; ( Move coord) : UP ( x y -- x y-1) 1- ; : DOWN ( x y -- x y+1) 1+ ; : LEFT ( x y -- x-1 y) SWAP 1- SWAP ; : RIGHT ( x y -- x+1 y) SWAP 1+ SWAP ; : SHOW ( x y -- c , show coord contents) 2DUP XY>SCREEN ROT ROT XY>BOARD C@ DUP ROT C! ; ( Tracking winning condition) 0 VARIABLE CLOSED : CLOSEALL XMAX @ YMAX @ * BOMBS @ - CLOSED ! ; ( Initialize count of closed tiles) : WIN? CLOSED @ 0= ; ( -- f , Check winning condition) : .WIN ( Win/Loose icon/tune) 0 XMAX @ 2 / AT WIN? IF 201 100 BEEP 100 150 BEEP 50 200 BEEP 15 ELSE 50 100 BEEP 100 150 BEEP 201 200 BEEP 14 THEN EMIT ; : OPENALL ( Open all tiles) YMAX @ 0 DO XMAX @ 0 DO I J XY>BOARD C@ I J XY>SCREEN C! LOOP LOOP ; : OPENXY ( x y -- x y , open tile at coord) XY-OK? IF 2DUP XY>SCREEN C@ DUP TILE = SWAP FLAG = OR IF CLOSED @ 1- CLOSED ! 2DUP SHOW 0= IF UP OPENXY RIGHT OPENXY DOWN OPENXY DOWN OPENXY LEFT OPENXY LEFT OPENXY UP OPENXY UP OPENXY RIGHT DOWN THEN THEN THEN ; : OPEN ( -- f , open tile and return true if BOMB ) BLIP XY@ OPENXY XY>BOARD C@ BOMB = ; : FLAGIT ( Mark/Unmark tile with a flag) SCREEN> C@ DUP TILE = IF FLAG SCREEN> C! THEN FLAG = IF TILE SCREEN> C! THEN ; : INC ( x y -- x y , Increment value of cell at coord) XY-OK? IF 2DUP XY>BOARD DUP C@ BOMB = IF DROP ELSE DUP C@ 1+ SWAP C! THEN THEN ; : BOMB! ( x y -- , Place Bomb at coord and increment neighbor) 2DUP XY>BOARD BOMB SWAP C! UP INC RIGHT INC DOWN INC DOWN INC LEFT INC LEFT INC UP INC UP INC 2DROP ; : BOMB? ( x y -- x y f , check if Bomb at coord) 2DUP XY>BOARD C@ BOMB = ; : SEED ( place Bombs at mine field) CLRBOARD BOMBS @ 0 DO 46 EMIT BEGIN XMAX @ RANDOM YMAX @ RANDOM BOMB? WHILE 2DROP REPEAT BOMB! LOOP ; ( Draw board ) : HBAR XMAX @ 2+ 0 DO 160 EMIT LOOP ; : DRAW CLS HBAR YMAX @ 1+ DUP 1 DO I 0 AT 160 EMIT XMAX @ 0 DO TILE EMIT LOOP 160 EMIT LOOP 0 AT HBAR 19 0 AT ." A move up Z move down" CR ." I move left P move right" CR ." F place flag O open" CR ." Q quit" ; : INIT 0 X ! 0 Y ! SEED CLOSEALL DRAW ; : XY! ( x y -- ) XY-OK? IF Y ! X ! ELSE 2DROP THEN ; : ACTION ( c -- f , execute key command, return true if end) DUP [ ASCII Q ] LITERAL = DUP 0= IF OVER [ ASCII I ] LITERAL = IF XY@ LEFT XY! THEN OVER [ ASCII P ] LITERAL = IF XY@ RIGHT XY! THEN OVER [ ASCII A ] LITERAL = IF XY@ UP XY! THEN OVER [ ASCII Z ] LITERAL = IF XY@ DOWN XY! THEN OVER [ ASCII F ] LITERAL = IF FLAGIT THEN OVER [ ASCII O ] LITERAL = IF OPEN OR WIN? OR THEN THEN SWAP DROP ; : GAME ( n -- , Play game at given level) CLS ." Wait" SETLEVEL INIT BEGIN .CURSOR KEY .CURSOR ACTION UNTIL .WIN OPENALL .CURSOR KEY DROP ; ( Main code, run it to play ACE Mines) : MINES SETGR RANDOMIZE BEGIN MENU DUP [ ASCII Q ] LITERAL = 0= WHILE GAME REPEAT DROP CLS ." Bye." ; |