Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pascalated ZX BASIC Demo #19 - Klotski
#1
To run online, click here: RUN ONLINE


Code:
' PROGRAM Klotski
' (c) ZarSoft 2022 Pascalated BASIC
' (c) ZarSoft 2023 Pascalated Boriel ZX BASIC
' Written by Ze Oliveira
' Pascalated Sinclair BASIC (c) 1987 by ZarSoft
' Pascalated BASIC Converter (c) 2021 by Zarsoft
' Pascalated Boriel (c) 2023 by ZarSoft
' ZX BASIC Compiler (c) 2008 by Boriel

#include <input.bas>  ' number = VAL INPUT(12)
#include <screen.bas> ' SCREEN$ function
#include <attr.bas>   ' ATTR function

'--- Pascalated Boriel ---
#define PROGRAM   REM
#define BEGIN    REM
'#define CONST     CONST
#define VAR       DIM
#define INTEGER   LONG
#define REAL      FLOAT
#define CHAR      STRING
'#define STRING    STRING
#define BOOLEAN   UBYTE
#define TYPE      AS
'#define WHILE    WHILE
#define REPEAT    DO
#define UNTIL     LOOP UNTIL
#define PROCEDURE  SUB
CONST   TRUE      TYPE BOOLEAN = 1
CONST   FALSE     TYPE BOOLEAN = 0

PROGRAM Klotski

' CONSTant declarations
REM CONSTant declarations
CONST black = 0
CONST blue = 1
CONST red = 2
CONST magenta = 3
CONST green = 4
CONST cyan = 5
CONST yellow = 6
CONST white = 7
CONST ScreenLin =6
CONST ScreenCol =8
CONST dl =3: REM 4
CONST dc =3: REM 8
CONST MaxM = 199
CONST MinM = 83

' VAR - Global variables
VAR Board$(4) TYPE STRING ' board
VAR Coord(9,2,2) TYPE INTEGER ' coordinates of objects
VAR Sprite$(9,6) TYPE STRING ' photo of objects
VAR PositionLin,PositionCol TYPE INTEGER
VAR Nmove TYPE INTEGER
VAR grabbed TYPE BOOLEAN
VAR abort TYPE BOOLEAN

PROCEDURE TRON (m TYPE STRING)
  PRINT AT 23,0;m;
  PAUSE 0
END PROCEDURE

PROCEDURE TraceBoard
PRINT AT 11,0;Board$(1);AT 12,0;Board$(2);AT 13,0;Board$(3);AT 14,0;;Board$(4)
END PROCEDURE

PROCEDURE finalization
PRINT AT 2,0;"###**=- CONGRATULATIONS! -=**###"
: FOR i=-11 TO 11: BEEP .01,i: BEEP .01,ABS(i): NEXT i
PRINT AT 23,0;INK magenta;" ";TAB 9;"Press any key";TAB 32;
PAUSE 0:
BEEP .1,5
END PROCEDURE

FUNCTION GetObjectAtCursor TYPE INTEGER
VAR ob TYPE INTEGER
LET ob = VAL Board$(PositionLin)(PositionCol)
RETURN ob
END FUNCTION

PROCEDURE EraseObject (ob TYPE INTEGER)
VAR PosLin, PosCol TYPE INTEGER
LET PosLin = ScreenLin+(Coord(ob,1,1)-1)*dl
LET PosCol = ScreenCol+(Coord(ob,1,2)-1)*dc
FOR l = 1 TO 6
  PRINT AT PosLin+l,PosCol;OVER 1;Sprite$(ob,l);
NEXT l
END PROCEDURE

PROCEDURE EraseObjectAtCursor
VAR ob TYPE INTEGER
LET ob = GetObjectAtCursor
EraseObject(ob)
END PROCEDURE

PROCEDURE PrintObject (ob TYPE INTEGER)
VAR PosLin, PosCol TYPE INTEGER
LET PosLin = ScreenLin+(Coord(ob,1,1)-1)*dl
LET PosCol = ScreenCol+(Coord(ob,1,2)-1)*dc
FOR l = 1 TO 6
  PRINT AT PosLin+l,PosCol;OVER 1;Sprite$(ob,l);
NEXT l
END PROCEDURE

