'HUOC: Huo Chess by Spiros I. Kakos (huo) - DRAFT VERSION (NOT FULLY TESTED, STILL IN PROGRESS) 'Version 0.2: Thinking in 3 moves depth 'Based on the Huo Chess implementation in C++ and C# 'Check https://harmoniaphilosophica.com/2019/02/13/huo-chess-c-micro-chess-updated/ 'Graphics taken from Deep Basic by Thomas McBurney 'Check https://web.archive.org/web/20081230182814/http://home.pacific.net.au/~tommyinoz/db.html 'Check also https://archive.org/details/DeepBasic 'Other QBasic Internet resources 'https://www.qb64.org/wiki/Arrays#Working_with_the_Array_Elements 'https://www.qb64.org/wiki/CALL 'https://www.qb64.org/wiki/SUB 'https://www.qb64.org/wiki/IF...THEN 'What is not supported... '1. En passant '2. Castling '3. Check '4. Mate DECLARE SUB movValidation (aline AS INTEGER, fline AS INTEGER, arcol AS INTEGER, telcol AS INTEGER) DECLARE SUB drawBoard () DECLARE SUB ElegxosNomimotitas(ENSkakiera() AS STRING, startColumn AS INTEGER, startRank AS INTEGER, finishColumn AS INTEGER, finishRank AS INTEGER, MovingPieceEN AS STRING) DEFINT A-Z OPTION BASE 1 'Make tables dimensions start from 1 DIM SHARED chessboard$(8, 8) COMMON SHARED playerColor$ COMMON SHARED startingRank, startingColumn COMMON SHARED finishingRank, finishingColumn COMMON SHARED startingRankText$, startingColumnText$ COMMON SHARED finishingRankText$, finishingColumnText$ COMMON SHARED Move$ COMMON SHARED MovingPiece$ COMMON SHARED ProsorinoKommati$ COMMON SHARED Nomimotita COMMON SHARED debugMode COMMON SHARED positionScore COMMON SHARED bestStartingRank, bestStartingColumn COMMON SHARED bestFinishingRank, bestFinishingColumn COMMON SHARED bestPositionScore COMMON SHARED whoPlays$ COMMON SHARED computerLogs$, humanLogs$ 'MinMax 'Important note: All dimensions in the tables are +1 compared to the Huo Chess in C#! (tables start from 1 here) COMMON SHARED foundMove DIM SHARED NodesAnalysis0(1000000, 6) DIM SHARED NodesAnalysis1(1000000, 2) DIM SHARED NodesAnalysis2(1000000, 2) 'DIM SHARED NodesAnalysis3%(10000000, 2) 'DIM SHARED NodesAnalysis4%(10000000, 2) DIM SHARED NodesMoves0$(1000000) DIM SHARED NodesMoves1$(1000000) DIM SHARED NodesMoves2$(1000000) COMMON SHARED NodeLevel_0_count AS LONG COMMON SHARED NodeLevel_1_count AS LONG COMMON SHARED NodeLevel_2_count AS LONG COMMON SHARED parentNodeAnalyzed AS LONG DIM SHARED bestNodes0(10000000) DIM SHARED bestNodes1(10000000) DIM SHARED bestNodes2(10000000) COMMON SHARED bestNode2, bestNode1, bestNode0 COMMON SHARED counter0 AS LONG COMMON SHARED counter1 AS LONG COMMON SHARED counter2 AS LONG COMMON SHARED counter3 AS LONG COMMON SHARED counter4 AS LONG COMMON SHARED huologs$, logLine$ OPEN "Huo Chess Logs - Nodes before.txt" FOR OUTPUT AS #1 OPEN "Huo Chess Logs - Nodes after.txt" FOR OUTPUT AS #2 WRITE #1, "Huo Chess Logs - Nodes before" WRITE #1, "" WRITE #2, "Huo Chess Logs - Nodes after" WRITE #2, "" COMMON SHARED thinkingDepth COMMON SHARED Move 'Set debugMode = 1 if you want debugging messages to appear, else set to 0 debugMode = 0 PRINT "Huo Chess - HUOC by Spiros Kakos (2020) - ALPHA VERSION" PRINT "The best educational purposes open source chess in BASIC" PRINT "" PRINT "Version 0.3: Thinking in 3 moves depth" PRINT "" PRINT "NOT FULLY FUNCTIONAL!" PRINT "NOT FULLY TESTED!" PRINT "FOR EDUCATIONAL PURPOSES ONLY!" PRINT "DEVELOPERS VERSION - TEST POSITION LOADED!" PRINT "" PRINT "Check HUO CHESS in C# for a fully functional open source chess program!" PRINT "" PRINT "Graphics taken from Deep Basic by Thomas McBurney" PRINT "" SetPlayerColor: 'Set the colour of the player INPUT "Set your color. Please select 'w' or 'b': ", playerColor$ IF playerColor$ <> "w" AND playerColor$ <> "b" THEN GOTO SetPlayerColor SetThinkingDepth: 'Set the thinking depth PRINT "": INPUT "Set thinking depth. Please select 1 or 3: ", thinkingDepth IF thinkingDepth <> 1 AND thinkingDepth <> 3 THEN GOTO SetThinkingDepth PRINT "" PRINT "NOTE: Remember to delete text log files in the application folder!" PRINT "" computerLogs: INPUT "Activate debug messages for computer? (y/n) ", computerLogs$: IF computerLogs$ <> "y" AND computerLogs$ <> "n" THEN GOTO computerLogs humanLogs: INPUT "Activate debug messages for the human? (y/n) ", humanLogs$: IF humanLogs$ <> "y" AND humanLogs$ <> "n" THEN GOTO humanLogs CALL initialPosition DIM SHARED P$(6), PIECE%(7, 16, 8, 2), CMOVES%(6, 100), HMOVES%(6, 100) DIM SHARED BO%(8, 9), CB%(9, 9) DIM SHARED ENGINE%(10, 100, 5), SCORE%(12, 2) DIM SHARED PAWN%(8, 2), BESTL%(10, 12, 4), HISTORY%(4, 10) DIM SHARED QENGINE%(15, 30, 5), QSCORE%(15, 2), QB%(8, 9) DIM SHARED FIRSTPLY%(218) DIM SHARED FIND$(10), QUERY$(9), dsc$(10), RECORD$(10) DIM SHARED TAKEBACK%(5, 200), v%(6) DIM SHARED TESTMODE%, NODES, EVAL%, MATEH%, MATEC%, SIDE%, PHASE%, HKY%, HKX% DIM SHARED CKY%, CKX%, SCORE%, TEMP1%, TEMP2%, TEMP3%, A%, TX%, TY% DIM C$(8), CY$(8) ' GRAPHICS DIM SHARED Gpiece(0 TO 400) AS INTEGER DIM SHARED blot(0 TO 400) AS INTEGER DIM SHARED GraphicImage(0 TO 4800) AS INTEGER 'SIDE 0 = COMPUTER PLAYS BLACK 'SIDE 1 = COMPUTER PLAYS WHITE 'SIDE% = 0 SCREEN 9 '12 '**** LOAD IMAGES OF PIECES LoadPieces: '**** LOAD GRAPHICS OF PIECES OFF DISK DEF SEG = VARSEG(GraphicImage(0)) BLOAD "PIECES.EGA", VARPTR(GraphicImage(0)) P$(1) = "P": P$(2) = "N": P$(3) = "B": P$(4) = "R": P$(5) = "Q": P$(6) = "K" C$(1) = "A": C$(2) = "B": C$(3) = "C": C$(4) = "D": C$(5) = "E": C$(6) = "F": C$(7) = "G": C$(8) = "H" CY$(1) = "8": CY$(2) = "7": CY$(3) = "6": CY$(4) = "5": CY$(5) = "4": CY$(6) = "3": CY$(7) = "2": CY$(8) = "1" ' PIECE VALUE v%(1) = 100: v%(2) = 300: v%(3) = 305 v%(4) = 500: v%(5) = 900: v%(6) = 19000 'MAXQDEPTH% = 4 'LEVEL% = 10 'MOVESPERHOUR% = 360 'BEEPMODE% = 0 ' *** KNIGHT PIECE%(2, 1, 1, 1) = -1: PIECE%(2, 1, 1, 2) = -2 PIECE%(2, 2, 1, 1) = 1: PIECE%(2, 2, 1, 2) = -2 PIECE%(2, 3, 1, 1) = 2: PIECE%(2, 3, 1, 2) = -1 PIECE%(2, 4, 1, 1) = 2: PIECE%(2, 4, 1, 2) = 1 PIECE%(2, 5, 1, 1) = 1: PIECE%(2, 5, 1, 2) = 2 PIECE%(2, 6, 1, 1) = -1: PIECE%(2, 6, 1, 2) = 2 PIECE%(2, 7, 1, 1) = -2: PIECE%(2, 7, 1, 2) = 1 PIECE%(2, 8, 1, 1) = -2: PIECE%(2, 8, 1, 2) = -1 '*** BISHOP FOR I = 1 TO 8 PIECE%(3, 1, I, 1) = I * -1: PIECE%(3, 1, I, 2) = I * -1 PIECE%(3, 2, I, 1) = I: PIECE%(3, 2, I, 2) = I * -1 PIECE%(3, 3, I, 1) = I: PIECE%(3, 3, I, 2) = I PIECE%(3, 4, I, 1) = I * -1: PIECE%(3, 4, I, 2) = I NEXT ' **** ROOK FOR I = 1 TO 8 PIECE%(4, 1, I, 1) = 0: PIECE%(4, 1, I, 2) = I * -1 PIECE%(4, 2, I, 1) = I: PIECE%(4, 2, I, 2) = 0 PIECE%(4, 3, I, 1) = 0: PIECE%(4, 3, I, 2) = I PIECE%(4, 4, I, 1) = I * -1: PIECE%(4, 4, I, 2) = 0 NEXT ' **** QUEEN FOR D = 1 TO 4 FOR I = 1 TO 8 PIECE%(5, D, I, 1) = PIECE%(3, D, I, 1): PIECE%(5, D, I, 2) = PIECE%(3, D, I, 2) NEXT NEXT FOR D = 1 TO 4 FOR I = 1 TO 8 PIECE%(5, D + 4, I, 1) = PIECE%(4, D, I, 1): PIECE%(5, D + 4, I, 2) = PIECE%(4, D, I, 2) NEXT NEXT ' **** KING FOR I = 1 TO 8 PIECE%(6, I, 1, 1) = PIECE%(5, I, 1, 1): PIECE%(6, I, 1, 2) = PIECE%(5, I, 1, 2) NEXT ' ***** SUPER PIECE FOR D = 1 TO 8 FOR S = 1 TO 8 PIECE%(7, D, S, 1) = PIECE%(5, D, S, 1): PIECE%(7, D, S, 2) = PIECE%(5, D, S, 2) NEXT NEXT FOR D = 1 TO 8 PIECE%(7, D + 8, 1, 1) = PIECE%(2, D, 1, 1): PIECE%(7, D + 8, 1, 2) = PIECE%(2, D, 1, 2) NEXT START: '************************** START ************************************** COLOR 7 MAIN: INITBOARD: '****************************************************************** ' Initialise the board '****************************************************************** FOR Y = 1 TO 9 FOR X = 1 TO 8 BO%(X, Y) = 0 NEXT NEXT FOR X = 1 TO 8: BO%(X, 2) = -1: BO%(X, 7) = 1: NEXT BO%(1, 1) = -4: BO%(8, 1) = -4: BO%(2, 1) = -2: BO%(7, 1) = -2 BO%(3, 1) = -3: BO%(6, 1) = -3: BO%(4, 1) = -5: BO%(5, 1) = -6 FOR X = 1 TO 8: BO%(X, 8) = BO%(X, 1) * -1: NEXT FOR I = 1 TO 4: BO%(I, 9) = 1: BO%(I + 4, 9) = 0: NEXT CALL DRAWBOARD COLOR 7 'LOCATE 2, 58: PRINT "MOVES LIST" LOCATE 2, 58: PRINT "H UO CHESS" 'LOCATE 5, 55: INPUT "Enter move:", Move$ 'LOCATE 7, 55: PRINT "Thinking..." IF playerColor$ = "w" THEN whoPlays$ = "Human" CALL PlayerMove END IF IF playerColor$ = "b" THEN whoPlays$ = "HY" LOCATE 7, 55: PRINT "Thinking... " CALL computerMove END IF SUB PlayerMove LOCATE 5, 67: PRINT " " LOCATE 5, 55: INPUT "Enter move: ", Move$ startingColumnText$ = MID$(Move$, 1, 1) startingRankText$ = MID$(Move$, 2, 1) finishingColumnText$ = MID$(Move$, 3, 1) finishingRankText$ = MID$(Move$, 4, 1) IF humanLogs$ = "y" THEN debugMode = 1 ELSE debugMode = 0 SELECT CASE startingRankText$ CASE "1" startingRank = 1 CASE "2" startingRank = 2 CASE "3" startingRank = 3 CASE "4" startingRank = 4 CASE "5" startingRank = 5 CASE "6" startingRank = 6 CASE "7" startingRank = 7 CASE "8" startingRank = 8 END SELECT SELECT CASE finishingRankText$ CASE "1" finishingRank = 1 CASE "2" finishingRank = 2 CASE "3" finishingRank = 3 CASE "4" finishingRank = 4 CASE "5" finishingRank = 5 CASE "6" finishingRank = 6 CASE "7" finishingRank = 7 CASE "8" finishingRank = 8 END SELECT SELECT CASE startingColumnText$ CASE "A", "a" startingColumn = 1 CASE "B", "b" startingColumn = 2 CASE "C", "c" startingColumn = 3 CASE "D", "d" startingColumn = 4 CASE "E", "e" startingColumn = 5 CASE "F", "f" startingColumn = 6 CASE "G", "g" startingColumn = 7 CASE "H", "h" startingColumn = 8 END SELECT SELECT CASE finishingColumnText$ CASE "A", "a" finishingColumn = 1 CASE "B", "b" finishingColumn = 2 CASE "C", "c" finishingColumn = 3 CASE "D", "d" finishingColumn = 4 CASE "E", "e" finishingColumn = 5 CASE "F", "f" finishingColumn = 6 CASE "G", "g" finishingColumn = 7 CASE "H", "h" finishingColumn = 8 END SELECT MovingPiece$ = chessboard$(startingColumn, startingRank) IF (debugMode = 1) THEN PRINT "[Move: " + STR$(startingColumn) + STR$(startingRank) + " -> " + STR$(finishingColumn) + STR$(finishingRank) + " ]" END IF 'Check legality of the move entered CALL ElegxosNomimotitas(chessboard$(), 0, startingColumn, startingRank, finishingColumn, finishingRank, MovingPiece$) 'If move is legal, then do the move and present it in the chessbooard IF Nomimotita = 1 THEN IF debugMode = 1 THEN PRINT "Now we will redraw the chessboard" END IF 'Do the move chessboard$(finishingColumn, finishingRank) = chessboard$(startingColumn, startingRank) chessboard$(startingColumn, startingRank) = "" 'LOCATE 8, 55: PRINT "Move OK" 'LOCATE 9, 55: INPUT "Checkpoint", A$ CALL DRAWBOARD END IF 'Time for the computer to think now... whoPlays$ = "HY" LOCATE 7, 55: PRINT "Thinking... " CALL computerMove END SUB SUB computerMove 'Initialize variables Move = 1 bestPositionScore = 0 bestStartingRank = 0 bestStartingColumn = 0 bestFinishingRank = 0 bestFinishingColumn = 0 IF playerColor$ = "w" THEN bestPositionScore = 999 IF playerColor$ = "b" THEN bestPositionScore = -999 'MinMax foundMove = 0 NodeLevel_0_count = 1 NodeLevel_1_count = 1 NodeLevel_2_count = 1 IF computerLogs$ = "y" THEN debugMode = 1 ELSE debugMode = 0 'Scan the chessboard... FOR I = 1 TO 8 FOR J = 1 TO 8 'If you find a piece of the computer... IF ((MID$(chessboard$(I, J), 1, 1) = "w" AND playerColor$ = "b") OR (MID$(chessboard$(I, J), 1, 1) = "b" AND playerColor$ = "w")) THEN 'Scan all possible destination squares... FOR ii = 1 TO 8 FOR jj = 1 TO 8 startingColumn = I startingRank = J finishingColumn = ii finishingRank = jj MovingPiece$ = chessboard$(I, J) ProsorinoKommati$ = chessboard$(ii, jj) 'Check legality of the move entered CALL ElegxosNomimotitas(chessboard$(), 0, startingColumn, startingRank, finishingColumn, finishingRank, MovingPiece$) IF debugMode = 1 THEN PRINT "" PRINT "NEW MOVE ANALYZED: " + STR$(startingColumn) + STR$(startingRank) + " -> " + STR$(finishingColumn) + STR$(finishingRank) PRINT "Legality of the move analyzed: " + STR$(Nomimotita) END IF IF startingColumn = 2 AND startingRank = 4 AND finishingColumn = 5 AND finishingRank = 7 THEN PRINT "" PRINT "BISHOP MOVE ANALYZED: " + STR$(startingColumn) + STR$(startingRank) + " -> " + STR$(finishingColumn) + STR$(finishingRank) PRINT "What is in e7: " + chessboard$(5, 7) PRINT "Moving piece : " + MovingPiece$ PRINT "Prosorino kommati : " + ProsorinoKommati$ PRINT "Legality of the move analyzed: " + STR$(Nomimotita) INPUT A$ END IF 'If move is legal, then do the move and present it in the chessbooard IF Nomimotita = 1 THEN '-------------- MinMax -------------- 'Important note: All dimensions in the tables are +1 compared to the Huo Chess in C#! (tables start from 1 here) NodesAnalysis0(NodeLevel_0_count, 3) = startingColumn NodesAnalysis0(NodeLevel_0_count, 4) = finishingColumn NodesAnalysis0(NodeLevel_0_count, 5) = startingRank NodesAnalysis0(NodeLevel_0_count, 6) = finishingRank 'If first move found, then store it (This is useless) IF foundMove = 0 THEN 'NodesAnalysis0(NodeLevel_0_count, 3) = startingColumn 'NodesAnalysis0(NodeLevel_0_count, 4) = finishingColumn 'NodesAnalysis0(NodeLevel_0_count, 5) = startingRank 'NodesAnalysis0(NodeLevel_0_count, 6) = finishingRank 'PRINT "startingColumn = " + STR$(startingColumn) 'PRINT "finishingColumn = " + STR$(finishingColumn) 'PRINT "startingRank = " + STR$(startingRank) 'PRINT "finishingRank = " + STR$(finishingRank) 'INPUT A$ foundMove = 1 END IF 'Do the move chessboard$(finishingColumn, finishingRank) = chessboard$(startingColumn, startingRank) chessboard$(startingColumn, startingRank) = "" 'Count the score of the move CALL countScore IF debugMode = 1 THEN PRINT "" PRINT "NodeLevel_0_count = " + STR$(NodeLevel_0_count) PRINT "NodeLevel_1_count = " + STR$(NodeLevel_1_count) END IF '-------------- MinMax -------------- 'Store scores NodesAnalysis0(NodeLevel_0_count, 1) = positionScore ' Store parents NodesAnalysis0(NodeLevel_0_count, 2) = 0 'Store the move NodesMoves0$(NodeLevel_0_count) = STR$(startingColumn) + STR$(startingRank) + " -> " + STR$(finishingColumn) + STR$(finishingRank) IF Move = thinkingDepth THEN 'If the score is better than the existing best score, then this is the best move now (and the best score) IF ((playerColor$ = "b" AND positionScore >= bestPositionScore) OR (playerColor$ = "w" AND positionScore <= bestPositionScore)) THEN bestStartingRank = startingRank bestStartingColumn = startingColumn bestFinishingRank = finishingRank bestFinishingColumn = finishingColumn bestPositionScore = positionScore END IF END IF IF Move < thinkingDepth THEN CALL HumanMove1(chessboard$()) 'Undo the move chessboard$(startingColumn, startingRank) = MovingPiece$ chessboard$(finishingColumn, finishingRank) = ProsorinoKommati$ '-------------- MinMax -------------- 'Increase node count NodeLevel_0_count = NodeLevel_0_count + 1 END IF NEXT jj NEXT ii END IF NEXT J NEXT I IF debugMode = 1 THEN PRINT "bestStartingRank = " + STR$(bestStartingRank) PRINT "bestStartingColumn = " + STR$(bestStartingColumn) PRINT "bestFinishingRank = " + STR$(bestFinishingRank) PRINT "bestFinishingColumn = " + STR$(bestFinishingColumn) END IF '-------------- MinMax -------------- CALL MinMax 'Do the best move found chessboard$(bestFinishingColumn, bestFinishingRank) = chessboard$(bestStartingColumn, bestStartingRank) chessboard$(bestStartingColumn, bestStartingRank) = "" SELECT CASE bestStartingColumn CASE 1 startingColumnText$ = "a" CASE 2 startingColumnText$ = "b" CASE 3 startingColumnText$ = "c" CASE 4 startingColumnText$ = "d" CASE 5 startingColumnText$ = "e" CASE 6 startingColumnText$ = "f" CASE 7 startingColumnText$ = "g" CASE 8 startingColumnText$ = "h" END SELECT SELECT CASE bestFinishingColumn CASE 1 finishingColumnText$ = "a" CASE 2 finishingColumnText$ = "b" CASE 3 finishingColumnText$ = "c" CASE 4 finishingColumnText$ = "d" CASE 5 finishingColumnText$ = "e" CASE 6 finishingColumnText$ = "f" CASE 7 finishingColumnText$ = "g" CASE 8 finishingColumnText$ = "h" END SELECT LOCATE 7, 55: PRINT "My move: " + startingColumnText$ + STR$(bestStartingRank) + " -> " + finishingColumnText$ + STR$(bestFinishingRank) CALL DRAWBOARD 'Time for the human to play now... whoPlays$ = "Human" CALL PlayerMove END SUB '----------------------------------------------------------------------------------------------------- SUB initialPosition chessboard$(1, 1) = "wrook": chessboard$(1, 2) = "wpawn" chessboard$(2, 1) = "wknight": chessboard$(2, 2) = "wpawn" chessboard$(3, 1) = "wbishop": chessboard$(3, 2) = "wpawn" chessboard$(4, 1) = "wqueen": chessboard$(4, 2) = "wpawn" chessboard$(5, 1) = "wking": chessboard$(5, 2) = "wpawn" chessboard$(6, 1) = "wbishop": chessboard$(6, 2) = "wpawn" chessboard$(7, 1) = "wknight": chessboard$(7, 2) = "wpawn" chessboard$(8, 1) = "wrook": chessboard$(8, 2) = "wpawn" chessboard$(1, 7) = "bpawn": chessboard$(1, 8) = "brook" chessboard$(2, 7) = "bpawn": chessboard$(2, 8) = "bknight" chessboard$(3, 7) = "bpawn": chessboard$(3, 8) = "bbishop" chessboard$(4, 7) = "bpawn": chessboard$(4, 8) = "bqueen" chessboard$(5, 7) = "bpawn": chessboard$(5, 8) = "bking" chessboard$(6, 7) = "bpawn": chessboard$(6, 8) = "bbishop" chessboard$(7, 7) = "bpawn": chessboard$(7, 8) = "bknight" chessboard$(8, 7) = "bpawn": chessboard$(8, 8) = "brook" '---------- TEST ---------- chessboard$(1, 1) = "wrook": chessboard$(1, 2) = "wpawn" chessboard$(2, 1) = "wknight": chessboard$(2, 2) = "bpawn" chessboard$(3, 1) = "": chessboard$(3, 2) = "wpawn" chessboard$(4, 1) = "": chessboard$(4, 2) = "wpawn" chessboard$(5, 1) = "wking": chessboard$(5, 2) = "" chessboard$(6, 1) = "": chessboard$(6, 2) = "wpawn" chessboard$(7, 1) = "wknight": chessboard$(7, 2) = "wpawn" chessboard$(8, 1) = "wrook": chessboard$(8, 2) = "" chessboard$(1, 7) = "": chessboard$(1, 8) = "brook" chessboard$(2, 7) = "wbishop": chessboard$(2, 8) = "bknight" chessboard$(3, 7) = "bpawn": chessboard$(3, 8) = "" chessboard$(4, 7) = "bpawn": chessboard$(4, 8) = "bqueen" chessboard$(5, 7) = "bpawn": chessboard$(5, 8) = "bking" chessboard$(6, 7) = "bpawn": chessboard$(6, 8) = "bbishop" chessboard$(7, 7) = "bpawn": chessboard$(7, 8) = "bknight" chessboard$(8, 7) = "bpawn": chessboard$(8, 8) = "brook" chessboard$(4, 4) = "wpawn" chessboard$(2, 4) = "wbishop" chessboard$(6, 4) = "wqueen" chessboard$(7, 6) = "bbishop" END SUB SUB ElegxosNomimotitas (ENSkakiera() AS STRING, checkForDanger AS INTEGER, startColumn AS INTEGER, startRank AS INTEGER, finishColumn AS INTEGER, finishRank AS INTEGER, MovingPieceEN AS STRING) 'Some GREEK: Skakiera in Greek means "chessboard". NomimotitaEN in Greek means "legality". 'This SUB checks the legality of the moves enetered by the player or thought by the computer DIM ProsorinoKommatiEN AS STRING DIM NomimotitaEN NomimotitaEN = 1 'Set legality (= Nomimotita in Greek) to TRUE. If a problem is found then it will be set to FALSE. IF (debugMode = 1) THEN PRINT "" PRINT "--------------- DEBUG MESSAGE ---------------" PRINT "ElegxosNomimotitas CALLED" PRINT "" PRINT "Start column: " + STR$(startColumn) PRINT "Start rank : " + STR$(startRank) PRINT "End column : " + STR$(finishColumn) PRINT "End rank : " + STR$(finishRank) PRINT "" PRINT "Moving piece: " + MovingPieceEN$ PRINT "ENSkakiera(1,1) = " + ENSkakiera(1, 1) PRINT "ENSkakiera(1,2) = " + ENSkakiera(1, 2) PRINT "" PRINT "playerColor$ = " + playerColor$ PRINT "---------------------------------------------" PRINT "" INPUT a$ END IF 'If player moves a different colour piece then move is illegal IF whoPlays$ = "Human" THEN IF MID$(playerColor$, 1, 1) <> MID$(ENSkakiera$(startColumn, startRank), 1, 1) THEN NomimotitaEN = 0 END IF IF whoPlays$ = "HY" THEN IF MID$(playerColor$, 1, 1) = MID$(ENSkakiera$(startColumn, startRank), 1, 1) THEN NomimotitaEN = 0 END IF ' ------------------------------------ ROOK ------------------------------------ IF (MovingPieceEN$ = "wrook" OR MovingPieceEN$ = "brook") THEN IF debugMode = 1 THEN PRINT "Nomimotita = " + STR$(NomimotitaEN) 'Check correctness of move (Rook only moves in lines) IF ((startColumn <> finishColumn) AND (startRank <> finishRank)) THEN NomimotitaEN = 0 IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Checkpoint ROOK-0" 'Check if the Rook moves beyond the limits of the chessboard IF ((finishColumn < 1) OR (finishRank < 1)) THEN NomimotitaEN = 0 IF ((finishColumn > 8) OR (finishRank > 8)) THEN NomimotitaEN = 0 IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Checkpoint ROOK-1" 'Check if another piece is between the current and the target square 'Horizontal movement IF (startColumn > finishColumn) AND (startRank = finishRank) THEN FOR J = startColumn TO finishColumn STEP -1 IF (J <> startColumn) AND (J <> finishColumn) AND ENSkakiera(J, startRank) <> "" THEN NomimotitaEN = 0 NEXT J END IF IF (startColumn < finishColumn) AND (startRank = finishRank) THEN FOR J = startColumn TO finishColumn IF (J <> startColumn) AND (J <> finishColumn) AND ENSkakiera(J, startRank) <> "" THEN NomimotitaEN = 0 NEXT J END IF IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Checkpoint ROOK-2" 'Vertical movement IF (startColumn = finishColumn) AND (startRank > finishRank) THEN FOR J = startRank TO finishRank STEP -1 IF (J <> startRank) AND (J <> finishRank) AND ENSkakiera(startColumn, J) <> "" THEN NomimotitaEN = 0 NEXT J END IF IF (startColumn = finishColumn) AND (startRank < finishRank) THEN FOR J = startRank TO finishRank IF (J <> startRank) AND (J <> finishRank) AND ENSkakiera(startColumn, J) <> "" THEN NomimotitaEN = 0 NEXT J END IF IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Checkpoint ROOK-3" 'If the start square is the same as the destination... IF startColumn = finishColumn AND startRank = finishRank THEN NomimotitaEN = 0 IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Checkpoint ROOK-4" 'Check if a piece of the same colour is at the destination square IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = MID$(ENSkakiera$(startColumn, startRank), 1, 1) THEN NomimotitaEN = 0 IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Checkpoint ROOK-5": 'INPUT a$ END IF ' ------------------------------------ BISHOP ------------------------------------ IF (MovingPieceEN$ = "wbishop" OR MovingPieceEN$ = "bbishop") THEN 'Check correctness of move (Bishop only moves in diagonals) IF ((startRank = finishRank) OR (startColumn = finishColumn)) THEN NomimotitaEN = 0 IF (ABS(startColumn - finishColumn) <> ABS(startRank - finishRank)) THEN NomimotitaEN = 0 'IF MovingPieceEN$ = "wbishop" AND startColumn = 2 AND startRank = 4 AND finishColumn = 5 AND finishRank = 7 THEN ' PRINT "Checkpoint 1 - Nomimotita = " + STR$(NomimotitaEN) ' INPUT C$ 'END IF IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Bishop - Checkpoint A" 'Check if the piece moves beyond the limits of the chessboard IF ((finishColumn < 1) OR (finishRank < 1)) THEN NomimotitaEN = 0 IF ((finishColumn > 8) OR (finishRank > 8)) THEN NomimotitaEN = 0 'IF MovingPieceEN$ = "wbishop" AND startColumn = 2 AND startRank = 4 AND finishColumn = 5 AND finishRank = 7 THEN ' PRINT "Checkpoint 2 - Nomimotita = " + STR$(NomimotitaEN) ' INPUT C$ 'END IF IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Bishop - Checkpoint B" 'Check if another piece is between the current and the target square 'Move down-left IF (finishColumn < startColumn) AND (finishRank < startRank) THEN FOR I = 1 TO 7 IF (startColumn - I) > 0 AND (startRank - I) > 0 THEN IF (startColumn - I) > finishColumn AND (startRank - I) > finishRank AND ENSkakiera(startColumn - I, startRank - I) <> "" THEN NomimotitaEN = 0 END IF NEXT I END IF 'Move up-left IF (finishColumn < startColumn) AND (finishRank > startRank) THEN FOR I = 1 TO 7 IF (startColumn - I) > 0 AND (startRank + I) < 9 THEN IF (startColumn - I) > finishColumn AND (startRank + I) < finishRank AND ENSkakiera(startColumn - I, startRank + I) <> "" THEN NomimotitaEN = 0 END IF NEXT I END IF 'IF MovingPieceEN$ = "wbishop" AND startColumn = 2 AND startRank = 4 AND finishColumn = 5 AND finishRank = 7 THEN ' PRINT "Checkpoint 3 - Nomimotita = " + STR$(NomimotitaEN) ' INPUT C$ 'END IF 'Move up-right IF (finishColumn > startColumn) AND (finishRank > startRank) THEN FOR I = 1 TO 7 IF (startColumn + I) < 9 AND (startRank + I) < 9 THEN IF (startColumn + I) < finishColumn AND (startRank + I) < finishRank AND ENSkakiera(startColumn + I, startRank + I) <> "" THEN NomimotitaEN = 0 'IF MovingPieceEN$ = "wbishop" AND startColumn = 2 AND startRank = 4 AND finishColumn = 5 AND finishRank = 7 THEN ' PRINT "Checkpoint 3.0 - Nomimotita = " + STR$(NomimotitaEN) + " (i = " + STR$(I) + ")" ' INPUT C$ 'END IF END IF NEXT I END IF 'IF MovingPieceEN$ = "wbishop" AND startColumn = 2 AND startRank = 4 AND finishColumn = 5 AND finishRank = 7 THEN ' PRINT "Checkpoint 3.1 - Nomimotita = " + STR$(NomimotitaEN) ' INPUT C$ 'END IF 'Move down-right IF (finishColumn > startColumn) AND (finishRank < startRank) THEN FOR I = 1 TO 7 IF (startColumn + I) < 9 AND (startRank - I) > 0 THEN IF (startColumn + I) < finishColumn AND (startRank - I) > finishRank AND ENSkakiera(startColumn + I, startRank - I) <> "" THEN NomimotitaEN = 0 END IF NEXT I END IF 'IF MovingPieceEN$ = "wbishop" AND startColumn = 2 AND startRank = 4 AND finishColumn = 5 AND finishRank = 7 THEN ' PRINT "Checkpoint 4 - Nomimotita = " + STR$(NomimotitaEN) ' INPUT C$ 'END IF IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Bishop - Checkpoint C" 'If the start square is the same as the destination... IF startColumn = finishColumn AND startRank = finishRank THEN NomimotitaEN = 0 IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Bishop - Checkpoint D" 'Check if a piece of the same colour is at the destination square IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = MID$(ENSkakiera$(startColumn, startRank), 1, 1) THEN NomimotitaEN = 0 'IF MovingPieceEN$ = "wbishop" AND startColumn = 2 AND startRank = 4 AND finishColumn = 5 AND finishRank = 7 THEN ' PRINT "Checkpoint 5 - Nomimotita = " + STR$(NomimotitaEN) ' INPUT C$ 'END IF IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Bishop - Checkpoint E": 'INPUT a$ END IF ' ------------------------------------ QUEEN ------------------------------------ IF (MovingPieceEN$ = "wqueen" OR MovingPieceEN$ = "bqueen") THEN 'Check correctness of move (Queen moves in diagonals and in lines) 'Different check depending on whether the queen moves in lines or not. 'Checks are a combination of the above checks for Rook and Bishop. IF (startRank <> finishRank) AND (startColumn <> finishColumn) THEN IF (ABS(startColumn - finishColumn) <> ABS(startRank - finishRank)) THEN NomimotitaEN = 0 END IF IF debugMode = 1 THEN PRINT "Queen - Entered check legality SUB": INPUT a$ IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Queen - Checkpoint Null" 'Check if the piece moves beyond the limits of the chessboard IF ((finishColumn < 1) OR (finishRank < 1)) THEN NomimotitaEN = 0 IF ((finishColumn > 8) OR (finishRank > 8)) THEN NomimotitaEN = 0 'Check if another piece is between the current and the target square 'Diagonal movement 'Move down-left IF (finishColumn < startColumn) AND (finishRank < startRank) THEN FOR I = 1 TO 7 IF (startColumn - I) > 0 AND (startRank - I) > 0 THEN IF (startColumn - I) > finishColumn AND (startRank - I) > finishRank AND ENSkakiera(startColumn - I, startRank - I) <> "" THEN NomimotitaEN = 0 END IF NEXT I END IF 'Move up-left IF (finishColumn < startColumn) AND (finishRank > startRank) THEN FOR I = 1 TO 7 IF (startColumn - I) > 0 AND (startRank + I) < 9 THEN IF (startColumn - I) > finishColumn AND (startRank + I) < finishRank AND ENSkakiera(startColumn - I, startRank + I) <> "" THEN NomimotitaEN = 0 END IF NEXT I END IF 'Move up-right IF (finishColumn > startColumn) AND (finishRank > startRank) THEN FOR I = 1 TO 7 IF (startColumn + I) < 9 AND (startRank + I) < 9 THEN IF (startColumn + I) < finishColumn AND (startRank + I) < finishRank AND ENSkakiera(startColumn + I, startRank + I) <> "" THEN NomimotitaEN = 0 END IF NEXT I END IF 'Move down-right IF (finishColumn > startColumn) AND (finishRank < startRank) THEN FOR I = 1 TO 7 IF (startColumn + I) < 9 AND (startRank - I) > 0 THEN IF (startColumn + I) < finishColumn AND (startRank - I) > finishRank AND ENSkakiera(startColumn + I, startRank - I) <> "" THEN NomimotitaEN = 0 END IF NEXT I END IF IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Queen - Checkpoint 0" 'Horizontal movement IF (startColumn > finishColumn) AND (startRank = finishRank) THEN FOR J = startColumn TO finishColumn STEP -1 IF (J <> startColumn) AND (J <> finishColumn) AND ENSkakiera(J, startRank) <> "" THEN NomimotitaEN = 0 NEXT J END IF IF (startColumn < finishColumn) AND (startRank = finishRank) THEN FOR J = startColumn TO finishColumn IF (J <> startColumn) AND (J <> finishColumn) AND ENSkakiera(J, startRank) <> "" THEN NomimotitaEN = 0 NEXT J END IF IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Queen - Checkpoint 1" IF debugMode = 1 THEN PRINT "startColumn = " + STR$(startColumn) + " - finishColumn = " + STR$(finishColumn) 'Vertical movement IF (startColumn = finishColumn) AND (startRank > finishRank) THEN FOR J = startRank TO finishRank STEP -1 IF (J <> startRank) AND (J <> finishRank) AND ENSkakiera(startColumn, J) <> "" THEN NomimotitaEN = 0 NEXT J END IF IF (startColumn = finishColumn) AND (startRank < finishRank) THEN FOR J = startRank TO finishRank IF (J <> startRank) AND (J <> finishRank) AND ENSkakiera(startColumn, J) <> "" THEN NomimotitaEN = 0 NEXT J END IF IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Queen - Checkpoint 2" 'If the start square is the same as the destination... IF startColumn = finishColumn AND startRank = finishRank THEN NomimotitaEN = 0 'Check if a piece of the same colour is at the destination square IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = MID$(ENSkakiera$(startColumn, startRank), 1, 1) THEN NomimotitaEN = 0 IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Queen - Checkpoint 3": INPUT a$ END IF ' ------------------------------------ KING ------------------------------------ IF (MovingPieceEN$ = "wking" OR MovingPieceEN$ = "bking") THEN 'Check correctness of move (King moves in diagonals and in lines, but only for one square) 'Different check depending on whether the queen moves in lines or not. 'Checks are the same as the checks for the Queen, with the addition of a check that King only moves one square. IF (startRank <> finishRank) AND (startColumn <> finishColumn) THEN IF (ABS(startColumn - finishColumn) <> ABS(startRank - finishRank)) THEN NomimotitaEN = 0 END IF 'Castling not supported 'Check if the King moves more than one square IF ABS(startColumn - finishColumn) > 1 OR ABS(startRank - finishRank) > 1 THEN NomimotitaEN = 0 'Check if the piece moves beyond the limits of the chessboard IF ((finishColumn < 1) OR (finishRank < 1)) THEN NomimotitaEN = 0 IF ((finishColumn > 8) OR (finishRank > 8)) THEN NomimotitaEN = 0 'If the start square is the same as the destination... IF startColumn = finishColumn AND startRank = finishRank THEN NomimotitaEN = 0 'Check if a piece of the same colour is at the destination square IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = MID$(ENSkakiera$(startColumn, startRank), 1, 1) THEN NomimotitaEN = 0 END IF ' ------------------------------------ KNIGHT ------------------------------------ IF (MovingPieceEN$ = "wknight" OR MovingPieceEN$ = "bknight") THEN NomimotitaEN = 0 IF (finishColumn = startColumn + 2) AND (finishRank = startRank + 1) THEN NomimotitaEN = 1 IF (finishColumn = startColumn + 2) AND (finishRank = startRank - 1) THEN NomimotitaEN = 1 IF (finishColumn = startColumn + 1) AND (finishRank = startRank + 2) THEN NomimotitaEN = 1 IF (finishColumn = startColumn + 1) AND (finishRank = startRank - 2) THEN NomimotitaEN = 1 IF (finishColumn = startColumn - 1) AND (finishRank = startRank + 2) THEN NomimotitaEN = 1 IF (finishColumn = startColumn - 1) AND (finishRank = startRank - 2) THEN NomimotitaEN = 1 IF (finishColumn = startColumn - 2) AND (finishRank = startRank + 1) THEN NomimotitaEN = 1 IF (finishColumn = startColumn - 2) AND (finishRank = startRank - 1) THEN NomimotitaEN = 1 'Check if the piece moves beyond the limits of the chessboard IF ((finishColumn < 1) OR (finishRank < 1)) THEN NomimotitaEN = 0 IF ((finishColumn > 8) OR (finishRank > 8)) THEN NomimotitaEN = 0 'Check if a piece of the same colour is at the destination square IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = MID$(ENSkakiera$(startColumn, startRank), 1, 1) THEN NomimotitaEN = 0 'If the start square is the same as the destination... IF startColumn = finishColumn AND startRank = finishRank THEN NomimotitaEN = 0 END IF ' ------------------------------------ PAWN ------------------------------------ IF (MovingPieceEN$ = "wpawn" OR MovingPieceEN$ = "bpawn") THEN NomimotitaEN = 0 IF MovingPieceEN$ = "wpawn" THEN IF (finishColumn = startColumn) AND (finishRank = startRank + 1) THEN NomimotitaEN = 1 IF (finishColumn = startColumn - 1) AND (finishRank = startRank + 1) THEN IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = "b" THEN NomimotitaEN = 1 END IF IF (finishColumn = startColumn + 1) AND (finishRank = startRank + 1) THEN IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = "b" THEN NomimotitaEN = 1 END IF END IF IF debugMode = 1 THEN PRINT "Pawn - Checkpoint Null: Nomimotita = " + STR$(NomimotitaEN) IF MovingPieceEN$ = "bpawn" THEN IF (finishColumn = startColumn) AND (finishRank = startRank - 1) THEN NomimotitaEN = 1 IF (finishColumn = startColumn - 1) AND (finishRank = startRank - 1) THEN IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = "w" THEN NomimotitaEN = 1 END IF IF (finishColumn = startColumn + 1) AND (finishRank = startRank - 1) THEN IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = "w" THEN NomimotitaEN = 1 END IF END IF 'Moving two squares IF MovingPieceEN$ = "wpawn" AND startRank = 2 AND finishRank = 4 AND startColumn = finishColumn AND ENSkakiera$(startColumn, 3) = "" AND ENSkakiera$(startColumn, 4) = "" THEN NomimotitaEN = 1 IF MovingPieceEN$ = "bpawn" AND startRank = 7 AND finishRank = 5 AND startColumn = finishColumn AND ENSkakiera$(startColumn, 6) = "" AND ENSkakiera$(startColumn, 5) = "" THEN NomimotitaEN = 1 IF debugMode = 1 THEN PRINT "Pawn - Checkpoint 1: Nomimotita = " + STR$(NomimotitaEN) 'En passant not supported 'Promotion not supported 'Check if the piece moves beyond the limits of the chessboard IF ((finishColumn < 1) OR (finishRank < 1)) THEN NomimotitaEN = 0 IF ((finishColumn > 8) OR (finishRank > 8)) THEN NomimotitaEN = 0 'Check if a piece of the same colour is at the destination square IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = MID$(ENSkakiera$(startColumn, startRank), 1, 1) THEN NomimotitaEN = 0 IF debugMode = 1 THEN PRINT "Pawn - Checkpoint 2: Nomimotita = " + STR$(NomimotitaEN) 'Check if a piece of any colour is at the destination square IF (finishColumn <> startColumn) THEN IF MovingPieceEN$ = "wpawn" AND MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = "w" THEN NomimotitaEN = 0 IF MovingPieceEN$ = "bpawn" AND MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = "b" THEN NomimotitaEN = 0 END IF IF (finishColumn = startColumn) THEN IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) <> "" THEN NomimotitaEN = 0 END IF IF debugMode = 1 THEN PRINT "Pawn - Checkpoint 3: Nomimotita = " + NomimotitaEN$: INPUT a$ 'If the start square is the same as the destination... IF startColumn = finishColumn AND startRank = finishRank THEN NomimotitaEN = 0 END IF IF (debugMode = 1) THEN PRINT "" PRINT "--------------- DEBUG MESSAGE ---------------" PRINT "startColumn = " + STR$(startColumn) PRINT "startRank = " + STR$(startRank) PRINT "finishColumn = " + STR$(finishColumn) PRINT "finishRank = " + STR$(finishRank) PRINT "ENSkakiera$(startColumn, startRank) = " + ENSkakiera$(startColumn, startRank) PRINT "ENSkakiera$(finishColumn, finishRank) = " + ENSkakiera$(finishColumn, finishRank) PRINT "" PRINT "NomimotitaEN = " + STR$(NomimotitaEN) PRINT "--------------- DEBUG MESSAGE ---------------" PRINT "" INPUT a$ END IF Nomimotita = NomimotitaEN END SUB SUB countScore positionScore = 0 FOR I = 1 TO 8 FOR J = 1 TO 8 IF chessboard$(I, J) = "wpawn" THEN positionScore = positionScore + 1 IF chessboard$(I, J) = "wrook" THEN positionScore = positionScore + 5 IF chessboard$(I, J) = "wknight" THEN positionScore = positionScore + 3 IF chessboard$(I, J) = "wbishop" THEN positionScore = positionScore + 3 IF chessboard$(I, J) = "wqueen" THEN positionScore = positionScore + 9 IF chessboard$(I, J) = "wking" THEN positionScore = positionScore + 100 IF chessboard$(I, J) = "bpawn" THEN positionScore = positionScore - 1 IF chessboard$(I, J) = "brook" THEN positionScore = positionScore - 5 IF chessboard$(I, J) = "bknight" THEN positionScore = positionScore - 3 IF chessboard$(I, J) = "bbishop" THEN positionScore = positionScore - 3 IF chessboard$(I, J) = "bqueen" THEN positionScore = positionScore - 9 IF chessboard$(I, J) = "bking" THEN positionScore = positionScore - 100 NEXT J NEXT I IF (debugMode = 1) THEN PRINT "Position Score = " + STR$(positionScore) END SUB SUB DRAWBOARD 'Test 'BO%(5, 3) = 3: BO%(8, 3) = -3 FOR k = 1 TO 8 FOR h = 1 TO 8 BO%(k, h) = 0 NEXT h NEXT k FOR k = 1 TO 8 FOR h = 1 TO 8 IF k = 1 THEN tr = 8 IF k = 2 THEN tr = 7 IF k = 3 THEN tr = 6 IF k = 4 THEN tr = 5 IF k = 5 THEN tr = 4 IF k = 6 THEN tr = 3 IF k = 7 THEN tr = 2 IF k = 8 THEN tr = 1 IF chessboard$(k, h) = "bpawn" THEN BO%(tr, h) = -1 IF chessboard$(k, h) = "wpawn" THEN BO%(tr, h) = 1 IF chessboard$(k, h) = "bknight" THEN BO%(tr, h) = -2 IF chessboard$(k, h) = "wknight" THEN BO%(tr, h) = 2 IF chessboard$(k, h) = "bbishop" THEN BO%(tr, h) = -3 IF chessboard$(k, h) = "wbishop" THEN BO%(tr, h) = 3 IF chessboard$(k, h) = "brook" THEN BO%(tr, h) = -4 IF chessboard$(k, h) = "wrook" THEN BO%(tr, h) = 4 IF chessboard$(k, h) = "bqueen" THEN BO%(tr, h) = -5 IF chessboard$(k, h) = "wqueen" THEN BO%(tr, h) = 5 IF chessboard$(k, h) = "bking" THEN BO%(tr, h) = -6 IF chessboard$(k, h) = "wking" THEN BO%(tr, h) = 6 NEXT h NEXT k '************************************************************************ ' DRAW THE BOARD AND THE PIECES ' 'MAKE-EGA - Define, test and save EGA (640 x 350 x 16) chess graphic pieces 'Ed Parry 'Started: 05-14-1991 'Updated: 06-25-1994 'MODIFIED BY THOMAS MCBURNEY FOR DEEP BASIC 8 FEB 2003 '************************************************************************* DRAWTHEBOARD: ' STATIC 'draws checkered chessboard 'Each square height and width high = 38 'square pixels height DEFAULT=40 WIDE = 45 'square pixels wide DEFAULT=56 'starting board positions - adjust for video modes hs = (640 \ 2) - ((WIDE * 6) + 38) 'board horizontal vertical position he = hs + (8 * WIDE) 'horz end vs = 30 'DEFAULT=10 - board starting vertical postion ve = vs + (8 * high) sbc = 15 'square border color lsc = 7 'lite sqr color dsc = 2 'dark sqr color 'board line matrix h = hs FOR I = vs TO ve STEP high 'horizontal lines LINE (hs, I)-(he, I), sbc 'vertical lines LINE (h, vs)-(h, ve), sbc h = h + WIDE NEXT I 'use line to fill each board square FOR j = vs + 1 TO ve - 1 STEP high FOR I = hs + 1 TO he - 1 STEP WIDE 'horizontal lines LINE (I, j)-(I + WIDE - 2, j + high - 2), lsc, BF SWAP lsc, dsc NEXT I SWAP lsc, dsc NEXT j COLOR 7 'Huo Chess flip% = 1 IF flip% = 0 THEN LOCATE 2, 4: PRINT " a b c d e f g h " IF flip% = 1 THEN LOCATE 2, 4: PRINT " h g f e d c b a " 'Print the numbers FOR Y = 1 TO 8 IF Y = 1 THEN YY = 4 IF Y = 2 THEN YY = 7 IF Y = 3 THEN YY = 10 IF Y = 4 THEN YY = 12 IF Y = 5 THEN YY = 15 IF Y = 6 THEN YY = 18 IF Y = 7 THEN YY = 20 IF Y = 8 THEN YY = 23 IF flip% = 0 THEN LOCATE YY, 49: PRINT MID$(STR$(9 - Y), 2, 1) IF flip% = 1 THEN LOCATE YY, 49: PRINT MID$(STR$(Y), 2, 1) NEXT COLOR 1 LINE (455, 30)-(535, 30) LINE (425, 10)-(565, 37), , B SHOWPIECES: 'White on any = Put blot OR, put piece XOR, put blot XOR 'Black on any = Put blot OR, put piece XOR high = 38 'square pixels height DEFAULT=40 WIDE = 45 'square pixels wide DEFAULT=56 vof = 32 'reset vert offset DEFAULT=14 hof = 17 PIECEOFFSET = 0 BLOTOFFSET = 2400 'put em up to test! FOR YY = 1 TO 8 FOR XX = 1 TO 8 IF BO%(XX, YY) <> 0 THEN P% = ABS(BO%(XX, YY)) FOR X = 0 TO 399 PIECEOFFSET = (400 * P%) - 400 BLOTOFFSET = ((400 * P%) - 400) + 2400 Gpiece(X) = GraphicImage(PIECEOFFSET + X) blot(X) = GraphicImage(BLOTOFFSET + X) NEXT X X1 = XX Y1 = YY IF flip% = 1 THEN X1 = 9 - XX: Y1 = 9 - YY IF BO%(XX, YY) > 0 THEN 'white piece PUT (hof + (WIDE * X1) - WIDE, vof + (38 * Y1) - 38), blot(), OR PUT (hof + (WIDE * X1) - WIDE, vof + (38 * Y1) - 38), Gpiece(), XOR PUT (hof + (WIDE * X1) - WIDE, vof + (38 * Y1) - 38), blot(), XOR END IF IF BO%(XX, YY) < 0 THEN 'BLACK piece PUT (hof + (WIDE * X1) - WIDE, vof + (38 * Y1) - 38), blot(), OR PUT (hof + (WIDE * X1) - WIDE, vof + (38 * Y1) - 38), Gpiece(), XOR END IF END IF NEXT NEXT END SUB SUB HumanMove1 (HM1Skakiera() AS STRING) 'Scan the chessboard... FOR I = 1 TO 8 FOR J = 1 TO 8 'If you find a piece of the human... IF ((MID$(HM1Skakiera$(I, J), 1, 1) = "w" AND playerColor$ = "w") OR (MID$(HM1Skakiera$(I, J), 1, 1) = "b" AND playerColor$ = "b")) THEN IF debugMode = 1 THEN PRINT "Inside Human level 1 move - Checkpoint A" 'Scan all possible destination squares... FOR ii = 1 TO 8 FOR jj = 1 TO 8 startingColumnHM1 = I startingRankHM1 = J finishingColumnHM1 = ii finishingRankHM1 = jj MovingPieceHM1$ = HM1Skakiera$(I, J) ProsorinoKommatiHM1$ = HM1Skakiera$(ii, jj) 'Check legality of the move entered whoPlays$ = "Human" CALL ElegxosNomimotitas(HM1Skakiera$(), 0, startingColumnHM1, startingRankHM1, finishingColumnHM1, finishingRankHM1, MovingPieceHM1$) whoPlays$ = "HY" IF debugMode = 1 THEN PRINT "" PRINT "NEW MOVE ANALYZED: " + STR$(startingColumnHM1) + STR$(startingRankHM1) + " -> " + STR$(finishingColumnHM1) + STR$(finishingRankHM1) PRINT "Legality of the move analyzed: " + STR$(Nomimotita) 'IF HM1Skakiera$(6, 7) = "wqueen" AND startingColumnHM1 = 5 AND startingRankHM1 = 8 AND finishingColumnHM1 = 6 AND finishingRankHM1 = 7 THEN ' PRINT "" ' PRINT "KING MOVE ANALYZED: " + STR$(startingColumnHM1) + STR$(startingRankHM1) + " -> " + STR$(finishingColumnHM1) + STR$(finishingRankHM1) ' PRINT "What is in f7: " + HM1Skakiera$(6, 7) ' PRINT "Legality of the move analyzed: " + STR$(Nomimotita) ' INPUT A$ 'END IF END IF 'If move is legal, then do the move and present it in the chessbooard IF Nomimotita = 1 THEN 'Do the move HM1Skakiera$(finishingColumnHM1, finishingRankHM1) = HM1Skakiera$(startingColumnHM1, startingRankHM1) HM1Skakiera$(startingColumnHM1, startingRankHM1) = "" 'Count the score of the move CALL countScore IF debugMode = 1 THEN PRINT "" PRINT "NodeLevel_0_count = " + STR$(NodeLevel_0_count) PRINT "NodeLevel_1_count = " + STR$(NodeLevel_1_count) PRINT "NodeLevel_2_count = " + STR$(NodeLevel_2_count): INPUT A$ END IF '-------------- MinMax -------------- 'Store scores NodesAnalysis1(NodeLevel_1_count, 1) = positionScore ' Store parents NodesAnalysis1(NodeLevel_1_count, 2) = NodeLevel_0_count 'Store the move NodesMoves1$(NodeLevel_1_count) = NodesMoves0$(NodeLevel_0_count) + " , " + STR$(startingColumnHM1) + STR$(startingRankHM1) + " -> " + STR$(finishingColumnHM1) + STR$(finishingRankHM1) CALL ComputerMove2(HM1Skakiera$()) 'Undo the move HM1Skakiera$(startingColumnHM1, startingRankHM1) = MovingPieceHM1$ HM1Skakiera$(finishingColumnHM1, finishingRankHM1) = ProsorinoKommatiHM1$ '-------------- MinMax -------------- 'Increase node count NodeLevel_1_count = NodeLevel_1_count + 1 END IF NEXT jj NEXT ii END IF NEXT J NEXT I END SUB SUB ComputerMove2 (CM2Skakiera() AS STRING) 'Scan the chessboard... FOR I = 1 TO 8 FOR J = 1 TO 8 IF debugMode = 1 THEN PRINT "NodeLevel_2_count (Begin ComputerMove2) = " + STR$(NodeLevel_2_count) IF NodeLevel_2_count < 0 THEN PRINT "Now 1": INPUT CheckpointA$ END IF 'If you find a piece of the computer... IF ((MID$(CM2Skakiera$(I, J), 1, 1) = "w" AND playerColor$ = "b") OR (MID$(CM2Skakiera$(I, J), 1, 1) = "b" AND playerColor$ = "w")) THEN IF debugMode = 1 THEN PRINT "Inside Computer level 2 move - Checkpoint A" 'Scan all possible destination squares... FOR ii = 1 TO 8 FOR jj = 1 TO 8 startingColumnCM2 = I startingRankCM2 = J finishingColumnCM2 = ii finishingRankCM2 = jj MovingPieceCM2$ = CM2Skakiera$(I, J) ProsorinoKommatiCM2$ = CM2Skakiera$(ii, jj) 'Check legality of the move entered CALL ElegxosNomimotitas(CM2Skakiera$(), 0, startingColumnCM2, startingRankCM2, finishingColumnCM2, finishingRankCM2, MovingPieceCM2$) IF debugMode = 1 THEN PRINT "" PRINT "NEW MOVE ANALYZED: " + STR$(startingColumnCM2) + STR$(startingRankCM2) + " -> " + STR$(finishingColumnCM2) + STR$(finishingRankCM2) PRINT "Legality of the move analyzed: " + STR$(Nomimotita) IF NodeLevel_2_count < 0 THEN PRINT "Now 2": INPUT CheckpointA$ END IF 'If move is legal, then do the move and present it in the chessbooard IF Nomimotita = 1 THEN 'Do the move CM2Skakiera$(finishingColumnCM2, finishingRankCM2) = CM2Skakiera$(startingColumnCM2, startingRankCM2) CM2Skakiera$(startingColumnCM2, startingRankCM2) = "" 'Count the score of the move CALL countScore IF debugMode = 1 THEN PRINT "" PRINT "NodeLevel_0_count = " + STR$(NodeLevel_0_count) PRINT "NodeLevel_1_count = " + STR$(NodeLevel_1_count) PRINT "NodeLevel_2_count = " + STR$(NodeLevel_2_count) IF NodeLevel_2_count < 0 THEN PRINT "Now 3": INPUT CheckpointA$ END IF '-------------- MinMax -------------- 'Store scores NodesAnalysis2(NodeLevel_2_count, 1) = positionScore ' Store parents NodesAnalysis2(NodeLevel_2_count, 2) = NodeLevel_1_count 'Store the move NodesMoves1$(NodeLevel_2_count) = NodesMoves1$(NodeLevel_1_count) + " , " + STR$(startingColumnCM2) + STR$(startingRankCM2) + " -> " + STR$(finishingColumnCM2) + STR$(finishingRankCM2) IF debugMode = 1 THEN IF NodeLevel_2_count < 0 THEN PRINT "Now 4": INPUT CheckpointA$ IF NodeLevel_2_count = 0 THEN PRINT "Now 4.1": INPUT CheckpointA$ IF NodeLevel_1_count = 1 THEN PRINT "Now 4.3": PRINT "NodesAnalysis2(NodeLevel_2_count, 2) = " + STR$(NodesAnalysis2(NodeLevel_2_count, 2)): INPUT CheckpointA$ IF NodeLevel_1_count = 0 THEN PRINT "Now 4.4 - NodeLevel_2_count = " + STR$(NodeLevel_2_count): INPUT CheckpointA$ END IF 'If the score is better than the existing best score, then this is the best move now (and the best score) IF ((playerColor$ = "b" AND positionScore >= bestPositionScore) OR (playerColor$ = "w" AND positionScore <= bestPositionScore)) THEN bestStartingRank = startingRank bestStartingColumn = startingColumn bestFinishingRank = finishingRank bestFinishingColumn = finishingColumn bestPositionScore = positionScore END IF 'Undo the move CM2Skakiera$(startingColumnCM2, startingRankCM2) = MovingPieceCM2$ CM2Skakiera$(finishingColumnCM2, finishingRankCM2) = ProsorinoKommatiCM2$ IF debugMode = 1 THEN PRINT "NodeLevel_2_count (ComputerMove2 Check 2) = " + STR$(NodeLevel_2_count) IF NodeLevel_2_count < 0 THEN PRINT "Now 6": INPUT CheckpointA$ END IF '-------------- MinMax -------------- 'Increase node count NodeLevel_2_count = NodeLevel_2_count + 1 IF debugMode = 1 THEN PRINT "NodeLevel_2_count (End ComputerMove2) = " + STR$(NodeLevel_2_count) IF NodeLevel_2_count < 0 THEN PRINT "Now 7": INPUT CheckpointA$ END IF END IF NEXT jj NEXT ii END IF NEXT J NEXT I END SUB '-------------- MinMax -------------- SUB MinMax () ' ------------------------------------------------------------------------------- ' DO THE BEST MOVE FOUND ' Analyze only if possibility to eat back is not true!!! ' MessageBox.Show("Entered Best Move found area!") ' v0.990: Added the possibility_to_eat ' v0.991: Removed possibility to eat! Why not think everything? ' v0.991: Added the opening book check ' if ((possibility_to_eat_back = false) AND (possibility_to_eat = false)) ' ------------------------------------------------------------------------------- ' [MiniMax algorithm - skakos] ' MessageBox.Show("Entered checkpoint 1") ' Find node 1 move with the best score via the MiniMax algorithm. ' v0.980: Remove unsued counters. ' v0.990: Move 4 changes ' v0.991: Added counter4 again (needed if Thinking_Depth = 4) counter0 = 1 counter1 = 1 counter2 = 1 counter3 = 1 counter4 = 1 ' ------------------------------------------------------------------- ' NodesAnalysis ' ------------------------------------------------------------------- ' Nodes structure... ' [ccc, xxx, 1]: Score of node No. ccc at level xxx ' [ccc, xxx, 2]: Parent of node No. ccc at level xxx-1 ' ------------------------------------------------------------------- ' ------- LOG: Nodes before (start) ------- WRITE #1, "-------- NODES LEVEL 0 --------": WRITE #1, "" FOR counter0 = 1 TO (NodeLevel_0_count - 1) WRITE #1, "NodesAnalysis0(counter0, 1) = ", NodesAnalysis0(counter0, 1) WRITE #1, "NodesAnalysis2(counter0, 2) = ", NodesAnalysis0(counter0, 2) 'WRITE #1, "startingColumn : ", NodesAnalysis0(counter0, 3) 'WRITE #1, "startingRank : ", NodesAnalysis0(counter0, 5) 'WRITE #1, "finishingColumn : ", NodesAnalysis0(counter0, 4) 'WRITE #1, "finishingRank : ", NodesAnalysis0(counter0, 6) WRITE #1, NodesMoves0$(counter0) WRITE #1, "" NEXT counter0 WRITE #1, "-------- NODES LEVEL 1 --------": WRITE #1, "" FOR counter1 = 1 TO (NodeLevel_1_count - 1) WRITE #1, "NodesAnalysis1(counter1, 1) = ", NodesAnalysis1(counter1, 1) WRITE #1, "NodesAnalysis1(counter1, 2) = ", NodesAnalysis1(counter1, 2) WRITE #1, NodesMoves1$(counter1) WRITE #1, "" NEXT counter1 WRITE #1, "-------- NODES LEVEL 2 --------": WRITE #1, "" 'PRINT "NodeLevel_2_count = " + STR$(NodeLevel_2_count) 'PRINT "NodesAnalysis2(counter2, 1) = " + STR$(NodesAnalysis2(counter2, 1)) 'PRINT "NodesAnalysis2(counter2, 2) = " + STR$(NodesAnalysis2(counter2, 2)) 'INPUT A$ FOR counter2 = 1 TO (NodeLevel_2_count - 1) 'PRINT "NodeLevel_2_count = " + STR$(NodeLevel_2_count) 'PRINT "counter2 = " + STR$(counter2) 'PRINT "NodesAnalysis2(counter2, 1) = " + STR$(NodesAnalysis2(counter2, 1)) 'PRINT "NodesAnalysis2(counter2, 2) = " + STR$(NodesAnalysis2(counter2, 2)) WRITE #1, "NodesAnalysis2(counter2, 1) = ", NodesAnalysis2(counter2, 1) WRITE #1, "NodesAnalysis2(counter2, 2) = ", NodesAnalysis2(counter2, 2) WRITE #1, NodesMoves2$(counter2) WRITE #1, "" NEXT counter2 ' ------- LOG: Nodes before (end) ------- parentNodeAnalyzed = -999 ' Move 2 level (Computer) -- The analysis starts from here if Thinking_Depth = 2. ' Note: Start from 1! FOR counter2 = 1 TO (NodeLevel_2_count - 1) IF debugMode = 1 THEN PRINT "counter2 = " + STR$(counter2) PRINT "NodesAnalysis2(counter2, 2) = " + STR$(NodesAnalysis2(counter2, 2)) PRINT "NodesAnalysis1(NodesAnalysis2(counter2, 2), 1) = " + STR$(NodesAnalysis1(NodesAnalysis2(counter2, 2), 1)) END IF IF (NodesAnalysis2(counter2, 2) <> parentNodeAnalyzed) THEN parentNodeAnalyzed = NodesAnalysis2(counter2, 2) NodesAnalysis1(NodesAnalysis2(counter2, 2), 1) = NodesAnalysis2(counter2, 1) bestNode2 = counter2 IF debugMode = 1 THEN PRINT "parentNodeAnalyzed = " + STR$(parentNodeAnalyzed) PRINT "parentNodeAnalyzed = " + STR$(parentNodeAnalyzed) END IF bestNodes2(parentNodeAnalyzed) = counter2 END IF ' v0.991: Original: >= ' v0.991: This should depend on the colour of the computer!!! ' v0.991: Tried to fix the problem in MinMax. Node1 elements for the SAME parent of Node2 must be filled accordingly. ' We do not need to take into account the Node2 elements which are empty, thus having a score of 0 but no ' assigned move! (this is why the Best Variant text is empty in the first moves) IF playerColor$ = "w" THEN IF (NodesAnalysis2(counter2, 1) <= NodesAnalysis1(NodesAnalysis2(counter2, 2), 1)) THEN NodesAnalysis1(NodesAnalysis2(counter2, 2), 1) = NodesAnalysis2(counter2, 1) bestNode2 = counter2 bestNodes2(parentNodeAnalyzed) = counter2 END IF ELSEIF (playerColor$ = "b") THEN IF (NodesAnalysis2(counter2, 1) >= NodesAnalysis1(NodesAnalysis2(counter2, 2), 1)) THEN NodesAnalysis1(NodesAnalysis2(counter2, 2), 1) = NodesAnalysis2(counter2, 1) bestNode2 = counter2 bestNodes2(parentNodeAnalyzed) = counter2 END IF END IF NEXT counter2 ' Now the Node1 level is filled with the score data ' this is line 1 in the shape at http:'upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Minimax.svg/300px-Minimax.svg.png ' Move 1 level (Human) parentNodeAnalyzed = -999 ' Note: Start from 1! FOR counter1 = 1 TO (NodeLevel_1_count - 1) IF (NodesAnalysis1(counter1, 2) <> parentNodeAnalyzed) THEN parentNodeAnalyzed = NodesAnalysis1(counter1, 2) NodesAnalysis0(NodesAnalysis1(counter1, 2), 1) = NodesAnalysis1(counter1, 1) bestNode1 = counter1 bestNodes1(parentNodeAnalyzed) = counter1 END IF ' v0.991: Choose different based on colour! IF (playerColor$ = "w") THEN IF NodesAnalysis1(counter1, 1) >= NodesAnalysis0(NodesAnalysis1(counter1, 2), 1) THEN NodesAnalysis0(NodesAnalysis1(counter1, 2), 1) = NodesAnalysis1(counter1, 1) bestNode1 = counter1 bestNodes1(parentNodeAnalyzed) = counter1 END IF ELSEIF (playerColor$ = "b") THEN IF NodesAnalysis1(counter1, 1) <= NodesAnalysis0(NodesAnalysis1(counter1, 2), 1) THEN NodesAnalysis0(NodesAnalysis1(counter1, 2), 1) = NodesAnalysis1(counter1, 1) bestNode1 = counter1 bestNodes1(parentNodeAnalyzed) = counter1 END IF END IF NEXT counter1 ' Choose the biggest score at the Node0 level ' Check example at http:'en.wikipedia.org/wiki/Minimax#Example_2 ' This is line 0 at the shape at http:'upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Minimax.svg/300px-Minimax.svg.png ' Move 0 level (Computer) ' Initialize the score with the first score and move found ' Note: Start from 1! temp_score = NodesAnalysis0(1, 1) ' v0.992: Start from 0 also here! bestStartingColumn = NodesAnalysis0(1, 3) bestStartingRank = NodesAnalysis0(1, 5) bestFinishingColumn = NodesAnalysis0(1, 4) bestFinishingRank = NodesAnalysis0(1, 6) ' v0.992 bestNode0 = 0 'PRINT "Best move : " + STR$(bestStartingColumn) + STR$(bestStartingRank) + " -> " + STR$(bestFinishingColumn) + STR$(bestFinishingRank) 'PRINT "Best score : " + STR$(temp_score) 'INPUT A$ 'Note: Start from 1! FOR counter0 = 1 TO (NodeLevel_0_count - 1) ' v0.991: Choose different based on colour! IF (playerColor$ = "b") THEN IF (NodesAnalysis0(counter0, 1) > temp_score) THEN temp_score = NodesAnalysis0(counter0, 1) bestStartingColumn = NodesAnalysis0(counter0, 3) bestStartingRank = NodesAnalysis0(counter0, 5) bestFinishingColumn = NodesAnalysis0(counter0, 4) bestFinishingRank = NodesAnalysis0(counter0, 6) ' v0.992 bestNode0 = counter0 END IF ELSEIF (playerColor$ = "w") THEN IF NodesAnalysis0(counter0, 1) < temp_score THEN temp_score = NodesAnalysis0(counter0, 1) bestStartingColumn = NodesAnalysis0(counter0, 3) bestStartingRank = NodesAnalysis0(counter0, 5) bestFinishingColumn = NodesAnalysis0(counter0, 4) bestFinishingRank = NodesAnalysis0(counter0, 6) ' v0.992 bestNode0 = counter0 END IF END IF NEXT counter0 ' ------- LOG: Nodes after (start) ------- WRITE #2, "-------- NODES LEVEL 0 --------": WRITE #2, "" FOR counter0 = 1 TO (NodeLevel_0_count - 1) WRITE #2, "NodesAnalysis0(counter0, 1) = ", NodesAnalysis0(counter0, 1) WRITE #2, "NodesAnalysis2(counter0, 2) = ", NodesAnalysis0(counter0, 2) 'WRITE #2, "startingColumn : ", NodesAnalysis0(counter0, 3) 'WRITE #2, "startingRank : ", NodesAnalysis0(counter0, 5) 'WRITE #2, "finishingColumn : ", NodesAnalysis0(counter0, 4) 'WRITE #2, "finishingRank : ", NodesAnalysis0(counter0, 6) WRITE #2, NodesMoves0$(counter0) WRITE #2, "" NEXT counter0 WRITE #2, "-------- NODES LEVEL 1 --------": WRITE #1, "" FOR counter1 = 1 TO (NodeLevel_1_count - 1) WRITE #2, "NodesAnalysis1(counter1, 1) = ", NodesAnalysis1(counter1, 1) WRITE #2, "NodesAnalysis1(counter1, 2) = ", NodesAnalysis1(counter1, 2) WRITE #2, NodesMoves1$(counter1) WRITE #2, "" NEXT counter1 WRITE #2, "-------- NODES LEVEL 2 --------": WRITE #1, "" FOR counter2 = 1 TO (NodeLevel_2_count - 1) WRITE #2, "NodesAnalysis2(counter2, 1) = ", NodesAnalysis2(counter2, 1) WRITE #2, "NodesAnalysis2(counter2, 2) = ", NodesAnalysis2(counter2, 2) WRITE #2, NodesMoves2$(counter2) WRITE #2, "" NEXT counter2 ' ------- LOG: Nodes after (end) ------- END SUB