00010 REM CLASSIC SOKOBAN MULTI-LEVEL ENGINE FOR MICROBEE 00020 CLEAR 2000:CLS:PRINT "--- CLASSIC SOKOBAN ---":PRINT 00030 DIM M$(20):REM MAX 20 ROWS PER MAP 00040 L=1:REM START AT LEVEL 1 00050 GOSUB 00500:REM LOAD SELECTED LEVEL L 00060 GOSUB 00600:REM RENDER MAP AND STATS 00070 REM MAIN GAME LOOP 00080 K$=INKEY$:IF K$="" THEN 00080 00090 DX=0:DY=0 00100 IF K$="W" OR K$="w" THEN DY=-1 00110 IF K$="S" OR K$="s" THEN DY=1 00120 IF K$="A" OR K$="a" THEN DX=-1 00130 IF K$="D" OR K$="d" THEN DX=1 00140 IF K$="R" OR K$="r" THEN GOTO 00050:REM RESTART LEVEL 00150 IF DX=0 AND DY=0 THEN 00080 00160 REM CHECK DESTINATION CELLS 00170 NX=PX+DX:NY=PY+DY:REM NEXT CELL 00180 NNX=PX+2*DX:NNY=PY+2*DY:REM CELL BEYOND 00190 IF NY<1 OR NY>H OR NX<1 OR NX>LEN(M$(NY)) THEN 00080 00200 C1$=MID$(M$(NY),NX,1) 00210 IF NNY>=1 AND NNY<=H AND NNX>=1 AND NNX<=LEN(M$(NNY)) THEN C2$=MID$(M$(NNY),NNX,1) ELSE C2$="#" 00220 IF C1$="#" THEN 00080:REM WALL COLLISION 00230 REM PUSHING A BOX 00240 IF C1$<>"$" AND C1$<>"*" THEN GOTO 00320 00250 IF C2$="#" OR C2$="$" OR C2$="*" THEN 00080 00260 REM MOVE BOX TO BEYOND CELL 00270 IF C2$="." THEN NC2$="*" ELSE NC2$="$" 00280 GOSUB 00800:REM UPDATE CELL NNX,NNY WITH NC2$ 00290 IF C1$="*" THEN NC1$="." ELSE NC1$=" " 00300 GOSUB 00700:REM UPDATE CELL NX,NY WITH NC1$ 00320 REM MOVE PLAYER TO NEXT CELL 00330 C1$=MID$(M$(NY),NX,1) 00340 IF C1$="." THEN NC1$="+" ELSE NC1$="@" 00350 GOSUB 00700:REM UPDATE CELL NX,NY WITH NC1$ 00360 CP$=MID$(M$(PY),PX,1) 00370 IF CP$="+" THEN NCP$="." ELSE NCP$=" " 00380 GOSUB 00900:REM UPDATE CELL PX,PY WITH NCP$ 00390 PX=NX:PY=NY:GOSUB 00600:REM REDRAW 00400 GOSUB 00440:IF W=1 THEN PRINT "LEVEL ";L;" CLEARED!":FOR T=1 TO 2000:NEXT T:L=L+1:GOTO 00050 00410 GOTO 00080 00440 REM WIN CONDITION CHECK 00450 W=1:FOR I=1 TO H:FOR J=1 TO LEN(M$(I)) 00460 IF MID$(M$(I),J,1)="$" THEN W=0 00470 NEXT J:NEXT I:RETURN 00500 REM PARSE LEVEL FROM DATA STATEMENTS 00510 RESTORE:FOR I=1 TO L:READ H:FOR J=1 TO H:READ M$(J):NEXT J:NEXT I 00520 REM LOCATE PLAYER POSITION 00530 FOR I=1 TO H:FOR J=1 TO LEN(M$(I)):C$=MID$(M$(I),J,1) 00540 IF C$="@" OR C$="+" THEN PX=J:PY=I 00550 NEXT J:NEXT I:RETURN 00600 REM SCREEN RENDER 00610 CLS:PRINT "--- CLASSIC SOKOBAN - LEVEL ";L;" ---":PRINT 00620 FOR I=1 TO H:PRINT M$(I):NEXT I 00630 PRINT:PRINT "WASD = MOVE | R = RESTART LEVEL" 00640 RETURN 00700 REM HELPER: UPDATE NX,NY WITH NC1$ 00710 M$(NY)=LEFT$(M$(NY),NX-1)+NC1$+MID$(M$(NY),NX+1):RETURN 00800 REM HELPER: UPDATE NNX,NNY WITH NC2$ 00810 M$(NNY)=LEFT$(M$(NNY),NNX-1)+NC2$+MID$(M$(NNY),NNX+1):RETURN 00900 REM HELPER: UPDATE PX,PY WITH NCP$ 00910 M$(PY)=LEFT$(M$(PY),PX-1)+NCP$+MID$(M$(PY),PX+1):RETURN 01000 REM --- LEVEL DATA PACK --- 01010 REM LEVEL 1 (CLASSIC #1) 01020 DATA 9 01030 DATA " #####" 01040 DATA " # #" 01050 DATA " #$ #" 01060 DATA "### $##" 01070 DATA "# $ $ #" 01080 DATA "### # ## # ######" 01090 DATA " # # ## ##### ..#" 01100 DATA " # @ $ ..#" 01110 DATA " ##### ### #@## ..#" 01120 REM LEVEL 2 (CLASSIC #2) 01130 DATA 10 01140 DATA "############" 01150 DATA "#.. # #" 01160 DATA "#.. # $ #" 01170 DATA "#.. #$ $ #" 01180 DATA "#.. $ #" 01190 DATA "#.. # #" 01200 DATA "###### #####" 01210 DATA " # $ $ #" 01220 DATA " # $ @ #" 01230 DATA " ########" 01240 REM LEVEL 3 (CLASSIC #3) 01250 DATA 8 01260 DATA " #######" 01270 DATA " # #" 01280 DATA " # $ $ #" 01290 DATA "### $ $ ###" 01300 DATA "# $@$ #" 01310 DATA "# .. .. #" 01320 DATA "# .. $ .. #" 01330 DATA "###########" 01340 REM LEVEL 4 (CLASSIC #4 VARIANT) 01350 DATA 11 01360 DATA " ####" 01370 DATA "### ####" 01380 DATA "# $ $ #" 01390 DATA "# # #" 01400 DATA "# #@# $ #" 01410 DATA "# # . #" 01420 DATA "# ...###" 01430 DATA "#### #" 01440 DATA " ####" 01450 DATA " # #" 01460 DATA " ####" 01470 REM LEVEL 5 (THE TIGHT CORRIDORS) 01480 DATA 9 01490 DATA "#####" 01500 DATA "#@ ####" 01510 DATA "# $ $ #" 01520 DATA "# # $ #" 01530 DATA "## # #" 01540 DATA "#.. .. #" 01550 DATA "#..# #" 01560 DATA "########" 01570 REM LEVEL 6 (THE SPLIT ROOM) 01580 DATA 10 01590 DATA " ######" 01600 DATA "### ###" 01610 DATA "# $$# #" 01620 DATA "# @ $ #" 01630 DATA "### #####" 01640 DATA " # #" 01650 DATA " #..#" 01660 DATA " #..#" 01670 DATA " #..#" 01680 DATA " ####"