www.jupiter-ace.co.uk
|
| Previous Page > Listings Index > SokoACE listing |
|
![]() |
SokoAce
by
Ricardo Fernandes Lopes
|
( SokoACE )
( Sokoban game for the Jupiter ACE )
( (c) 2006 by Ricardo Fernandes Lopes )
( under the GNU General Public License )
( Load and play the game with: )
( LOAD SOKOACE PLAY )
( Graphic characters )
CREATE T 56 ALLOT
: GR 8 * T + DUP 8 + SWAP DO I C! LOOP ;
: SETGR 56 0 DO T I + C@ 10240 I + C! LOOP ;
16 BASE C!
00 00 00 00 00 00 00 00 00 GR ( Not used )
00 00 00 18 18 00 00 00 01 GR ( Target )
3C 42 81 FF 99 99 7E 3C 02 GR ( Soko )
3C 42 BD FF BD 99 7E 3C 03 GR ( Soko + Target )
00 7E 42 42 42 42 7E 00 04 GR ( Box )
00 7E 42 5A 5A 42 7E 00 05 GR ( Box + Target )
FF AB D5 AB D5 AB D5 FF 06 GR ( Wall )
DECIMAL
( Screen elements)
01 CONSTANT TARGET ( 00 0001b )
02 CONSTANT SOKO ( 00 0010b )
04 CONSTANT BOX ( 00 0100b )
06 CONSTANT WALL ( 00 0110b )
32 CONSTANT BL ( 10 0000b )
: KEY ( -- c ,wait for keypress)
BEGIN INKEY 0= UNTIL
BEGIN INKEY ?DUP UNTIL ;
: >UPPER ( c1 -- c2 ,convert to uppercase)
DUP 96 > IF 223 AND THEN ;
: IN? ( -- n , get number from user)
QUERY NUMBER DUP
IF 4181 = ( avoid float numbers)
IF DROP 0 THEN
THEN ;
: +! ( n adr -- ) SWAP OVER @ + SWAP ! ;
: INC ( a -- ) 1 SWAP +! ;
: DEC ( a -- ) -1 SWAP +! ;
0 VARIABLE SOKO> ( holds SOKO screen address )
0 VARIABLE #BOX ( number of boxes out of target )
0 VARIABLE #STEP ( number of steps )
0 VARIABLE #PUSH ( number of pushes )
( Movement directions)
-32 CONSTANT UP
32 CONSTANT DOWN
-1 CONSTANT LEFT
1 CONSTANT RIGHT
: STEP ( a1 -- , move SOKO one step)
DUP C@ TARGET AND SOKO OR OVER C! ( place SOKO in new position )
SOKO> @ ( previous SOKO position )
DUP C@ TARGET AND ( check previous contents )
IF TARGET ELSE BL THEN ( Target or Blank )
SWAP C! ( remove SOKO from old position )
SOKO> !
#STEP INC ;
: PUSH ( a1 a2 -- , push a BOX)
OVER C@ TARGET AND IF #BOX INC THEN ( Box entered a target region)
DUP C@ DUP TARGET AND IF #BOX DEC THEN ( Box exited a target area)
TARGET AND BOX OR SWAP C! ( Move Box)
STEP ( Move Soko)
#STEP DEC ( Inc Pushes but not Steps)
#PUSH INC ;
: GO ( dir -- , try to move Soko in the specified direction)
SOKO> @ OVER + ( next position )
DUP C@ WALL =
IF DROP DROP ( if WALL, do nothing )
ELSE
DUP C@ DUP BL = SWAP TARGET = OR
IF STEP DROP ( if Blank or Target, do Step)
ELSE
SWAP OVER + ( over next position )
DUP C@ DUP BL = SWAP TARGET = OR
IF PUSH ( if Blank or Target, do Push )
ELSE DROP DROP ( else, do nothing )
THEN
THEN
THEN ;
: WALK ( c -- c, interpret key and move Soko )
DUP ASCII I = IF UP GO ELSE
DUP ASCII K = IF DOWN GO ELSE
DUP ASCII J = IF LEFT GO ELSE
DUP ASCII L = IF RIGHT GO
THEN THEN THEN THEN ;
: .#### ( a -- , formatted score type)
@ 0 <# # # # # #> TYPE ;
: .SCORE ( update score )
3 28 AT #BOX @ .
5 28 AT #STEP .####
7 28 AT #PUSH .#### ;
: .FRAME ( Draw screen )
CLS ." ______SokoACE_______ version 1.0"
3 22 AT ." BOXES ?"
5 22 AT ." STEPS"
7 21 AT ." PUSHES"
10 21 AT ." I Up"
11 21 AT ." K Down"
12 21 AT ." J Left"
13 21 AT ." L Right"
15 21 AT ." N Level + 1"
16 21 AT ." P Level - 1"
17 21 AT ." M Level ?"
18 21 AT ." R Restart"
20 21 AT ." Q Quit"
22 0 AT ." _by Ricardo F Lopes_ c 2006" ;
: SCAN ( Scan screen map for Soko position and count boxes out of target)
0 #BOX ! ( reset number of boxes)
9920 9280
DO
I C@
DUP SOKO = IF I SOKO> ! ELSE ( Search for SOKO start position)
DUP BOX = IF #BOX INC ( Count Boxes out of target)
THEN THEN DROP
LOOP ;
20 21 * CONSTANT MAPSIZE ( Map size = 20x20 chars + 20 chars for map label line )
CREATE MAPS MAPSIZE 30 * ALLOT ( Room for 30 maps )
: MAP ( level -- a , return a map address)
MAPSIZE * MAPS + ;
: MAP>SCR ( level -- , copy level map to screen)
MAP 22 1
DO
I 0 AT DUP 20 TYPE CR 20 +
LOOP DROP ;
0 VARIABLE LEVEL
: INIT ( level -- , Initialize Level)
0 #STEP ! ( reset steps count )
0 #PUSH ! ( reset pushes count )
.FRAME
0 MAX 29 MIN DUP LEVEL !
MAP>SCR
SCAN ;
: MAP? ( c -- c , Change level)
DUP ASCII N = IF LEVEL @ 1+ INIT ELSE ( Next level)
DUP ASCII P = IF LEVEL @ 1- INIT ELSE ( Previous level)
DUP ASCII M = IF IN? INIT ELSE ( Entered level number)
DUP ASCII R = IF LEVEL @ INIT ( Re-start same level)
THEN THEN THEN THEN ;
: PLAY ( Main code, run this to play SokoACE)
SETGR ( initialize graphics )
0 INIT ( start the first level )
BEGIN
.SCORE ( Update Score)
KEY >UPPER ( Get key pressed )
WALK ( Move SOKO )
MAP? ( Check for level request)
1 9 AT
#BOX @ 0= ( No boxes left?)
IF
." Done !" 100 50 BEEP 75 25 BEEP ( Level completed !)
THEN
ASCII Q = ( Quit?)
UNTIL
." Quit." ;
( Before saving this program, populate the )
( level slots with maps created with SokoED.)
( To do that, use: )
( 0 MAP 0 BLOAD MAP1 )
( 1 MAP 0 BLOAD MAP2 )
( 2 MAP 0 BLOAD MAP3 )
( etc..)
( Where 0, 1, 2,.. 29 are the available level numbers)
( and MAP1, MAP2, etc. are map files created with SokoED)
|
|