PROCEDURE MoveObject (key$ TYPE STRING)
VAR ob TYPE INTEGER
ob = GetObjectAtCursor
EraseObjectAtCursor
FOR l = Coord(ob,1,1) TO Coord(ob,2,1)
  FOR c = Coord(ob,1,2) TO Coord(ob,2,2)
    LET Board$(l)(c) = "0"
  NEXT c
NEXT l
IF key$ ="Q"
  LET Coord(ob,1,1) = Coord(ob,1,1)-1: LET Coord(ob,2,1) = Coord(ob,2,1)-1:
  LET PositionLin = PositionLin-1:
ELSEIF key$="A"
  LET Coord(ob,1,1) = Coord(ob,1,1)+1: LET Coord(ob,2,1) = Coord(ob,2,1)+1:
  LET PositionLin = PositionLin+1:
ELSEIF key$="O"
  LET Coord(ob,1,2) = Coord(ob,1,2)-1: LET Coord(ob,2,2) = Coord(ob,2,2)-1:
  LET PositionCol = PositionCol-1:
ELSEIF key$="P"
  LET Coord(ob,1,2) = Coord(ob,1,2)+1: LET Coord(ob,2,2) = Coord(ob,2,2)+1:
  LET PositionCol = PositionCol+1:
ENDIF
FOR l = Coord(ob,1,1) TO Coord(ob,2,1)
  FOR c = Coord(ob,1,2) TO Coord(ob,2,2)
    LET Board$(l)(c) = STR$ ob
  NEXT c
NEXT l
PrintObject(ob)
LET Nmove = Nmove+1:
PRINT AT 2,0;"Current: ";Nmove
END PROCEDURE

FUNCTION CheckLegalUp TYPE BOOLEAN
VAR l,c TYPE INTEGER
VAR ok TYPE BOOLEAN
VAR ob TYPE INTEGER
ob = GetObjectAtCursor
LET l = Coord(ob,1,1)-1
IF l > 0
  LET ok = TRUE
ELSE
  LET ok = FALSE
ENDIF
LET c = Coord(ob,1,2):
WHILE (c <= Coord(ob,2,2)) AND ok
  IF Board$(l)(c) <> "0" THEN LET ok = FALSE
  LET c = c+1
END WHILE
RETURN ok
END FUNCTION

FUNCTION CheckLegalDown TYPE BOOLEAN
VAR l,c TYPE INTEGER
VAR ok TYPE BOOLEAN
VAR ob TYPE INTEGER
ob = GetObjectAtCursor
LET l = Coord(ob,2,1)+1:
IF l < 5
  LET ok = TRUE
ELSE
  LET ok = FALSE
ENDIF
LET c = Coord(ob,1,2):
WHILE (c <= Coord(ob,2,2)) AND ok
  IF Board$(l)(c) <> "0" THEN LET ok = FALSE
  LET c = c+1
END WHILE
RETURN ok
END FUNCTION

FUNCTION CheckLegalLeft TYPE BOOLEAN
VAR l,c TYPE INTEGER
VAR ok TYPE BOOLEAN
VAR ob TYPE INTEGER
ob = GetObjectAtCursor
LET c = Coord(ob,1,2)-1:
IF c > 0
  LET ok = TRUE
ELSE
  LET ok = FALSE
ENDIF
LET l = Coord(ob,1,1):
WHILE (l <= Coord(ob,2,1)) AND ok
  IF Board$(l)(c) <> "0" THEN LET ok = FALSE
  LET l = l+1
END WHILE
RETURN ok
END FUNCTION

FUNCTION CheckLegalRight TYPE BOOLEAN
VAR l,c TYPE INTEGER
VAR ok TYPE BOOLEAN
VAR ob TYPE INTEGER
ob = GetObjectAtCursor
LET c = Coord(ob,2,2)+1:
IF c < 6
  LET ok = TRUE
ELSE
  LET ok = FALSE:
ENDIF
LET l = Coord(ob,1,1):
WHILE (l <= Coord(ob,2,1)) AND ok
  IF Board$(l)(c) <> "0" THEN LET ok = FALSE
  LET l = l+1
END WHILE
RETURN ok
END FUNCTION

