====Xbasic====
For some time I felt enthusiastic about this BASIC compiler designed back in the VisualBasic 3.x times, as a solution to easily program Windows. But laziness beat me, I stopped using it, and, when I felt strong enough to return to Xbasic I discovered it was not so easy as it seemed...
===xbcaballo ===
This program generates all possible knight trips ('caballo' is the Spanish word for the chess knight). I used Xbasic to speed up things and allow for special data types, such as BYTE, to save memory.
The movements are output to a text file, and can be interpreted with a qbasic program such as the one shown below. I made a javascript program to allow player try to interactively solve knight trips, also.
Please notice the attached file does not contain the english comments.
'
'
' ####################
' ##### PROLOG #####
' ####################
'
PROGRAM "xbCaballo" ' 1-8 char program/file name without .x or any .extent
VERSION "1.1000" ' version number - increment before saving altered program
'
' You can stop the PDE from inserting the following PROLOG comment lines
' by removing them from the prolog.xxx file in your \xb\xxx directory.
'
' Programs contain: 1: PROLOG - no executable code - see below
' 2: Entry function - start execution at 1st declared func
' * = optional 3: Other functions - everything else - all other functions
'
' The PROLOG contains (in this order):
' * 1. Program name statement PROGRAM "progname"
' * 2. Version number statement VERSION "0.0000"
' * 3. Import library statements IMPORT "libName"
' * 4. Composite type definitions TYPE ... END TYPE
' 5. Internal function declarations DECLARE/INTERNAL FUNCTION Func (args)
' * 6. External function declarations EXTERNAL FUNCTION FuncName (args)
' * 7. Shared constant definitions $$ConstantName = literal or constant
' * 8. Shared variable declarations SHARED variable
'
' ****** Comment libraries in/out as needed *****
'
' IMPORT "xma" ' Math library : SIN/ASIN/SINH/ASINH/LOG/EXP/SQRT...
' IMPORT "xcm" ' Complex library : complex number library (trig, etc)
IMPORT "xst" ' Standard library : required by most programs
' IMPORT "xgr" ' GraphicsDesigner : required by GuiDesigner programs
' IMPORT "xui" ' GuiDesigner : required by GuiDesigner programs
'
DECLARE FUNCTION Entry ()
DECLARE FUNCTION ProbarDirec ()
DECLARE FUNCTION SBYTE Matriz (SSHORT X, SSHORT Y)
DECLARE FUNCTION RecorrerInversoEImprimir (SSHORT X, SSHORT Y)
DECLARE FUNCTION MostrarSolucion (S$)
DECLARE FUNCTION SSHORT Cargarsolucion ()
SHARED SBYTE VengoDe[64]
'
'
' ######################
' ##### Entry () #####
' ######################
'
' Programs contain:
' 1. A PROLOG with type/function/constant declarations.
' 2. This Entry() function where execution begins.
' 3. Zero or more additional functions.
'
FUNCTION Entry ()
SHARED SBYTE VengoDe[64]
'Vengode (=ICamefrom[] ) contains the 64 squares in jump order.
SHARED SBYTE MovimientoX[7]
SHARED SBYTE MovimientoY[7]
' MovimientoX and MovimientoY contain the destination X and Y coordinates
' of each possible movement.
AUTO SBYTE X
AUTO SBYTE Y
AUTO SBYTE NextX
AUTO SBYTE NextY
SHARED SBYTE Puntero
MovimientoY[0]=-2:MovimientoX[0]=1
MovimientoY[1]=-1:MovimientoX[1]=2
MovimientoY[2]=1:MovimientoX[2]=2
MovimientoY[3]=2:MovimientoX[3]=1
MovimientoY[4]=2:MovimientoX[4]=-1
MovimientoY[5]=1:MovimientoX[5]=-2
MovimientoY[6]=-1:MovimientoX[6]=-2
MovimientoY[7]=-2:MovimientoX[7]=-1
VengoDe[0]=-1
'Idea:
'Increase one by one directions
' Direccion=0
' Test whether destination coordinates for direction are inside board or not.
' If they are offbounds, jump to end of loop: Direccion=Direccion+1
' Test whether or not coordinates carry us to an unvisited square (VengoDe=-3)
' If visited (>=0), jump to end of loop: Direccion=Direccion+1
' If unvisited (=-3),
' X=X+DireccionX[Direccion]
' Y=Y+DireccionY[Direccion]
' VengoDe[X,Y]=Direccion.
' Increase direction pointer (Puntero). Test it is < 64.
' If it is 64, travel backwards and print it.
' Return to start of loop, with direccion=0
'END OF LOOP (Direccion=Direccion+1)
' If direccion>= 8
' Take VengoDe and Mark current square as free.
'Return backwards using (VengoDe+4 MOD 8)
'Reduce address pointer (Puntero).
'1-Mark all squares as free.
FOR F=0 TO 64
VengoDe[F]=-3
NEXT F
'Recover old solutions--this allows program to run in batch mode.
SI$=INLINE$("Do you want to recover solutions from file (Y/N)?")
RESP=0
DO WHILE RESP=0
IF (UCASE$(SI$)="S") OR (UCASE$(SI$)="Y") THEN RESP=1
IF UCASE$(SI$)="N" THEN RESP=-1
LOOP
IF RESP=1 THEN
R=Cargarsolucion()
IF R<>-1 THEN
X=R MOD 8
Y=INT(R / 8)
GOTO RecienCargado
END IF
END IF
'Variable initialization
Puntero=0
X=0
Y=0
'Main Loop
DO
NextX=X+MovimientoX[Direccion]
NextY=Y+MovimientoY[Direccion]
' Test if coordinates for direction Direccion are valid
' If unvisited (=-3),
Mat=Matriz(NextX,NextY)
'PRINT SPACE$(Puntero+1)+STRING$(Direccion)+"["+STRING$(Puntero)+"]"
IF Mat=-3 THEN
X=NextX
Y=NextY
VengoDe[Y*8+X]=Direccion
Direccion=0
Puntero=Puntero+1
'We reach this point after loading old solutions
RecienCargado:
IF Puntero=63 THEN
RecorrerInversoEImprimir(X,Y)
GOSUB Retroceso
END IF
ELSE
Direccion=Direccion+1
DO WHILE Direccion>=8
GOSUB Retroceso
LOOP
END IF
LOOP
'
'
'Retroceso = Go backwards.
'This sub allows us to go backwards one (or more) steps and try next solution.
'
SUB Retroceso
VengoDesde=Matriz(X,Y)
VengoDe[Y*8+X]=-3
'If vengoDesde contains an illegal value, chances are that we have ended.
IF VengoDesde<0 THEN EXIT FUNCTION
'If "Puntero" (pointer) is -1, chances are that we have ended.
Puntero=Puntero-1
IF Puntero<0 THEN EXIT FUNCTION
X=X+MovimientoX[(VengoDesde+4) MOD 8]
Y=Y+MovimientoY[(VengoDesde+4) MOD 8]
Direccion=VengoDesde+1
END SUB
END FUNCTION
'
'
' ############################
' ##### ProbarDirec () #####
' ############################
'
FUNCTION ProbarDirec ()
SHARED SBYTE MovimientoX[]
SHARED SBYTE MovimientoY[]
FOR f=0 TO 7
FOR g=-2 TO 2
Q$="|"
FOR h=-2 TO 2
IF (h=MovimientoX[f]) AND (g=MovimientoY[f]) THEN
Q$=Q$+"*"
ELSE
IF (h=0) AND (g=0) THEN
Q$=Q$+"X"
ELSE
IF (h=MovimientoX[(f+4) MOD 8]) AND (g=MovimientoY[(f+4) MOD 8]) THEN
Q$=Q$+"@"
ELSE
Q$=Q$+" "
END IF
END IF
END IF
Q$=Q$+"|"
NEXT h
PRINT Q$
Q$="-"
FOR h=-2 TO 2
Q$=Q$+"--"
NEXT
PRINT Q$
NEXT g
PRINT
PRINT f
X$=INLINE$(X$)
NEXT f
END FUNCTION
'
'
' #######################
' ##### Matriz () #####
' #######################
'
FUNCTION SBYTE Matriz (SSHORT X, SSHORT Y)
SHARED SBYTE VengoDe[]
IF X<0 THEN RETURN -2
IF X>=8 THEN RETURN -2
IF Y<0 THEN RETURN -2
IF Y>=8 THEN RETURN -2
'PRINT Y*8+X;"=>";
'PRINT VengoDe[Y*8+X]
RETURN (VengoDe[Y*8+X])
END FUNCTION
'
'
' #########################################
' ##### RecorrerInversoEImprimir () #####
' #########################################
'
FUNCTION RecorrerInversoEImprimir (SSHORT X, SSHORT Y)
SHARED SBYTE MovimientoX[]
SHARED SBYTE MovimientoY[]
ofile=OPEN ("SALTOSCABALLO.TXT",$$RW)
SEEK (ofile,LOF(ofile))
P$=""
Direc=Matriz(X,Y)
DO WHILE Direc>=0
P$=STR$(Direc)+P$
X=X+MovimientoX[(Direc+4) MOD 8]
Y=Y+MovimientoY[(Direc+4) MOD 8]
Direc=Matriz(X,Y)
LOOP
PRINT P$
PRINT [ofile],P$
CLOSE (ofile)
' Un-comment this to show solution in a chess board.
' MostrarSolucion(Solu1$)
END FUNCTION
'
'
' ################################
' ##### MostrarSolucion () #####
' ################################
'
FUNCTION MostrarSolucion (S$)
SHARED SBYTE MovimientoX[]
SHARED SBYTE MovimientoY[]
SBYTE Mat[8,8]
SBYTE Dir
SBYTE X
SBYTE Y
UBYTE P
Tablero$=""
X=0:Y=0:P=0
FOR f=1 TO LEN(S$) STEP 2
Mat[X,Y]=P
P=P+1
Dir=SBYTE(MID$(S$,f,2))
X=X+MovimientoX[Dir]
Y=Y+MovimientoY[Dir]
NEXT f
Mat[X,Y]=P
FOR X=0 TO 7
L1$=""
L2$=""
FOR Y=0 TO 7
L1$=L1$+RIGHT$(STR$(Mat[X,Y]),2)+"|"
L2$=L2$+"---"
NEXT Y
Tablero$=Tablero$+L1$+"\n"+L2$+"\n"
NEXT X
PRINT Tablero$
END FUNCTION
'
'
' ###############################
' ##### Cargarsolucion () #####
' ###############################
'
FUNCTION USHORT Cargarsolucion ()
SHARED SBYTE VengoDe[]
SHARED SBYTE MovimientoX[]
SHARED SBYTE MovimientoY[]
SBYTE Dir
SHARED SBYTE Puntero
AUTO SBYTE X
AUTO SBYTE Y
SSHORT ifile
ifile=OPEN ("SALTOSCABALLO.TXT",$$RD)
IF ifile=-1 THEN RETURN -1
longitud=LOF(ifile)
IF longitud=0 THEN
CLOSE (ifile)
XstDeleteFile("SALTOSCABALLO.TXT")
RETURN -1
END IF
PRINT "RELOADING LAST POSITION FROM FILE"
Line1$=""
DO
Line2$=Line1$
Line1$=INFILE$(ifile)
LOOP WHILE NOT EOF(ifile)
X=0:Y=0:Dir=0:Puntero=0
FOR f=1 TO LEN(Line2$) STEP 2
IF Matriz(X,Y)<>-3 THEN
PRINT "ERROR -- INVALID FILE OR DATA"
GOSUB VaciaTablero
RETURN -1
END IF
VengoDe[Y*8+X]=Dir
Puntero=Puntero+1
Dir=SBYTE(MID$(Line2$,f,2))
X=X+MovimientoX[Dir]
Y=Y+MovimientoY[Dir]
NEXT f
VengoDe[Y*8+X]=Dir
PRINT "Data successfuly loaded"
RETURN Y*8+X
SUB VaciaTablero
FOR f=0 TO 63
VengoDe[f]=-3
NEXT f
END SUB
END FUNCTION
END PROGRAM
'Trying the xbasic knight trip program.
Direcciones:
DATA 1,-2: '0 - at one
DATA 2,-1: '1 - at two
DATA 2,1: '2 - at four
DATA 1,2: '3 - at five
DATA -1,2: '4- at seven
DATA -2,1: '5- at eight
DATA -2,-1: '6 - at ten
DATA -1,-2: '7- At eleven
Saltos:
'Imported from saltoscaballo.txt, generated by xbasic's xcaballo.bas
DATA 2,1,2,3,4,3,6,0: '
DATA 0,5,2,4,5,0,0,0: '
DATA 5,0,5,2,0,5,4,4: '
DATA 1,2,4,6,5,6,0,0: '
DATA 0,3,0,5,6,4,2,7: '
DATA 4,3,4,1,0,6,7,1: '
DATA 4,4,3,2,0,7,4,4: '
DATA 7,1,0,3,4,2,1: '
DIM movimientox(0 TO 7)
DIM movimientoy(0 TO 7)
RESTORE Direcciones
FOR f = 0 TO 7
READ movimientox(f), movimientoy(f)
NEXT
CLS
FOR x = 0 TO 7
FOR y = 0 TO 7
LOCATE y * 2 + 1, x * 3 + 1
PRINT " |"
LOCATE y * 2 + 2, x * 3 + 1
PRINT "---"
NEXT y
NEXT x
RESTORE Saltos
x = 0: y = 0
FOR f = 0 TO 63
LOCATE y * 2 + 1, x * 3 + 1
PRINT USING "##|"; f
LOCATE y * 2 + 2, x * 3 + 1
PRINT "---"
IF f < 63 THEN READ salto
x = x + movimientox(salto)
y = y + movimientoy(salto)
SLEEP 0
NEXT f