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


Code:
' PROGRAM The Towers of Hanoi
' (c) Zarsoft 2022 Pascalated BASIC
' (c) Zarsoft 2023 Pascalated Boriel ZX BASIC
' 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 The Towers of Hanoi

' CONSTant declarations
CONST black TYPE INTEGER = 0
CONST blue TYPE INTEGER = 1
CONST green TYPE INTEGER = 4
CONST white TYPE INTEGER = 7
CONST MinDisks TYPE INTEGER = 6
CONST PoleLine TYPE INTEGER = 16

' VAR - Global variables
VAR DiskShape(11) TYPE STRING ' :REM disk ARRAY (0..10) OF ARRAY (1..19) OF CHAR;
VAR Pole(3,11) TYPE INTEGER ' pole ARRAY (1..03) OF ARRAY (1..10) OF INTEGER;
VAR PoleLen(3) TYPE INTEGER :REM REM PoleLen :ARRAY (1..03) OF INTEGER;
VAR PoleCol(3) TYPE INTEGER :REM REM PoleCol :ARRAY (1..03) OF INTEGER;
VAR f,t TYPE INTEGER ' from, to
VAR MaxDisks TYPE INTEGER
VAR movement TYPE INTEGER
VAR LegalMove TYPE BOOLEAN
VAR abort TYPE BOOLEAN
VAR TheEnd TYPE BOOLEAN

PROCEDURE CheckEnd
LET TheEnd = TRUE
IF abort THEN LET TheEnd = FALSE
IF (MaxDisks < MinDisks)
  LET TheEnd = FALSE
  PRINT AT PoleLine+2,0;
  PRINT INK 3;"    =-- NOT ENOUGH DISKS --="
  PRINT INK 2;"           Try again  "
ELSEIF (MaxDisks >= MinDisks) AND (movement > 2^MaxDisks-1)
  LET TheEnd = FALSE
  PRINT AT PoleLine+2,0;
  PRINT INK 3;"  =-- TOO MUCH MOVEMENTS --="
  PRINT INK 2;"         Try again  "
  PAUSE 10
ENDIF
PRINT AT 21,0;PAPER 1;"   Press any key to continue    "
PAUSE 10
PAUSE 10
PAUSE 0
END PROCEDURE

PROCEDURE finalization
PRINT AT PoleLine+2,0;
PRINT INK 3;"  ===-- CONGRATULATIONS! --==="
PRINT INK 2;"                                "
: FOR i=-11 TO 11: BEEP .01,i: BEEP .01,ABS(i): NEXT i
PAUSE 0
END PROCEDURE

PROCEDURE MoveDisk (f TYPE INTEGER,t TYPE INTEGER)
VAR column TYPE INTEGER
VAR l,col TYPE INTEGER
BEGIN
LET movement = movement+1
PRINT AT 2,0;"This move: ";movement
LET PoleLen(t) = PoleLen(t)+1
LET Pole(t,PoleLen(t)) = Pole(f,PoleLen(f))
LET Pole(f,PoleLen(f)) = 0
LET PoleLen(f) = PoleLen(f)-1
REM move up
LET col = PoleCol(f)
FOR l = PoleLine-PoleLen(f)-2 TO PoleLine-11 STEP -1
  PRINT AT l,col;INK green;DiskShape$(Pole(t,PoleLen(t))+1);
  PRINT AT l+1,col;INK blue;DiskShape$(0+1);
NEXT l
REM left/right
IF f < t
  REM move right
  LET col = PoleCol(f)+2
  WHILE col < PoleCol(t)
    PRINT AT PoleLine-11,col-2;INK green;"  ";DiskShape$(Pole(t,PoleLen(t))+1);
    LET col = col+2
  END WHILE
ELSE
  REM move left
  LET col = PoleCol(f)-2
  WHILE col > PoleCol(t)
    PRINT AT PoleLine-11,col;INK green;DiskShape$(Pole(t,PoleLen(t))+1);"  ";
    LET col = col-2
  END WHILE
ENDIF
PRINT AT PoleLine-11,PoleCol(t);"         ";
PRINT AT PoleLine-11,0;"                                ";
PRINT AT PoleLine-10,PoleCol(t);INK green;DiskShape$(Pole(t,PoleLen(t))+1);
REM move down
LET col = PoleCol(t)
FOR l = PoleLine-9 TO PoleLine-PoleLen(t)
  PRINT AT l,col;INK green;DiskShape$(Pole(t,PoleLen(t))+1);
  PRINT AT l-1,col;INK blue;DiskShape$(0+1);
NEXT l
END PROCEDURE

PROCEDURE CheckLegalMove
REM (VAR f,t:INTEGER);
LET LegalMove = TRUE
IF (f = t) OR (PoleLen(f) = 0)
  LET LegalMove = FALSE
ELSEIF PoleLen(t) <> 0
  IF NOT( Pole(f,PoleLen(f)) < Pole(t,PoleLen(t)) ) THEN LET LegalMove = FALSE
ENDIF
END PROCEDURE

PROCEDURE InputMove
REM (VAR f,t:INTEGER);
VAR k$ TYPE STRING
BEGIN
PRINT AT PoleLine+2,1;"MOVE FROM... ";
REPEAT
  PAUSE 0
  LET k$ = INKEY$
UNTIL k$ >= "0" AND k$ <= "9"
BEEP .1,5
LET f = VAL (k$)
LET k$ = "X"
IF f=0 THEN LET abort = TRUE: LET k$="0"
PRINT AT PoleLine+2,1;"MOVE FROM ";f;" TO... ";
WHILE NOT(abort) AND NOT (k$ >= "0" AND k$ <= "9")
  PAUSE 0
  LET k$ = INKEY$