FUNCTION CheckLegalMove (key$ TYPE STRING) TYPE BOOLEAN
VAR legal TYPE BOOLEAN
VAR ob TYPE INTEGER
LET legal = FALSE
ob = GetObjectAtCursor
IF key$ = " " OR key$="M"
  IF ob > 0
    REM IF grabbed THEN EraseObjectAtCursor
    LET grabbed = NOT(grabbed):
    REM GetObjectAtCursor: PrintObject: REM (ObjectAtCursor)
  ENDIF
ELSEIF key$>="A" AND key$<="Z"
  IF grabbed
    IF ob > 0
      IF key$="Q" THEN legal = CheckLegalUp
      IF key$="A" THEN legal = CheckLegalDown
      IF key$="O" THEN legal = CheckLegalLeft
      IF key$="P" THEN legal = CheckLegalRight
    ENDIF
  ELSE
    IF key$="Q" THEN IF PositionLin > 1 THEN LET PositionLin = PositionLin-1:
    IF key$="A" THEN IF PositionLin < 4 THEN LET PositionLin = PositionLin+1:
    IF key$="O" THEN IF PositionCol > 1 THEN LET PositionCol = PositionCol-1:
    IF key$="P" THEN IF PositionCol < 5 THEN LET PositionCol = PositionCol+1:
  ENDIF
ELSE IF key$ = "0"
  LET abort = TRUE
ENDIF
RETURN legal
END FUNCTION

FUNCTION InputMove TYPE STRING
VAR key$ TYPE STRING
VAR ColorCursor TYPE INTEGER
LET ColorCursor = yellow
IF grabbed THEN LET ColorCursor = red
PRINT AT ScreenLin+(PositionLin-1)*dl+2,ScreenCol+(PositionCol-1)*dc+1;OVER 1;PAPER ColorCursor;INK ColorCursor;" ";
REPEAT
  PAUSE 0: LET key$ = INKEY$
  REM IF key$=CHR$(27) THEN LET t = "0":
  IF key$ > "Z" THEN LET key$ = CHR$(CODE(key$)+CODE("A")-CODE("a"))
UNTIL key$="0" OR key$=" " OR (key$>="A" AND key$<="Z")
BEEP .1,5
REM IF grabbed THEN PRINT "#" ELSE PRINT " "
PRINT AT ScreenLin+(PositionLin-1)*dl+2,ScreenCol+(PositionCol-1)*dc+1;OVER 1;" ";
RETURN key$
END FUNCTION

