====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