END WHILE
BEEP .1,5
LET t = VAL k$
IF t=0 THEN LET abort = TRUE
IF abort THEN LET f = 1: LET t = 1
PRINT AT PoleLine+2,1;"                            ";
END PROCEDURE

PROCEDURE PrintPole (PoleNumber TYPE INTEGER)
VAR col TYPE INTEGER
VAR i TYPE INTEGER
BEGIN
LET col = PoleCol(PoleNumber)
FOR i = 1 TO 10
  IF Pole(PoleNumber,i) = 0 THEN INK blue
  IF Pole(PoleNumber,i) <> 0 THEN INK green
  PRINT AT PoleLine-i,col;DiskShape$(Pole(PoleNumber,i)+1);
NEXT i
INK white
END PROCEDURE

PROCEDURE Initialization
VAR i TYPE INTEGER
BEGIN
LET TheEnd = FALSE
LET abort = FALSE
LET PoleCol(1) = 1
LET PoleCol(2) = 1+9+2
LET PoleCol(3) = 1+9+2+9+2
LET DiskShape$( 1) =  "    |    "
LET DiskShape$( 2) =  "    1    "
LET DiskShape$( 3) =  "   \A2\C   "
LET DiskShape$( 4) =  "   \B3\B   "
LET DiskShape$( 5) =  "  \A\B4\B\C  "
LET DiskShape$( 6) =  "  \B\B5\B\B  "
LET DiskShape$( 7) =  " \A\B\B6\B\B\C "
LET DiskShape$( 8) =  " \B\B\B7\B\B\B "
LET DiskShape$( 9) =  "\A\B\B\B8\B\B\B\C"
LET DiskShape$(10) =  "\B\B\B\B9\B\B\B\B"
FOR i = 1 TO 10
  LET Pole(1,i) = 0
  LET Pole(2,i) = 0
  LET Pole(3,i) = 0
NEXT i
FOR i = 1 TO MaxDisks
  LET Pole(1,i) = MaxDisks-(i-1)
NEXT i
LET PoleLen(1) = MaxDisks
LET PoleLen(2) = 0
LET PoleLen(3) = 0
INK blue
PRINT AT PoleLine,PoleCol(1);
PRINT "\::\::\::\::1\::\::\::\::";
PRINT "  ";
PRINT "\::\::\::\::2\::\::\::\::";
PRINT "  ";
PRINT "\::\::\::\::3\::\::\::\::";
INK white
LET movement = 0
PRINT AT 0,7;INK green;"THE TOWERS OF HANOI"
PRINT AT 2,19;"Minimum: ";2^MaxDisks-1
PAPER blue: INK green
PRINT AT 21,0;"1,2,3 - Select pole    0 - ABORT"
PAPER black
END PROCEDURE

PROCEDURE AskMaxDisks
VAR  k$ TYPE CHAR
BEGIN
INK green
PRINT AT PoleLine+3,0;"NUMBER OF DISKS = [1..9] ";
REPEAT
  PAUSE 0
  LET k$ = INKEY$
UNTIL k$ >= "1" AND k$ <= "9"
BEEP .1,5
LET MaxDisks = VAL (k$)
IF MaxDisks=0 THEN LET MaxDisks = 10
PRINT AT PoleLine+2,1;
END PROCEDURE

PROCEDURE Introduction
REM VAR s :BOOLEAN
BEGIN
BORDER black: PAPER black:  INK green: CLS
PRINT "     THE TOWERS OF HANOI"
PRINT
INK white
PRINT "In the great temple of Brahma","in Benares of India, there is ","a plate with 3 diamond needles","under the dome that marks the","center of the world."
PRINT
PRINT "At the creation, God placed 64","disks of pure gold in the order of their sizes, from largest to smallest."
PRINT
PRINT "This is the Tower of Brahma."
PRINT
PRINT "Day and night unceasingly the","monks of the temple move the","disks from one diamond needle","to another."
PRINT
PRINT AT 21,0;PAPER 1;"Press any key to read the rules"
PAUSE 0
INK 6
CLS
PRINT INK 3;"RULES:"
PRINT
PRINT " 1 - Only one disk can be moved at a time."
PRINT
PRINT " 2 - A disk can only be placed","on a larger disk (or no smaller disk below)."
PRINT
PRINT " 3 - All disks must go to the","third needle."
PRINT
INK 7
PRINT "When all disks are moved from","the first needle to the third","needle forming the Tower of","Brahma, then will come the end","of the universe and all will","turn to dust."
PRINT
END PROCEDURE

PROCEDURE DefineChars
VAR n TYPE INTEGER
'RESTORE DataChars
READ b$
REPEAT
  FOR i=0 TO 7
    READ n
    POKE USR b$+i,n
  NEXT i
  READ b$
UNTIL b$ = ""
END PROCEDURE

PROCEDURE DataChars
DATA "A"
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00001111
DATA BIN 00001111
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA "B"
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA "C"
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 11110000
DATA BIN 11110000
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA ""
END PROCEDURE

PROCEDURE MainRoutine
DefineChars
REPEAT
  Introduction
  AskMaxDisks
  CLS
  Initialization
  PrintPole(1)
  PrintPole(2)
  PrintPole(3)
  REPEAT
    InputMove: REM (f,t)
    CheckLegalMove: REM (f,t)
    IF LegalMove THEN MoveDisk(f,t)
  UNTIL (PoleLen(3) = MaxDisks) OR abort
  CheckEnd
UNTIL TheEnd
finalization
END PROCEDURE

BEGIN
CLS
PRINT "Demo for Pascalated BASIC"
MainRoutine
END
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)