PROCEDURE initialization
LET abort = FALSE
LET Nmove = 0
LET grabbed = FALSE
LET PositionLin = 3: LET PositionCol = 3
REM board
LET Board$(0) = "......":
LET Board$(1) = ".98076":
LET Board$(2) = ".98076":
LET Board$(3) = ".11355":
LET Board$(4) = ".11244":
REM size of objects
LET Coord(1,1,1) = 3: LET Coord(1,1,2) = 1: LET Coord(1,2,1) = 4: LET Coord(1,2,2) = 2
LET Coord(2,1,1) = 4: LET Coord(2,1,2) = 3: LET Coord(2,2,1) = 4: LET Coord(2,2,2) = 3
LET Coord(3,1,1) = 3: LET Coord(3,1,2) = 3: LET Coord(3,2,1) = 3: LET Coord(3,2,2) = 3
LET Coord(4,1,1) = 4: LET Coord(4,1,2) = 4: LET Coord(4,2,1) = 4: LET Coord(4,2,2) = 5
LET Coord(5,1,1) = 3: LET Coord(5,1,2) = 4: LET Coord(5,2,1) = 3: LET Coord(5,2,2) = 5
LET Coord(6,1,1) = 1: LET Coord(6,1,2) = 5: LET Coord(6,2,1) = 2: LET Coord(6,2,2) = 5
LET Coord(7,1,1) = 1: LET Coord(7,1,2) = 4: LET Coord(7,2,1) = 2: LET Coord(7,2,2) = 4
LET Coord(8,1,1) = 1: LET Coord(8,1,2) = 2: LET Coord(8,2,1) = 2: LET Coord(8,2,2) = 2
LET Coord(9,1,1) = 1: LET Coord(9,1,2) = 1: LET Coord(9,2,1) = 2: LET Coord(9,2,2) = 1
REM photo of objects
REM 1
LET Sprite$(1,1) = "\ .\..\..\..\..\.."
LET Sprite$(1,2) = "\ :\::\::\::\::\::"
LET Sprite$(1,3) = "\ :\::\::\::\::\::"
LET Sprite$(1,4) = "\ :\::\::\::\::\::"
LET Sprite$(1,5) = "\ :\::\::\::\::\::"
LET Sprite$(1,6) = "\ :\::\::\::\::\::"
REM 2
LET Sprite$(2,1) = "\ .\..\.."
LET Sprite$(2,2) = "\ :\::\::"
LET Sprite$(2,3) = "\ :\::\::"
REM 3
LET Sprite$(3,1) = "\ .\..\.."
LET Sprite$(3,2) = "\ :\::\::"
LET Sprite$(3,3) = "\ :\::\::"
REM 4
LET Sprite$(4,1) = "\ .\..\..\..\..\.."
LET Sprite$(4,2) = "\ :\::\::\::\::\::"
LET Sprite$(4,3) = "\ :\::\::\::\::\::"
REM 5
LET Sprite$(5,1) = "\ .\..\..\..\..\.."
LET Sprite$(5,2) = "\ :\::\::\::\::\::"
LET Sprite$(5,3) = "\ :\::\::\::\::\::"
REM 6
LET Sprite$(6,1) = "\ .\..\.."
LET Sprite$(6,2) = "\ :\::\::"
LET Sprite$(6,3) = "\ :\::\::"
LET Sprite$(6,4) = "\ :\::\::"
LET Sprite$(6,5) = "\ :\::\::"
LET Sprite$(6,6) = "\ :\::\::"
REM 7
LET Sprite$(7,1) = "\ .\..\.."
LET Sprite$(7,2) = "\ :\::\::"
LET Sprite$(7,3) = "\ :\::\::"
LET Sprite$(7,4) = "\ :\::\::"
LET Sprite$(7,5) = "\ :\::\::"
LET Sprite$(7,6) = "\ :\::\::"
REM 8
LET Sprite$(8,1) = "\ .\..\.."
LET Sprite$(8,2) = "\ :\::\::"
LET Sprite$(8,3) = "\ :\::\::"
LET Sprite$(8,4) = "\ :\::\::"
LET Sprite$(8,5) = "\ :\::\::"
LET Sprite$(8,6) = "\ :\::\::"
REM 9
LET Sprite$(9,1) = "\ .\..\.."
LET Sprite$(9,2) = "\ :\::\::"
LET Sprite$(9,3) = "\ :\::\::"
LET Sprite$(9,4) = "\ :\::\::"
LET Sprite$(9,5) = "\ :\::\::"
LET Sprite$(9,6) = "\ :\::\::"
REM background
CLS
PRINT AT 0,12;INK 2;"KLOTSKI"
REM PRINT AT 2,0;"Current= ";Nmove
PRINT AT 2,20;"Minimum= ";MinM
PRINT AT 23,0;INK magenta;"QAOP-Move M,SPC-Select 0-Abort";
FOR ob = 1 TO 9 : PrintObject(ob): NEXT ob
END PROCEDURE

PROCEDURE introduction
BORDER 4: PAPER 4: INK 0: CLS
PRINT AT 5,12;INK 2;"KLOTSKI"
PRINT AT 10,0;"Move the big square","from bottom-left to bottom-right"
PRINT AT 23,0;INK magenta;" ";TAB 9;"Press any key";TAB 32;
PAUSE 0
BEEP .1,5
END PROCEDURE

PROCEDURE MainRoutine
VAR key$ TYPE STRING
VAR legal TYPE BOOLEAN
REPEAT
  introduction
  initialization
  REPEAT
    key$ = InputMove
    legal = CheckLegalMove(key$)
    IF legal THEN MoveObject(key$)
  UNTIL (Board$(4)(5)="1") OR abort
UNTIL (Board$(4)(5)="1")
IF Board$(4)(5)="1" THEN finalization
END PROCEDURE

PROGRAM Klotski
PRINT AT 23,0;"Pascalated Boriel ZX BASIC demo";
PAUSE 1*50
MainRoutine
END PROGRAM
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)