QB64.org Forum

Active Forums => Programs => Topic started by: STxAxTIC on January 24, 2020, 06:52:46 pm

Title: A 90% complete chess engine
Post by: STxAxTIC on January 24, 2020, 06:52:46 pm
Sup all

So back in like 2014 I got the idea to make a chess engine. The whole dream lasted a day, 90% of which I spent discovering how the chess algorithm should work. End result is a working engine that plays (the same) game against itself. This is fully deterministic - no randomness. It's got all the pieces, most of the rules, all of the mechanics, except a few things:

* This ignores castling.
* This ignores check and checkmate.
* This ignores pawn promotion.

Because of the second incompleteness, the king dies early, but no big deal. The rest is completely there. It thinks 2 or 3 moves ahead at the moment. You can see what code to un-comment to generalize this and add more fake thinking.

I think some folks might need to be reminded of the so-called chess algorithm. Computers are stupid, they have no intuition, and certainly can't play chess like a person. What the computer does, with this program being an example, is to try *every* possible move available to *every* movable piece, with each result ending in a "score" that determines if the move is any good. The score is calculated from the pieces still left after a move. So the computer needs to do this immense tallying job in order to make the decision on which piece to move... for every single move.

Anyway, consider this yet another angle to the chess tutorial. My style was still flourishing in 2014 so forgive the code... It took me all night one night.

Code: QB64: [Select]
  1. '#lang "qb"
  2.  
  3. DIM SHARED BoardState(8, 8, 10) AS STRING
  4. DIM SHARED MoveListArray(99999, 10) AS STRING
  5. DIM SHARED MoveListArraySize(10)
  6.  
  7. DECLARE FUNCTION CalculateScore (TheColorIn$, GameLayerParIn)
  8. DECLARE SUB DoAMove (TheMoveIn$, GameLayerPar1In, GameLayerPar2In)
  9. DECLARE FUNCTION FindCoordinates$ (ThePieceIn$, GameLayerParIn)
  10. DECLARE SUB GenerateMoveList (TheColorIn$, GameLayerParIn, MoveListLayerIn)
  11. DECLARE SUB ListPieceMoves (ThePieceIn$, GameLayerParIn)
  12. DECLARE SUB PrintGame (GameLayerParIn)
  13. DECLARE SUB GetRowColMovesFull (PieceNameIn$, GameLayerParIn)
  14. DECLARE SUB GetDiagMovesFull (PieceNameIn$, GameLayerParIn)
  15. DECLARE SUB GetRowColMovesSingle (PieceNameIn$, GameLayerParIn)
  16. DECLARE SUB GetDiagMovesSingle (PieceNameIn$, GameLayerParIn)
  17. DECLARE SUB GetKnightMoves (PieceNameIn$, GameLayerParIn)
  18.  
  19.  
  20. ' Initialize chess board.
  21. FOR x = 1 TO 8
  22.     FOR y = 1 TO 8 STEP 1
  23.         BoardState(x, y, 0) = "0"
  24.     NEXT
  25.  
  26. ' Place pieces in their starting positions
  27. BoardState(1, 2, 0) = "WP1" ' White Pawn
  28. BoardState(2, 2, 0) = "WP2" ' White Pawn
  29. BoardState(3, 2, 0) = "WP3" ' White Pawn
  30. BoardState(4, 2, 0) = "WP4" ' White Pawn
  31. BoardState(5, 2, 0) = "WP5" ' White Pawn
  32. BoardState(6, 2, 0) = "WP6" ' White Pawn
  33. BoardState(7, 2, 0) = "WP7" ' White Pawn
  34. BoardState(8, 2, 0) = "WP8" ' White Pawn
  35. BoardState(1, 1, 0) = "WQR" ' White Queen Rook
  36. BoardState(2, 1, 0) = "WQN" ' White Queen Knight
  37. BoardState(3, 1, 0) = "WQB" ' White Queen Bishop
  38. BoardState(4, 1, 0) = "WQQ" ' White Queen
  39. BoardState(5, 1, 0) = "WKK" ' White King
  40. BoardState(6, 1, 0) = "WKB" ' White King Bishop
  41. BoardState(7, 1, 0) = "WKN" ' White King Knight
  42. BoardState(8, 1, 0) = "WKR" ' White King Rook
  43.  
  44. BoardState(1, 7, 0) = "BP1" ' Black Pawn
  45. BoardState(2, 7, 0) = "BP2" ' Black Pawn
  46. BoardState(3, 7, 0) = "BP3" ' Black Pawn
  47. BoardState(4, 7, 0) = "BP4" ' Black Pawn
  48. BoardState(5, 7, 0) = "BP5" ' Black Pawn
  49. BoardState(6, 7, 0) = "BP6" ' Black Pawn
  50. BoardState(7, 7, 0) = "BP7" ' Black Pawn
  51. BoardState(8, 7, 0) = "BP8" ' Black Pawn
  52. BoardState(1, 8, 0) = "BQR" ' Black Queen Rook
  53. BoardState(2, 8, 0) = "BQN" ' Black Queen Knight
  54. BoardState(3, 8, 0) = "BQB" ' Black Queen Bishop
  55. BoardState(4, 8, 0) = "BQQ" ' Black Queen
  56. BoardState(5, 8, 0) = "BKK" ' Black King
  57. BoardState(6, 8, 0) = "BKB" ' Black King Bishop
  58. BoardState(7, 8, 0) = "BKN" ' Black King Knight
  59. BoardState(8, 8, 0) = "BKR" ' Black King Rook
  60.  
  61. ' Show the board and wait for key.
  62. CALL PrintGame(0)
  63. LOCATE 20, 20: PRINT "Press any key to begin..."
  64. LOCATE 20, 20: PRINT "                         "
  65.  
  66. CurrentPlayer$ = "B": CurrentOpponent$ = "W"
  67.  
  68. TotalGameCalculations = 0
  69.  
  70.     IF CurrentPlayer$ = "W" THEN
  71.         CurrentPlayer$ = "B"
  72.         CurrentOpponent$ = "W"
  73.     ELSE
  74.         CurrentPlayer$ = "W"
  75.         CurrentOpponent$ = "B"
  76.     END IF
  77.  
  78.     BestCandidateMoveIndex = -1
  79.     BestScoreDifference = -999
  80.     OriginalScoreDifference = CalculateScore(CurrentPlayer$, 0) - CalculateScore(CurrentOpponent$, 3)
  81.  
  82.     CALL GenerateMoveList(CurrentPlayer$, 0, 0) '                    Using game 0 generate a move list called 0.
  83.     FOR i = 1 TO MoveListArraySize(0)
  84.         CALL DoAMove(MoveListArray(i, 0), 0, 1) '                    Do the ith move using list 0 taking game 0 to game 1.
  85.         CALL GenerateMoveList(CurrentOpponent$, 1, 1) '              Use game 1 to generate list 1.
  86.         FOR j = 1 TO MoveListArraySize(1)
  87.             CALL DoAMove(MoveListArray(j, 1), 1, 2) '                Do the jth move using list 1 taking game 1 to game 2.
  88.             CALL GenerateMoveList(CurrentPlayer$, 2, 2) '            Use game 2 to generate list 2.
  89.             FOR k = 1 TO MoveListArraySize(2)
  90.                 CALL DoAMove(MoveListArray(k, 2), 2, 3) '            Do the kth move using list 2 taking game 2 to game 3.
  91.              
  92.                 'CALL GenerateMoveList(CurrentOpponent$, 3, 3) '     Use game 3 to generate list 3.
  93.                 'FOR m = 1 TO MoveListArraySize(3)
  94.                 'CALL DoAMove(MoveListArray(m, 3), 3, 4) '           Do the kth move using list 3 taking game 3 to game 4.
  95.  
  96.                 ' This is a very simplistic "toy model" for computing the score for a given board state.
  97.                 ' This is meant to be improved upon and is really the heart of the engine.
  98.                 WScore = CalculateScore(CurrentPlayer$, 3)
  99.                 BScore = CalculateScore(CurrentOpponent$, 3)
  100.                 ScoreDiff = WScore - BScore
  101.                 IF ScoreDiff > BestScoreDifference THEN
  102.                     BestScoreDifference = ScoreDiff
  103.                     BestCandidateMoveIndex = i
  104.                 END IF
  105.                 TotalGameCalculations = TotalGameCalculations + 1
  106.                 LOCATE 20, 20: PRINT "Mini-games tried: "; TotalGameCalculations
  107.  
  108.                 'NEXT
  109.  
  110.             NEXT
  111.         NEXT
  112.     NEXT
  113.  
  114.     IF BestScoreDifference = -999 THEN EXIT DO
  115.  
  116.     CALL DoAMove(MoveListArray(BestCandidateMoveIndex, 0), 0, 9)
  117.  
  118.     FOR x = 1 TO 8
  119.         FOR y = 1 TO 8
  120.             BoardState(x, y, 0) = BoardState(x, y, 9)
  121.         NEXT
  122.     NEXT
  123.  
  124.     CALL PrintGame(0)
  125.  
  126.  
  127. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  128.  
  129. FUNCTION CalculateScore (TheColorIn AS STRING, GameLayerParIn)
  130.     DIM TCI AS STRING
  131.     TCI = TheColorIn
  132.     GameLayerParameter = GameLayerParIn
  133.     TheScore = 0
  134.     FOR x = 1 TO 8
  135.         FOR y = 1 TO 8
  136.             c$ = BoardState(x, y, GameLayerParameter)
  137.             IF c$ <> "0" AND LEFT$(c$, 1) = TCI THEN
  138.                 SELECT CASE MID$(c$, 3, 1)
  139.                     CASE "K"
  140.                         TheScore = TheScore + 1000
  141.                     CASE "Q"
  142.                         TheScore = TheScore + 80
  143.                     CASE "B"
  144.                         TheScore = TheScore + 30
  145.                     CASE "N"
  146.                         TheScore = TheScore + 30
  147.                     CASE "R"
  148.                         TheScore = TheScore + 50
  149.                     CASE ELSE
  150.                         TheScore = TheScore + 10
  151.                 END SELECT
  152.             END IF
  153.         NEXT
  154.     NEXT
  155.     CalculateScore = TheScore
  156.  
  157. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  158.  
  159. SUB DoAMove (TheMoveIn AS STRING, GameLayerPar1In, GameLayerPar2In)
  160.     DIM TheMove AS STRING
  161.     TheMove = TheMoveIn
  162.     GameLayerParameter1 = GameLayerPar1In
  163.     GameLayerParameter2 = GameLayerPar2In
  164.     ThePiece$ = LEFT$(TheMove, 3)
  165.     OldLocation$ = FindCoordinates$(ThePiece$, GameLayerParameter1)
  166.     OldXLoc = VAL(LEFT$(OldLocation$, 1))
  167.     OldYLoc = VAL(RIGHT$(OldLocation$, 1))
  168.     NewLocation$ = RIGHT$(TheMove, 2)
  169.     NewXLoc = VAL(LEFT$(NewLocation$, 1))
  170.     NewYLoc = VAL(RIGHT$(NewLocation$, 1))
  171.     FOR x = 1 TO 8
  172.         FOR y = 1 TO 8
  173.             BoardState(x, y, GameLayerParameter2) = BoardState(x, y, GameLayerParameter1)
  174.         NEXT
  175.     NEXT
  176.     BoardState(OldXLoc, OldYLoc, GameLayerParameter2) = "0"
  177.     BoardState(NewXLoc, NewYLoc, GameLayerParameter2) = ThePiece$
  178.  
  179. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  180.  
  181. FUNCTION FindCoordinates$ (ThePieceIn AS STRING, GameLayerParIn)
  182.     DIM ThePiece AS STRING
  183.     ThePiece = ThePieceIn
  184.     GameLayerParameter = GameLayerParIn
  185.     Temp$ = "-1"
  186.     FOR x = 1 TO 8
  187.         FOR y = 8 TO 1 STEP -1
  188.             IF BoardState(x, y, GameLayerParameter) = ThePiece THEN
  189.                 Temp$ = LTRIM$(STR$(x)) + LTRIM$(STR$(y))
  190.                 EXIT FOR
  191.             END IF
  192.         NEXT
  193.     NEXT
  194.     FindCoordinates$ = Temp$
  195.  
  196. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  197.  
  198. SUB GenerateMoveList (TheColorIn AS STRING, GameLayerParIn, MoveListLayerIn)
  199.     ' Creates a string and then an array from the string.
  200.     DIM TCI AS STRING
  201.     TCI = TheColorIn
  202.     GameLayerParameter = GameLayerParIn
  203.     MoveListLayer = MoveListLayerIn
  204.     'Temp$ = ""
  205.     'MoveCountIndex = 0
  206.     MoveListArraySize(MoveListLayer) = 0
  207.     FOR x = 1 TO 8
  208.         FOR y = 1 TO 8
  209.             c$ = BoardState(x, y, GameLayerParameter)
  210.             IF LEFT$(c$, 1) = TCI THEN
  211.                 CALL ListPieceMoves(c$, GameLayerParameter, MoveListLayer)
  212.             END IF
  213.         NEXT
  214.     NEXT
  215.  
  216. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  217.  
  218. SUB ListPieceMoves (ThePieceIn AS STRING, GameLayerParIn, MoveListLayerIn)
  219.     DIM ThePiece AS STRING
  220.     ThePiece = ThePieceIn
  221.     GameLayerParameter = GameLayerParIn
  222.     MoveListLayer = MoveListLayerIn
  223.  
  224.     ' Isolate last character.
  225.     TheLastChar$ = RIGHT$(ThePiece, 1)
  226.  
  227.     Temp$ = ""
  228.     SELECT CASE TheLastChar$
  229.         CASE "K" ' King
  230.             CALL GetDiagMovesSingle(ThePiece, GameLayerParameter, MoveListLayer)
  231.             CALL GetRowColMovesSingle(ThePiece, GameLayerParameter, MoveListLayer)
  232.         CASE "Q" ' Queen
  233.             CALL GetDiagMovesFull(ThePiece, GameLayerParameter, MoveListLayer)
  234.             CALL GetRowColMovesFull(ThePiece, GameLayerParameter, MoveListLayer)
  235.         CASE "R" ' Rook
  236.             CALL GetRowColMovesFull(ThePiece, GameLayerParameter, MoveListLayer)
  237.         CASE "N" ' Knight
  238.             CALL GetKnightMoves(ThePiece, GameLayerParameter, MoveListLayer)
  239.         CASE "B" ' Bishop
  240.             CALL GetDiagMovesFull(ThePiece, GameLayerParameter, MoveListLayer)
  241.         CASE ELSE ' It's a pawn. They are not ambi-directional so be careful.
  242.  
  243.             PlayerColor$ = LEFT$(ThePiece, 1)
  244.             SELECT CASE PlayerColor$
  245.                 CASE "W"
  246.                     OpponentColor$ = "B"
  247.                     PawnMoveDirection = 1
  248.                 CASE "B"
  249.                     OpponentColor$ = "W"
  250.                     PawnMoveDirection = -1
  251.             END SELECT
  252.  
  253.             CoordTemp$ = FindCoordinates$(ThePiece, GameLayerParameter)
  254.             XOrig = VAL(LEFT$(CoordTemp$, 1))
  255.             YOrig = VAL(RIGHT$(CoordTemp$, 1))
  256.  
  257.             Temp$ = ""
  258.  
  259.             ' Three standard pawn moves.
  260.             X = XOrig: Y = YOrig: X = X: Y = Y + PawnMoveDirection
  261.             IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  262.                 IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  263.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  264.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = ThePiece + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  265.                 END IF
  266.             END IF
  267.  
  268.             X = XOrig: Y = YOrig: X = X + 1: Y = Y + PawnMoveDirection
  269.             IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  270.                 IF LEFT$(BoardState(X, Y, GameLayerParameter), 1) = OpponentColor$ THEN
  271.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  272.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = ThePiece + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  273.                 END IF
  274.             END IF
  275.  
  276.             X = XOrig: Y = YOrig: X = X - 1: Y = Y + PawnMoveDirection
  277.             IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  278.                 IF LEFT$(BoardState(X, Y, GameLayerParameter), 1) = OpponentColor$ THEN
  279.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  280.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = ThePiece + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  281.                 END IF
  282.             END IF
  283.  
  284.             ' Special case of first pawn move.
  285.             X = XOrig: Y = YOrig:
  286.             SELECT CASE PlayerColor$
  287.                 CASE "W"
  288.                     IF Y = 2 THEN
  289.                         X = XOrig: Y = YOrig: X = X: Y = Y + 2 * PawnMoveDirection
  290.                         IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  291.                             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  292.                             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = ThePiece + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  293.                         END IF
  294.                     END IF
  295.                 CASE "B"
  296.                     IF Y = 7 THEN
  297.                         X = XOrig: Y = YOrig: X = X: Y = Y + 2 * PawnMoveDirection
  298.                         IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  299.                             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  300.                             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = ThePiece + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  301.                         END IF
  302.                     END IF
  303.             END SELECT
  304.  
  305.     END SELECT
  306.  
  307. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  308.  
  309. SUB PrintGame (GameLayerParIn)
  310.     GameLayerParameter = GameLayerParIn
  311.     FOR x = 1 TO 8
  312.         FOR y = 1 TO 8
  313.             c$ = BoardState(x, 8 - y + 1, GameLayerParameter)
  314.             SELECT CASE c$
  315.                 CASE "0"
  316.                     LOCATE y * 2, x * 5: PRINT "0  "
  317.                 CASE ELSE
  318.                     LOCATE y * 2, x * 5: PRINT c$
  319.             END SELECT
  320.  
  321.             LOCATE y * 2, x * 3 + 50: PRINT LTRIM$(STR$(x)) + LTRIM$(STR$(8 - y + 1))
  322.  
  323.         NEXT
  324.     NEXT
  325.  
  326. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  327.  
  328. SUB GetRowColMovesFull (PieceNameIn AS STRING, GameLayerParIn, MoveListLayerIn)
  329.     PieceName$ = PieceNameIn
  330.     GameLayerParameter = GameLayerParIn
  331.     MoveListLayer = MoveListLayerIn
  332.     FirstLetter$ = LEFT$(PieceName$, 1)
  333.     Temp$ = FindCoordinates$(PieceName$, GameLayerParameter)
  334.     XOrig = VAL(LEFT$(Temp$, 1))
  335.     YOrig = VAL(RIGHT$(Temp$, 1))
  336.     X = XOrig
  337.     Y = YOrig
  338.     DO
  339.         X = X + 1
  340.         IF X <= 8 THEN
  341.             IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  342.  
  343.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  344.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  345.             ELSE
  346.                 IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  347.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  348.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  349.                 END IF
  350.                 EXIT DO
  351.             END IF
  352.         END IF
  353.     LOOP UNTIL X > 8
  354.     X = XOrig
  355.     Y = YOrig
  356.     DO
  357.         X = X - 1
  358.         IF X >= 1 THEN
  359.             IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  360.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  361.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  362.             ELSE
  363.                 IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  364.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  365.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  366.                 END IF
  367.                 EXIT DO
  368.             END IF
  369.         END IF
  370.     LOOP UNTIL X < 1
  371.     X = XOrig
  372.     Y = YOrig
  373.     DO
  374.         Y = Y + 1
  375.         IF Y <= 8 THEN
  376.             IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  377.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  378.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  379.             ELSE
  380.                 IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  381.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  382.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  383.                 END IF
  384.                 EXIT DO
  385.             END IF
  386.         END IF
  387.     LOOP UNTIL Y > 8
  388.     X = XOrig
  389.     Y = YOrig
  390.     DO
  391.         Y = Y - 1
  392.         IF Y >= 1 THEN
  393.             IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  394.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  395.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  396.             ELSE
  397.                 IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  398.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  399.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  400.                 END IF
  401.                 EXIT DO
  402.             END IF
  403.         END IF
  404.     LOOP UNTIL Y < 1
  405.  
  406.  
  407. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  408.  
  409. SUB GetDiagMovesFull (PieceNameIn AS STRING, GameLayerParIn, MoveListLayerIn)
  410.     PieceName$ = PieceNameIn
  411.     GameLayerParameter = GameLayerParIn
  412.     MoveListLayer = MoveListLayerIn
  413.     FirstLetter$ = LEFT$(PieceName$, 1)
  414.     Temp$ = FindCoordinates$(PieceName$, GameLayerParameter)
  415.     XOrig = VAL(LEFT$(Temp$, 1))
  416.     YOrig = VAL(RIGHT$(Temp$, 1))
  417.     X = XOrig
  418.     Y = YOrig
  419.     DO
  420.         X = X + 1
  421.         Y = Y + 1
  422.         IF X <= 8 AND Y <= 8 THEN
  423.             IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  424.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  425.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  426.             ELSE
  427.                 IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  428.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  429.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  430.                 END IF
  431.                 EXIT DO
  432.             END IF
  433.         END IF
  434.     LOOP UNTIL X > 8 OR Y > 8
  435.     X = XOrig
  436.     Y = YOrig
  437.     DO
  438.         X = X - 1
  439.         Y = Y + 1
  440.         IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  441.             IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  442.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  443.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  444.             ELSE
  445.                 IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  446.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  447.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  448.                 END IF
  449.                 EXIT DO
  450.             END IF
  451.         END IF
  452.     LOOP UNTIL X < 1 OR Y > 8
  453.     X = XOrig
  454.     Y = YOrig
  455.     DO
  456.         X = X - 1
  457.         Y = Y - 1
  458.         IF X >= 1 AND Y >= 1 THEN
  459.             IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  460.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  461.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  462.             ELSE
  463.                 IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  464.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  465.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  466.                 END IF
  467.                 EXIT DO
  468.             END IF
  469.         END IF
  470.     LOOP UNTIL X < 1 OR Y < 1
  471.     X = XOrig
  472.     Y = YOrig
  473.     DO
  474.         X = X + 1
  475.         Y = Y - 1
  476.         IF X <= 8 AND Y >= 1 THEN
  477.             IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  478.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  479.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  480.             ELSE
  481.                 IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  482.                     MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  483.                     MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  484.                 END IF
  485.                 EXIT DO
  486.             END IF
  487.         END IF
  488.     LOOP UNTIL X > 8 OR Y < 1
  489.  
  490.  
  491. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  492.  
  493. SUB GetRowColMovesSingle (PieceNameIn AS STRING, GameLayerParIn, MoveListLayerIn)
  494.     PieceName$ = PieceNameIn
  495.     GameLayerParameter = GameLayerParIn
  496.     MoveListLayer = MoveListLayerIn
  497.     FirstLetter$ = LEFT$(PieceName$, 1)
  498.     Temp$ = FindCoordinates$(PieceName$, GameLayerParameter)
  499.     XOrig = VAL(LEFT$(Temp$, 1))
  500.     YOrig = VAL(RIGHT$(Temp$, 1))
  501.     x = XOrig
  502.     Y = YOrig
  503.     x = x + 1
  504.     IF x <= 8 THEN
  505.         IF BoardState(x, Y, GameLayerParameter) = "0" THEN
  506.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  507.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(x)) + LTRIM$(STR$(Y))
  508.         ELSE
  509.             IF FirstLetter$ <> LEFT$(BoardState(x, Y, GameLayerParameter), 1) THEN
  510.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  511.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(x)) + LTRIM$(STR$(Y))
  512.             END IF
  513.         END IF
  514.     END IF
  515.     x = XOrig
  516.     Y = YOrig
  517.     x = x - 1
  518.     IF x >= 1 THEN
  519.         IF BoardState(x, Y, GameLayerParameter) = "0" THEN
  520.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  521.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(x)) + LTRIM$(STR$(Y))
  522.         ELSE
  523.             IF FirstLetter$ <> LEFT$(BoardState(x, Y, GameLayerParameter), 1) THEN
  524.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  525.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(x)) + LTRIM$(STR$(Y))
  526.             END IF
  527.         END IF
  528.     END IF
  529.     x = XOrig
  530.     Y = YOrig
  531.     Y = Y + 1
  532.     IF Y <= 8 THEN
  533.         IF BoardState(x, Y, GameLayerParameter) = "0" THEN
  534.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  535.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(x)) + LTRIM$(STR$(Y))
  536.         ELSE
  537.             IF FirstLetter$ <> LEFT$(BoardState(x, Y, GameLayerParameter), 1) THEN
  538.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  539.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(x)) + LTRIM$(STR$(Y))
  540.             END IF
  541.         END IF
  542.     END IF
  543.     x = XOrig
  544.     Y = YOrig
  545.     Y = Y - 1
  546.     IF Y >= 1 THEN
  547.         IF BoardState(x, Y, GameLayerParameter) = "0" THEN
  548.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  549.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(x)) + LTRIM$(STR$(Y))
  550.         ELSE
  551.             IF FirstLetter$ <> LEFT$(BoardState(x, Y, GameLayerParameter), 1) THEN
  552.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  553.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(x)) + LTRIM$(STR$(Y))
  554.             END IF
  555.         END IF
  556.     END IF
  557.  
  558.  
  559. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  560.  
  561. SUB GetDiagMovesSingle (PieceNameIn AS STRING, GameLayerParIn, MoveListLayerIn)
  562.     PieceName$ = PieceNameIn
  563.     GameLayerParameter = GameLayerParIn
  564.     MoveListLayer = MoveListLayerIn
  565.     FirstLetter$ = LEFT$(PieceName$, 1)
  566.     Temp$ = FindCoordinates$(PieceName$, GameLayerParameter)
  567.     XOrig = VAL(LEFT$(Temp$, 1))
  568.     YOrig = VAL(RIGHT$(Temp$, 1))
  569.     X = XOrig
  570.     Y = YOrig
  571.     X = X + 1
  572.     Y = Y + 1
  573.     IF X <= 8 AND Y <= 8 THEN
  574.         IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  575.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  576.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  577.         ELSE
  578.             IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  579.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  580.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  581.             END IF
  582.         END IF
  583.     END IF
  584.     X = XOrig
  585.     Y = YOrig
  586.     X = X - 1
  587.     Y = Y + 1
  588.     IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  589.         IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  590.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  591.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  592.         ELSE
  593.             IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  594.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  595.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  596.             END IF
  597.         END IF
  598.     END IF
  599.     X = XOrig
  600.     Y = YOrig
  601.     X = X - 1
  602.     Y = Y - 1
  603.     IF X >= 1 AND Y >= 1 THEN
  604.         IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  605.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  606.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  607.         ELSE
  608.             IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  609.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  610.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  611.             END IF
  612.         END IF
  613.     END IF
  614.     X = XOrig
  615.     Y = YOrig
  616.     X = X + 1
  617.     Y = Y - 1
  618.     IF X <= 8 AND Y >= 1 THEN
  619.         IF BoardState(X, Y, GameLayerParameter) = "0" THEN
  620.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  621.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  622.         ELSE
  623.             IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  624.                 MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  625.                 MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  626.             END IF
  627.         END IF
  628.     END IF
  629.  
  630.  
  631. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  632.  
  633. SUB GetKnightMoves (PieceNameIn AS STRING, GameLayerParIn, MoveListLayerIn)
  634.     PieceName$ = PieceNameIn
  635.     GameLayerParameter = GameLayerParIn
  636.     MoveListLayer = MoveListLayerIn
  637.     FirstLetter$ = LEFT$(PieceName$, 1)
  638.     Temp$ = FindCoordinates$(PieceName$, GameLayerParameter)
  639.     XOrig = VAL(LEFT$(Temp$, 1))
  640.     YOrig = VAL(RIGHT$(Temp$, 1))
  641.  
  642.     X = XOrig: Y = YOrig: X = X + 2: Y = Y + 1
  643.     IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  644.         IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  645.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  646.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  647.         END IF
  648.     END IF
  649.  
  650.     X = XOrig: Y = YOrig: X = X + 1: Y = Y + 2
  651.     IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  652.         IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  653.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  654.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  655.         END IF
  656.     END IF
  657.  
  658.     X = XOrig: Y = YOrig: X = X - 1: Y = Y + 2
  659.     IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  660.         IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  661.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  662.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  663.         END IF
  664.     END IF
  665.  
  666.     X = XOrig: Y = YOrig: X = X - 2: Y = Y + 1
  667.     IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  668.         IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  669.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  670.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  671.         END IF
  672.     END IF
  673.  
  674.     X = XOrig: Y = YOrig: X = X - 2: Y = Y - 1
  675.     IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  676.         IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  677.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  678.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  679.         END IF
  680.     END IF
  681.  
  682.     X = XOrig: Y = YOrig: X = X - 1: Y = Y - 2
  683.     IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  684.         IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  685.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  686.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  687.         END IF
  688.     END IF
  689.  
  690.     X = XOrig: Y = YOrig: X = X + 1: Y = Y - 2
  691.     IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  692.         IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  693.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  694.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  695.         END IF
  696.     END IF
  697.  
  698.     X = XOrig: Y = YOrig: X = X + 2: Y = Y - 1
  699.     IF X >= 1 AND X <= 8 AND Y >= 1 AND Y <= 8 THEN
  700.         IF FirstLetter$ <> LEFT$(BoardState(X, Y, GameLayerParameter), 1) THEN
  701.             MoveListArraySize(MoveListLayer) = MoveListArraySize(MoveListLayer) + 1
  702.             MoveListArray(MoveListArraySize(MoveListLayer), MoveListLayer) = PieceName$ + LTRIM$(STR$(X)) + LTRIM$(STR$(Y))
  703.         END IF
  704.     END IF
  705.  
  706.  
  707. ' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
  708.  
Title: Re: A 90% complete chess engine
Post by: Richard Frost on January 24, 2020, 11:57:23 pm
Here's mine.  It has lots of bugs, mainly that it doesn't recognize checkmate - you get to capture the King and
keep on playing.  Also, castling only seems to work for the white side.

I wrote this over 20 years ago, and am now converting it to QB64.  Hard to remember what my logic was back
then - lots of bits I've forgotten what they're for!  Anyway, "d" switches it to a big board, the move is highlighted
for review and the user presses a key to execute it, arrow keys and Enter to make your own move. 

This is the only code I've ever done that uses recursion.  The code is entirely mine, but I did steal the chess pieces
from somewhere, since I'm no artist.

The last subroutine evaluates the moves, and needs major expansion.  The priority is to get it working properly
first.  It plays suprisingly well with so few rules.  A text file is created of all the "thinking" should one be a masochist
and wish to review it.

Code: QB64: [Select]
  1. _TITLE "Chess"
  2. DEFINT A-Z
  3. CONST true = -1, false = 0
  4. CONST BoardWhite = 1, BoardBlack = 2
  5. CONST Rook = 1, Knight = 2, Bishop = 3, Queen = 4, King = 5, Pawn = 6
  6.  
  7. COMMON SHARED debug$
  8. COMMON SHARED WorB, Move, Score, Index, opening
  9. COMMON SHARED m$, i$, Enter$, Esc$, lf$, mess$
  10. COMMON SHARED fln '                                                  file line number, diagnostics
  11. COMMON SHARED fr, fc, tr, tc
  12. COMMON SHARED MaxRow
  13. COMMON SHARED xq, yq '                                               size of squares in pixels
  14. COMMON SHARED xc, yc '                                               top left of board
  15. COMMON SHARED WaitForKey
  16. COMMON SHARED Castle$, OtherK$, kr, kc, mkr, mkc
  17. COMMON SHARED MasterLevel, SaveWorB
  18. COMMON SHARED GameFile$, check, redo, redo$, b1, b2, b1$, b2$
  19. COMMON SHARED debug, DebugR, DebugC
  20. COMMON SHARED Start1&, Start2&, MaxElapse!
  21. COMMON SHARED human, humanc, OnAuto
  22. COMMON SHARED linesprinted&&
  23.  
  24. l = VAL(COMMAND$) '                                                  going beyond 6 plies takes a long time
  25. IF l = 0 THEN l = 4 '
  26. MasterLevel = l
  27. human = 1: humanc = 0 '                                              comment line out for autoplay
  28. debug = 1 '                                                          change to 0 or press "d" during play for bigger board
  29.  
  30. p = 6: b = 8: q1 = 200: q2 = 500
  31. DIM SHARED b(b, b), t(b, b, l), o(b, b), mp$(p, 7)
  32. DIM SHARED Moves(l), Move$(l, q1), Score(l, q1), TieTo(l), Index(l, q1)
  33. DIM SHARED x(p, q2), y(p, q2), c&(12, q2), MoveLog$(q2)
  34. DIM SHARED gm$(999), garr(31000), cp&(32)
  35.  
  36. OnAuto = NOT (OnAuto)
  37. Begin:
  38. Init
  39. opening = 1
  40.  
  41.     redo$ = ""
  42.     MiscInfo
  43.     'LINE (0, 0)-(945, _HEIGHT), _RGB(0, 0, 0), BF
  44.     SaveWorB = WorB
  45.     IF opening > 0 THEN
  46.         READ m$
  47.         IF m$ = "end" THEN opening = 0
  48.     END IF
  49.     IF opening = 0 THEN
  50.         IF Start1& = 0 THEN Start1& = TIMER
  51.         Start2& = TIMER
  52.         CheckBoard 0
  53.         IF Moves(0) = 0 THEN mess$ = "No legal moves."
  54.         IF LEN(mess$) > 0 THEN EXIT DO
  55.         IF human AND (humanc = WorB) THEN
  56.             woof:
  57.             HumanMove
  58.             ok = 0
  59.             FOR i = 1 TO Moves(0)
  60.                 IF m$ = Move$(0, i) THEN ok = 1: EXIT FOR
  61.             NEXT i
  62.             IF ok = 0 THEN SOUND 200, 1: GOTO woof
  63.         ELSE
  64.             fln = 0
  65.             DebugR = 999: DebugC = 1
  66.  
  67.             Recurse 1
  68.             TakeBest 0
  69.             IF debug THEN MovesRanked
  70.  
  71.             b1$ = m$
  72.             IF (Score(0, 1) = 777) AND (Score(1, 1) <> -777) THEN
  73.                 Score(0, 1) = 22
  74.                 TakeBest 0
  75.                 b1$ = m$
  76.             END IF
  77.             BoSave 0
  78.  
  79.             WorB = SaveWorB
  80.             CheckBoard 0
  81.             b1 = Score(0, 1)
  82.             MoveIt b1$, 0 '                                          make the move
  83.  
  84.             WorB = SaveWorB XOR 1 '                                  toggle player
  85.             CheckBoard 0 '                                           see what damage can be done
  86.             b2$ = m$
  87.             b2 = Score
  88.  
  89.             redo$ = STR$(b1) + STR$(b2 - 12)
  90.             IF (b1 < (b2 - 112)) OR (Score = 777) THEN '            I forgot WHAT this bit was!
  91.                 'IF Score = 777 THEN
  92.                 redo = true
  93.                 redo$ = "*" + STR$(b1) + STR$(b2 - 12)
  94.             END IF
  95.  
  96.             BoRestore 0
  97.             WorB = SaveWorB
  98.             m$ = b1$
  99.  
  100.             wonka:
  101.             IF redo THEN '                                           try again checking ALL
  102.                 sl = MasterLevel
  103.                 MasterLevel = 2
  104.                 WorB = SaveWorB
  105.                 CheckBoard 0
  106.                 Recurse 1 '                                          start over
  107.                 TakeBest 0
  108.                 IF debug THEN MovesRanked
  109.                 m$ = Move$(0, 1)
  110.                 MasterLevel = sl
  111.                 redo = false
  112.             END IF
  113.             WorB = SaveWorB
  114.             PlotAll
  115.  
  116.             fr = VAL(MID$(m$, 2, 1)) '                               from row
  117.             fc = INSTR("abcdefgh", LEFT$(m$, 1)) '                   from column
  118.             IF LEFT$(m$, 1) = "O" THEN fr = kr: fc = kc
  119.             x1 = xc + (fc - 5) * xq
  120.             y1 = yc + ((9 - fr) - 6) * yq
  121.             LINE (x1, y1)-STEP(xq, yq), _RGB(0, 255, 0), B
  122.             LINE (x1 + 1, y1 + 1)-STEP(xq - 2, yq - 2), _RGB(0, 255, 0), B
  123.  
  124.             IF LEFT$(m$, 1) <> "O" THEN
  125.                 tr = VAL(MID$(m$, 4, 1))
  126.                 tc = INSTR("abcdefgh", MID$(m$, 3, 1))
  127.                 x1 = xc + (tc - 5) * xq
  128.                 y1 = yc + ((9 - tr) - 6) * yq
  129.                 LINE (x1, y1)-STEP(xq, yq), _RGB(255, 255, 255), B
  130.             END IF
  131.  
  132.             'SOUND 333, 1
  133.             IF debug = 1 THEN
  134.                 MiscInfo
  135.                 RESTORE vlines
  136.                 DO
  137.                     READ x
  138.                     IF x = 0 THEN EXIT DO
  139.                     FOR i = -2 TO 2 STEP 4
  140.                         LINE (x + i, 0)-(x + i, _HEIGHT - 16), _RGB32(155, 0, 0)
  141.                     NEXT i
  142.                 LOOP
  143.             END IF
  144.  
  145.             DO: _LIMIT 10
  146.                 ScanKey
  147.                 IF i$ = "s" THEN i$ = "": SHELL _DONTWAIT "notepad chtemp.txt"
  148.             LOOP UNTIL LEN(i$)
  149.         END IF
  150.     END IF
  151.     WorB = SaveWorB
  152.     DispTime
  153.     MoveIt m$, -1
  154.     ShowAlgebraic m$
  155.  
  156.     IF opening = 0 THEN
  157.         check = false
  158.         CheckBoard 0
  159.         LOCATE 1, 8
  160.         IF Score = 777 THEN
  161.             check = true
  162.             PRINT "Check!";
  163.         ELSE
  164.             PRINT "      ";
  165.         END IF
  166.     END IF
  167.  
  168.     WorB = SaveWorB XOR 1 '                                          toggle white/black
  169.     IF LEN(GameFile$) > 0 THEN KeyGet
  170.     WaitForKey = true
  171. LOOP UNTIL Move = 500
  172.  
  173. IF Move = 500 THEN mess$ = "Over 500 moves...."
  174. LOCATE 1, 1: PRINT mess$;
  175.  
  176. vlines:
  177. DATA 226,467,707,950,0
  178.  
  179. o1:
  180. DATA e2e4,e7e5,g1f3,b8c6,f1b5,a7a6,b5a4,b7b5,a4b3,g8f6,b1c3,f8e7,f3g5,h7h6
  181. 'DATA g5f7,O-O
  182. 'DATA f7d8,g8h7
  183.  
  184. SetUp:
  185. DATA 1,2,3,4,5,3,2,1
  186. DATA 6,6,6,6,6,6,6,6
  187. DATA 0,0,0,0,0,0,0,0
  188. DATA 0,0,0,0,0,0,0,0
  189. DATA 0,0,0,0,0,0,0,0
  190. DATA 0,0,0,0,0,0,0,0
  191. DATA 12,12,12,12,12,12,12,12
  192. DATA 7,8,9,10,11,9,8,7
  193.  
  194. Legal:
  195. '      udlr,udlr,udlr,udlr,udlr,udlr,udlr,udlr
  196. DATA R,8000,0800,0080,0008,0000,0000,0000,0000
  197. DATA N,2010,2001,0210,0201,1020,1002,0120,0102
  198. DATA B,8080,8008,0880,0808,0000,0000,0000,0000
  199. DATA Q,8000,0800,0080,0008,8080,8008,0880,0808
  200. DATA K,1000,0100,0010,0001,1010,1001,0110,0101
  201. DATA P,1000,1001,1010,0000,0000,0000,0000,0000
  202.  
  203. PiecePatterns:
  204. DATA ........................
  205. DATA ........................
  206. DATA ........................
  207. DATA ........................
  208. DATA ....X..XX..XX..XX..X....
  209. DATA ....X..XX..XX..XX..X....
  210. DATA ....X..XX..XX..XX..X....
  211. DATA ....X..XX..XX..XX..X....
  212. DATA ....X..XX..XX..XX..X....
  213. DATA .....X.XX..XX..XX.X.....
  214. DATA ......XXXXXXXXXXXX......
  215. DATA .....XX..........XX.....
  216. DATA ......X.XXXXXXXX.X......
  217. DATA ......X.XXXXXXXX.X......
  218. DATA ......X.XXXXXXXX.X......
  219. DATA ......X.XXXXXXXX.X......
  220. DATA .....X............X.....
  221. DATA .....X..XXXXXXXX..X.....
  222. DATA ....X..............X....
  223. DATA ...X..XXXXXXXXXXXX..X...
  224. DATA ...X................X...
  225. DATA ...XXXXXXXXXXXXXXXXXX...
  226.  
  227. DATA ........................
  228. DATA ........................
  229. DATA ........................
  230. DATA ........................
  231. DATA ............XXX.........
  232. DATA ..........XX.X.X........
  233. DATA .........X..X.X.XX......
  234. DATA ........X.X.XX.X..X.....
  235. DATA .......X.XXXX.X.X..X....
  236. DATA .......X.X...XXX.X..X...
  237. DATA .....X..XX..X.XXX.X.X...
  238. DATA ....X.XXXXXXX.XXX.X..X..
  239. DATA ...X.XXXXXX.X..XX.X..X..
  240. DATA ...X.XX..XXX.X.XX.X..X..
  241. DATA ....X..XXXX..X.XX.X..X..
  242. DATA .....XX..X..X.XXX.X..X..
  243. DATA ........X..XX.XX.XX.X...
  244. DATA .......X..XX.XX.XX.X....
  245. DATA ......XXXXXXXXXXXXXX....
  246. DATA .....X..............X...
  247. DATA ....X................X..
  248. DATA .....XXXXXXXXXXXXXXXX...
  249.  
  250. DATA ........................
  251. DATA ........................
  252. DATA ........................
  253. DATA ............X...........
  254. DATA ...........X.X..........
  255. DATA ..........X.X.X.........
  256. DATA ........X...XX..X.......
  257. DATA .......X..X..XX..X......
  258. DATA .......X.XXX..XX.X......
  259. DATA .......X.XXXX..X.X......
  260. DATA ........X.......X.......
  261. DATA .......XX.X.X.X.XX......
  262. DATA ......X...........X.....
  263. DATA .......X.XXX.XX.XX......
  264. DATA ........X.XX.XX.X.......
  265. DATA .......X.XXX.XXX.X......
  266. DATA .......X.XXX.XXX.X......
  267. DATA ......X.X.......X.X.....
  268. DATA .....X.XXXXX.XXXXX.X....
  269. DATA .....X.XXXXX.XXXXX.X....
  270. DATA .....X.............X....
  271. DATA ......XXXXXXXXXXXXX.....
  272.  
  273. DATA ............X...........
  274. DATA ...........X.X..........
  275. DATA .....X....X.X.X....X....
  276. DATA ....X.X.XX.XXX..X.X.X...
  277. DATA ...X.X.X..XX.XXX.X.X.X..
  278. DATA ...X.XX.XXX.X.XXX.XX.X..
  279. DATA ...X.XXX.X.XXX.X.XXX.X..
  280. DATA ...X.XXXX.XXXXX.XXXX.X..
  281. DATA ....X.XXXXXX..XXXXX.X...
  282. DATA .....X.XXXXX..XXXX.X....
  283. DATA .....X.............X....
  284. DATA ......XXXXXXXXXXXXX.....
  285. DATA ....X...............X...
  286. DATA ......XX.XXXXXXX.XX.....
  287. DATA .......X.X.XXX.X.X......
  288. DATA ......X.XX.XXX.XX.X.....
  289. DATA ......X.XX.XXX.XX.X.....
  290. DATA .....XXXXXXXXXXXXXXX....
  291. DATA ....X...............X...
  292. DATA ...X..XX.XX.XX.XX.X..X..
  293. DATA ...X.................X..
  294. DATA ....XXXXXXXXXXXXXXXXX...
  295.  
  296. DATA ...........XX...........
  297. DATA .........XX..XX.........
  298. DATA .......XX.X..X.XX.......
  299. DATA .....XX.X......X.XX.....
  300. DATA ....X..XX.X..X.XX..X....
  301. DATA ...X...XXXX..XXXX...X...
  302. DATA ..X...XX........XX...X..
  303. DATA .X..XXX.XXX..XXX.XXX..X.
  304. DATA X..XXX..XXX..XXX..XXX..X
  305. DATA X.XXXX..XXX..XXXX.XXXX.X
  306. DATA X.XXXX.XXXX..XXXX.XXXX.X
  307. DATA X.XXXX..XXXXXXXX..XXXX.X
  308. DATA .X.XXXX..XXXXXX..XXXX.X.
  309. DATA .X..XXXX..XXXX..XXXX..X.
  310. DATA ..X..XXXX......XXXX..X..
  311. DATA ...X....X......X....X...
  312. DATA ...XXXXXXXXXXXXXXXXXX...
  313. DATA ..X..................X..
  314. DATA .X..XXXXXXXXXXXXXXXX..X.
  315. DATA .X..XXXXXXXXXXXXXXXX..X.
  316. DATA ..X..................X..
  317. DATA ...XXXXXXXXXXXXXXXXXX...
  318.  
  319. DATA ........................
  320. DATA ........................
  321. DATA ........................
  322. DATA ..........XXXX..........
  323. DATA .........X....X.........
  324. DATA ........X.XXXX.X........
  325. DATA ........X.XXXX.X........
  326. DATA .........X....X.........
  327. DATA ........XXXXXXXX........
  328. DATA .......X........X.......
  329. DATA ........XXXXXXXX........
  330. DATA .........X.XX.X.........
  331. DATA .........X.XX.X.........
  332. DATA .........X.XX.X.........
  333. DATA ........X..XX..X........
  334. DATA .......X..XXXX..X.......
  335. DATA ......X.XXXXXXXX.X......
  336. DATA ......X.XXXXXXXX.X......
  337. DATA .....X............X.....
  338. DATA ......XXXXXXXXXXXX......
  339. DATA ........................
  340. DATA ........................
  341.  
  342. rgb:
  343. DATA 0,0,0,0,""
  344. DATA 1,40,10,20,"board white"
  345. DATA 2,0,0,0,"board black"
  346. DATA 3,42,42,42,"white bright"
  347. DATA 4,2,2,2,"white highlight"
  348. DATA 5,0,0,0,"black bright"
  349. DATA 6,32,32,32,"black highlight"
  350. DATA 7,20,20,20,""
  351. DATA 8,20,20,20,""
  352. DATA 9,20,20,20,""
  353. DATA 10,20,20,20,""
  354. DATA 11,20,20,20,""
  355. DATA 12,20,20,20,""
  356. DATA 13,20,20,20,""
  357. DATA 14,20,20,20,""
  358. DATA 15,30,30,30,"printing"
  359.  
  360. SUB AddIt (Level, tm$, Score)
  361.     Moves(Level) = Moves(Level) + 1 '                                count ok
  362.     Move$(Level, Moves(Level)) = tm$ '                               save move
  363.     Score(Level, Moves(Level)) = Score
  364.     Index(Level, Moves(Level)) = TieTo(Level)
  365.  
  366. SUB BoRestore (Level)
  367.     FOR r = 1 TO 8
  368.         FOR c = 1 TO 8
  369.             b(r, c) = t(r, c, Level)
  370.         NEXT c
  371.     NEXT r
  372.  
  373. SUB BoSave (Level)
  374.     FOR r = 1 TO 8
  375.         FOR c = 1 TO 8
  376.             t(r, c, Level) = b(r, c)
  377.         NEXT c
  378.     NEXT r
  379.  
  380. SUB CheckBoard (Level)
  381.     Moves(Level) = 0
  382.  
  383.     OtherK = King - (WorB = 1) * 6 '                                 find location of kings
  384.     debug$ = STR$(King) + STR$(OtherK)
  385.     FOR fkr = 1 TO 8 '                                               row
  386.         FOR fkc = 1 TO 8 '                                           column
  387.             IF b(fkr, fkc) = 5 THEN mkr = fkr: mkc = fkc '           my king
  388.             IF b(fkr, fkc) = 11 THEN kr = fkr: kc = fkc '            opponent king
  389.         NEXT fkc
  390.     NEXT fkr
  391.  
  392.     FOR r = 1 TO 8 '                                                 row
  393.         ScanKey
  394.         FOR c = 1 TO 8 '                                             column
  395.             mp = b(r, c)
  396.             mc = -(mp > 6) - (mp = 0) * 2
  397.             IF mc = WorB THEN TryMove Level, r, c
  398.         NEXT c
  399.     NEXT r
  400.  
  401.     IF MID$(Castle$, WorB * 2 + 1, 1) = " " THEN cq = true ELSE cq = false
  402.     IF MID$(Castle$, WorB * 2 + 2, 1) = " " THEN ck = true ELSE ck = false
  403.  
  404.     FOR Castle = 0 TO 1 '                                            queenside, then kingside
  405.         IF Castle = 0 THEN cn$ = "2345" ELSE cn$ = "765"
  406.         IF WorB = 0 THEN rn$ = "8" ELSE rn$ = "1"
  407.         FOR cs = 1 TO LEN(cn$)
  408.             rn = VAL(rn$)
  409.             cn = VAL(MID$(cn$, cs, 1))
  410.             tp = b(rn, cn)
  411.             tp = tp + (tp > 6) * 6
  412.             IF (tp <> 0) AND (tp <> King) THEN
  413.                 IF Castle = 0 THEN cq = false ELSE ck = false
  414.             ELSE
  415.                 csq$ = MID$("abcdefgh", cn, 1) + rn$
  416.                 FOR lm = 1 TO Moves(1)
  417.                     IF csq$ = RIGHT$(Move$(1, lm), 2) THEN
  418.                         IF Castle = 0 THEN cq = false ELSE ck = false
  419.                     END IF
  420.                 NEXT lm
  421.             END IF
  422.         NEXT cs
  423.     NEXT Castle
  424.  
  425.     IF ck THEN AddIt Level, "O-O", 12
  426.     IF cq THEN AddIt Level, "O-O-O", 13
  427.  
  428.     ' LOCATE 26 + WorB, 30: PRINT "*"; Castle$; "*";
  429.     ' PRINT MID$("K ", ck + 2, 1);
  430.     ' PRINT MID$("Q ", cq + 2, 1);
  431.  
  432.     TakeBest Level
  433.  
  434. SUB MovesRanked '                                shows ranked eval at lower left
  435.     sr = 40
  436.     r = sr
  437.     c = 124
  438.     FOR t = 1 TO 120
  439.         IF c < 150 THEN
  440.             IF t <= Moves(0) THEN
  441.                 LOCATE r, c: PRINT SPACE$(8);
  442.                 LOCATE r, c
  443.                 PRINT Make4$(Move$(0, t)); rjust$(Score(0, t), 4);
  444.             END IF
  445.         END IF
  446.         r = r + 1
  447.         IF r > MaxRow THEN r = sr: c = c + 12
  448.     NEXT t
  449.  
  450. SUB MoveInfo (Level) STATIC
  451.     IF debug <> 1 THEN EXIT SUB
  452.     IF Level < 2 THEN
  453.         'DebugR = DebugR + 1
  454.         'EXIT SUB
  455.     END IF
  456.  
  457.     IF DebugR > MaxRow THEN
  458.         DebugR = 1
  459.         DebugC = 1
  460.         FOR r = 1 TO MaxRow
  461.             LOCATE DebugR, DebugC
  462.             'PRINT SPACE$(120 - DebugC);
  463.         NEXT r
  464.     END IF
  465.  
  466.     LOCATE DebugR, DebugC
  467.     ts = 0: s = 1
  468.     fln = fln + 1
  469.     tt$ = RIGHT$(SPACE$(5) + STR$(fln), 5)
  470.  
  471.     fprint tt$ + " "
  472.     FOR t = 1 TO Level
  473.         ti = TieTo(t)
  474.         IF t < 3 THEN PRINT Make4$(Move$(t - 1, ti)); rjust$(Score(t - 1, ti), 3); " ";
  475.         fprint Make4$(Move$(t - 1, ti)) + rjust$(Score(t - 1, ti), 3) + " "
  476.         ts = ts + Score(t - 1, ti) * s
  477.         s = -s
  478.     NEXT t
  479.     ts = ts + Score
  480.     PRINT Make4$(m$); rjust$(Score, 3); rjust$(ts, 4);
  481.     fprint Make4$(m$) + rjust$(Score, 3) + rjust$(ts, 4) + crlf$
  482.     DebugR = DebugR + 1
  483.     IF DebugR > MaxRow THEN
  484.         DebugR = 1
  485.         DebugC = DebugC + 30
  486.         IF DebugC > 120 THEN DebugC = 1
  487.     END IF
  488.  
  489. SUB DispTime
  490.     IF Start2& > 0 THEN
  491.         Elapse1! = TIMER - Start1&
  492.         Elapse2! = TIMER - Start2&
  493.         IF Elapse2! > MaxElapse! THEN MaxElapse! = Elapse2!
  494.         'ShowTime 1, Elapse1!, "Game:"
  495.         'ShowTime 2, Elapse2!, "This move:"
  496.         'ShowTime 3, MaxElapse!, "Max move:"
  497.     END IF
  498.  
  499. SUB FadePiece (fr, fc, tr, tc)
  500.     x1 = xc + (fc - 5) * xq
  501.     y1 = yc + ((9 - fr) - 6) * yq
  502.     x2 = xc + (tc - 5) * xq
  503.     y2 = yc + ((9 - tr) - 6) * yq
  504.     p = b(tr, tc)
  505.     IF p > 6 THEN wb = 1: p = p - 6
  506.     i = p - (wb = 0) * 6
  507.  
  508.     FOR ps = 0 TO 1
  509.         IF ps = 0 THEN
  510.             c = fr + fc: tx = x1: ty = y1
  511.         ELSE
  512.             c = tr + tc: tx = x2: ty = y2
  513.         END IF
  514.         IF (c MOD 2) = 1 THEN
  515.             LINE (tx, ty)-(tx + xq, ty + yq), cp&(BoardWhite), BF
  516.         ELSE
  517.             LINE (tx, ty)-(tx + xq, ty + yq), cp&(BoardBlack), BF '       black square
  518.             LINE (tx, ty)-(tx + xq, ty + yq), cp&(BoardWhite), B '        border
  519.         END IF
  520.     NEXT ps
  521.  
  522.     FOR t = 1 TO c&(p, 0)
  523.         IF debug = 1 THEN
  524.             tx = x2 + x(p, t)
  525.             ty = y2 + y(p, t)
  526.             PSET (tx, ty), c&(i, t)
  527.         ELSE
  528.             tx = x2 + x(p, t) * 3 - 2
  529.             ty = y2 + y(p, t) * 3
  530.             LINE (tx, ty)-STEP(3, 3), c&(i, t), BF
  531.         END IF
  532.         'PSET (tx, ty), tc&
  533.     NEXT t
  534.  
  535. SUB HumanMove
  536.     FOR i = 0 TO 1
  537.         IF i = 0 THEN
  538.             rr = 1: cc = 1
  539.         ELSE
  540.             rr = fr: cc = fc
  541.         END IF
  542.         mx = _MOUSEX
  543.         my = _MOUSEY
  544.         DO
  545.             'LOCATE 1, 1: PRINT "Move ";
  546.             x1 = xc + (cc - 5) * xq
  547.             x2 = xc + (cc - 4) * xq
  548.             y1 = yc + (rr - 6) * yq
  549.             y2 = yc + (rr - 5) * yq
  550.             IF debug < -2 THEN
  551.                 GET (x1, y1)-(x2, y2), garr()
  552.                 PUT (x1, y1), garr(), PRESET
  553.                 _DELAY .1
  554.                 PUT (x1, y1), garr(), PSET
  555.                 _DELAY .1
  556.             ELSE
  557.                 zz = zz XOR 1
  558.                 IF zz THEN tc& = _RGB32(0, 0, 0) ELSE tc& = _RGB32(0, 255, 0)
  559.                 LINE (x1, y1)-(x2, y2), tc&, B
  560.                 _DELAY .1
  561.                 LINE (x1, y1)-(x2, y2), _RGB32(0, 0, 0), B
  562.             END IF
  563.             'tmx = _MOUSEX: tmy = _MOUSEY
  564.             IF (ABS(mx - tmx) > 8) OR (ABS(my - tmy) > 8) THEN
  565.                 IF tmx > mx THEN cc = cc + 1
  566.                 IF tmx < mx THEN cc = cc - 1
  567.                 IF tmy > my THEN rr = rr + 1
  568.                 IF tmx < my THEN rr = rr - 1
  569.             END IF
  570.             'i$ = INKEY$
  571.             ScanKey
  572.             IF LEN(i$) = 2 THEN
  573.                 kk = ASC(RIGHT$(i$, 1))
  574.                 cc = cc + (kk = 75) - (kk = 77) '                    left right
  575.                 rr = rr + (kk = 72) - (kk = 80) '                    up down
  576.             END IF
  577.             IF rr < 1 THEN rr = 1
  578.             IF rr > 8 THEN rr = 8
  579.             IF cc < 1 THEN cc = 1
  580.             IF cc > 8 THEN cc = 8
  581.             IF i$ = Esc$ THEN SYSTEM
  582.         LOOP UNTIL i$ = Enter$
  583.         IF i = 0 THEN
  584.             fr = rr: fc = cc
  585.         ELSE
  586.             tr = rr: tc = cc
  587.         END IF
  588.     NEXT i
  589.     fs$ = MID$("abcdefgh", fc, 1) + LTRIM$(STR$(9 - fr))
  590.     ts$ = MID$("abcdefgh", tc, 1) + LTRIM$(STR$(9 - tr))
  591.     m$ = fs$ + ts$
  592.     '   LOCATE 1, 1: PRINT m$; SPACE$(40);
  593.  
  594. SUB Init
  595.     xr = 1280: yr = 800 '                                            120*50 text?
  596.     SCREEN _NEWIMAGE(xr, yr, 32)
  597.  
  598.     RESTORE rgb
  599.     FOR p = 0 TO 15
  600.         READ PalNum, r, g, b, desc$
  601.         cp&(p) = _RGB32(r * 4, g * 4, b * 4)
  602.     NEXT p
  603.  
  604.     'RANDOMIZE TIMER '                                               seed generator
  605.     Move = 0
  606.     WorB = 1 '                                                       white=1, black=0
  607.     IF debug = 1 THEN
  608.         q = 28: xq = q: yq = q '                                         size of squares
  609.         xc = 1100: yc = 160 '                                            top left corner of board
  610.     ELSE
  611.         q = 80: xq = q: yq = q '                                         size of squares
  612.         xc = 360: yc = 440 '                                            top left corner of board
  613.     END IF
  614.     lf$ = CHR$(10)
  615.     Enter$ = CHR$(13)
  616.     Esc$ = CHR$(27)
  617.     crlf$ = Enter$ + lf$
  618.     Castle$ = SPACE$(4) '                                            flags QKQK (B then W)
  619.     mess$ = ""
  620.  
  621.     RESTORE PiecePatterns '                                          bit images
  622.     FOR p = 1 TO 6 '                                                 RNBQKP
  623.         ScanKey
  624.         n = 0
  625.         FOR y = 0 TO 21 '                                            22 rows
  626.             READ d$
  627.             p1 = INSTR(d$ + "X", "X") '                              find first "on" bit
  628.             FOR t = LEN(d$) TO 1 STEP -1 '                           find last "on" bit
  629.                 IF MID$(d$, t, 1) = "X" THEN
  630.                     p2 = t
  631.                     EXIT FOR
  632.                 END IF
  633.             NEXT t
  634.             FOR x = p1 TO p2
  635.                 pixel = INSTR(".X", MID$(d$, x, 1))
  636.                 n = n + 1
  637.                 IF pixel = 2 THEN tc& = cp&(3) ELSE tc& = cp&(4)
  638.                 x(p, n) = x + 1
  639.                 y(p, n) = y + 2
  640.                 c&(p, n) = tc&
  641.                 IF pixel = 2 THEN tc& = cp&(5) ELSE tc& = cp&(6)
  642.                 c&(p + 6, n) = tc&
  643.             NEXT x
  644.         NEXT y
  645.         c&(p, 0) = n
  646.     NEXT p
  647.  
  648.     RESTORE Legal '                                                  define how piece moves
  649.     FOR p = 1 TO 6 '                                                 RNBQKP
  650.         READ p$ '                                                    piece, not saved
  651.         FOR t = 0 TO 7 '                                             8 each
  652.             READ mp$(p, t) '                                         mp (move piece)
  653.         NEXT t
  654.     NEXT p
  655.  
  656.     RESTORE SetUp '                                                  initial board position
  657.     FOR r = 8 TO 1 STEP -1 '                                         row
  658.         FOR c = 1 TO 8 '                                             column
  659.             READ b(r, c)
  660.             o(r, c) = b(r, c)
  661.         NEXT c
  662.     NEXT r
  663.  
  664.     elim$ = " ,"
  665.     gm = 0: n = 0
  666.     IF LEN(GameFile$) > 0 THEN ReadGame
  667.     gm = 0
  668.  
  669.     MaxRow = 49
  670.  
  671.     f = f + 1
  672.     f$ = "chess" + LTRIM$(STR$(f))
  673.     OPEN f$ + ".alg" FOR OUTPUT AS #1 '                              algrebraic moves
  674.  
  675.     tf = FREEFILE
  676.     OPEN "chtemp.txt" FOR OUTPUT AS #tf
  677.     PRINT #tf, DATE$; " "; TIME$; crlf; crlf$;
  678.     CLOSE #tf
  679.     PlotAll
  680.  
  681. SUB KeyGet
  682.     sr = CSRLIN: sc = POS(0)
  683.     DO: _LIMIT 10
  684.         ScanKey
  685.         star = star XOR 1
  686.         IF i$ > "" THEN star = 0
  687.         LOCATE sr, sc
  688.         IF LEN(GameFile$) = 0 THEN PRINT CHR$(32 + star * 10);
  689.     LOOP UNTIL i$ > ""
  690.     IF i$ = "s" THEN WaitForKey = false
  691.  
  692. FUNCTION Make4$ (t$)
  693.     Make4$ = LEFT$(t$ + SPACE$(4), 4)
  694.  
  695. SUB MoveIt (m$, real)
  696.     IF m$ = "res" THEN EXIT SUB '                                    resign?
  697.     fs$ = LEFT$(m$, 2) '                                             from square
  698.     ts$ = RIGHT$(m$, 2) '                                            to square
  699.     nnn = 1 - (LEFT$(m$, 1) = "O") '                                 two moves for a castle
  700.     FOR pass = 1 TO nnn '                                            two moves for a castle
  701.         IF m$ = "O-O" THEN '                                         castle Kingside
  702.             IF WorB = 1 THEN '                                       white
  703.                 IF pass = 1 THEN '                                   first move of KS castle
  704.                     fs$ = "e1": ts$ = "g1"
  705.                 ELSE '                                               else 2nd
  706.                     fs$ = "h1": ts$ = "f1"
  707.                 END IF
  708.             ELSE '                                                   black castle
  709.                 IF pass = 1 THEN
  710.                     fs$ = "e8": ts$ = "g8"
  711.                 ELSE
  712.                     fs$ = "h8": ts$ = "f8"
  713.                 END IF
  714.             END IF
  715.         END IF
  716.         IF m$ = "O-O-O" THEN '                                       castle Queenside
  717.             IF WorB = 1 THEN '                                       white
  718.                 IF pass = 1 THEN
  719.                     fs$ = "e1": ts$ = "c1"
  720.                 ELSE
  721.                     fs$ = "a1": ts$ = "d1"
  722.                 END IF
  723.             ELSE
  724.                 IF pass = 1 THEN
  725.                     fs$ = "e8": ts$ = "c8"
  726.                 ELSE
  727.                     fs$ = "a8": ts$ = "d8"
  728.                 END IF
  729.             END IF
  730.         END IF
  731.         fr = VAL(RIGHT$(fs$, 1)) '                                   from row
  732.         fc = INSTR("abcdefgh", LEFT$(fs$, 1)) '                      from column
  733.  
  734.         pm = b(fr, fc) '                                             piece to move
  735.         p = pm + (pm > 6) * 6
  736.         tr = VAL(RIGHT$(ts$, 1)) '                                   to row
  737.         tc = INSTR("abcdefgh", LEFT$(ts$, 1)) '                      to column
  738.         b(tr, tc) = pm '                                             move piece in array
  739.         b(fr, fc) = 0 '                                              blank old array spot
  740.         IF real THEN
  741.             IF b(r, c) = o(r, c) THEN o(r, c) = -1
  742.             FadePiece fr, fc, tr, tc
  743.             IF p = King THEN MID$(Castle$, WorB * 2 + 1, 2) = "XX"
  744.             IF p = Rook THEN
  745.                 IF WorB = 0 THEN
  746.                     IF (fr = 8) AND (fc = 1) THEN MID$(Castle$, 1, 1) = "X"
  747.                     IF (fr = 8) AND (fc = 8) THEN MID$(Castle$, 2, 1) = "X"
  748.                 ELSE
  749.                     IF (fr = 1) AND (fc = 1) THEN MID$(Castle$, 3, 1) = "X"
  750.                     IF (fr = 1) AND (fc = 8) THEN MID$(Castle$, 4, 1) = "X"
  751.                 END IF
  752.             END IF
  753.         END IF
  754.         IF (p = Pawn) AND ((tr = 1) OR (tr = 8)) THEN
  755.             b(tr, tc) = Queen - (pm > 6) * 6 '                       promote to queen
  756.             IF real THEN FadePiece tr, tc, tr, tc '                  show queen
  757.         END IF
  758.     NEXT pass
  759.  
  760. SUB PlotAll
  761.     IF LEN(GameFile$) > 0 THEN
  762.         LOCATE 3, 40 - LEN(GameFile$) \ 2
  763.         PRINT GameFile$;
  764.     END IF
  765.     FOR r = 1 TO 8
  766.         FOR c = 1 TO 8
  767.             FadePiece r, c, r, c
  768.         NEXT c
  769.     NEXT r
  770.     FOR i = 1 TO 8 '                                                 legend
  771.         n$ = LTRIM$(STR$(i))
  772.         a$ = MID$("abcdefgh", i, 1)
  773.         IF debug = 1 THEN
  774.             nx = xc - 4 * xq - 12
  775.             ny = y2 + i * yq
  776.             ax = xc + (i - 5) * xq + 10
  777.             ay = yc + 3 * yq + 3
  778.         ELSE
  779.             nx = xc - 4 * xq - 14
  780.             ny = y2 + i * yq + 13
  781.             ax = xc + (i - 5) * xq + 35
  782.             ay = yc + 3 * yq + 3
  783.         END IF
  784.         _PRINTSTRING (nx, ny), n$
  785.         _PRINTSTRING (ax, ay), a$
  786.     NEXT i
  787.  
  788. SUB ReadGame
  789.     DIM g$(500)
  790.     OPEN GameFile$ FOR INPUT AS #1
  791.     WHILE NOT (EOF(1))
  792.         LINE INPUT #1, t$
  793.         n = n + 1
  794.         g$(n) = t$
  795.     WEND
  796.     CLOSE #1
  797.     i = 1
  798.     DO
  799.         g$ = g$(i)
  800.         DO
  801.             p1 = INSTR(g$, " ")
  802.             IF p1 = 0 THEN EXIT DO
  803.             p2 = INSTR(g$, ",")
  804.             IF p2 = 0 THEN p2 = LEN(g$)
  805.             t$ = LTRIM$(MID$(g$, p1, p2 - 2))
  806.             p = INSTR(t$, " ")
  807.             IF p = 0 THEN p = LEN(t$)
  808.             t2$ = RTRIM$(LEFT$(t$, p))
  809.             IF INSTR(elim$, RIGHT$(t2$, 1)) THEN t2$ = LEFT$(t2$, LEN(t2$) - 1)
  810.             gm$(gm) = t2$
  811.             gm = gm + 1
  812.             IF LEN(t$) > p THEN
  813.                 t$ = LTRIM$(RIGHT$(t$, LEN(t$) - p + 1))
  814.                 WHILE INSTR(elim$, RIGHT$(t$, 1))
  815.                     t$ = LEFT$(t$, LEN(t$) - 1)
  816.                 WEND
  817.                 gm$(gm) = t$
  818.                 'PRINT 2; gm$(gm)
  819.                 gm = gm + 1
  820.             END IF
  821.             ' KeyGet
  822.             g$ = RIGHT$(g$, LEN(g$) - p2)
  823.         LOOP UNTIL LEN(g$) = 0
  824.         i = i + 1
  825.     LOOP UNTIL i > n
  826.  
  827. SUB Recurse (Level)
  828.     DispTime
  829.     'LOCATE 1, 45 + Level * 2: PRINT "* ";
  830.     IF Level = MasterLevel THEN EXIT SUB
  831.     IF redo THEN
  832.         EndAt = Moves(Level - 1)
  833.     ELSE
  834.         EndAt = 5
  835.         IF EndAt > Moves(Level - 1) THEN EndAt = Moves(Level - 1)
  836.     END IF
  837.  
  838.     FOR t = 1 TO EndAt
  839.         WorB = SaveWorB
  840.         IF (Level MOD 2) = 1 THEN WorB = WorB XOR 1
  841.         TieTo(Level) = t
  842.         IF (Score(0, t) > -777) THEN
  843.             BoSave Level
  844.             m$ = Move$(Level - 1, t)
  845.             MoveIt m$, 0
  846.             lm1 = Level - 1
  847.             t$ = rjust$(Moves(lm1), 3)
  848.             t$ = t$ + rjust$(t, 4) + " "
  849.             t$ = t$ + Make4$(m$)
  850.             t$ = t$ + rjust$(Score(lm1, t), 5)
  851.  
  852.             'IF debug = 2 THEN ShowMe 3 + Level, 1, t$
  853.             'LOCATE 34, Level * 20: PRINT t; EndAt; " ";
  854.             CheckBoard Level
  855.             Recurse Level + 1
  856.             TakeBest Level
  857.             IF debug = 1 THEN MoveInfo Level
  858.             i = Index
  859.             Score = Score(Level, 1)
  860.             ' IF Level = 2 THEN Score = Score \ 2
  861.             levm1 = Level - 1
  862.             Score(levm1, i) = Score(levm1, i) - Score
  863.             'ShowMe 35, 130, Make4$(Move$(Level, 1)) + rjust$(Score(Level, 1), 4) + " "
  864.             'ShowMe 36, 130, Make4$(Move$(levm1, i)) + rjust$(Score(levm1, i), 4) + " "
  865.             BoRestore Level
  866.         END IF
  867.     NEXT t
  868.  
  869. FUNCTION rjust$ (t, n)
  870.     rjust$ = RIGHT$("   " + STR$(t), n)
  871.  
  872. SUB ScanKey
  873.     i$ = INKEY$
  874.     IF i$ = "" THEN EXIT SUB
  875.  
  876.     IF LEN(i$) = 1 THEN
  877.         IF i$ = "a" THEN
  878.             OnAuto = NOT (OnAuto)
  879.             IF auto THEN human = 0
  880.         END IF
  881.  
  882.         c = INSTR("123456789)!@#$%", i$)
  883.         IF c > 0 THEN
  884.             SOUND 777, 1
  885.             r = RND * 255: g = RND * 255: b = RND * 255
  886.             c& = _RGB32(r, g, b)
  887.             FOR y = 0 TO ym: FOR x = 0 TO xm
  888.                     p& = POINT(x, y)
  889.                     IF p& = cp&(c) THEN PSET (x, y), c&
  890.             NEXT x: NEXT y
  891.             cp&(c) = c&
  892.             i$ = ""
  893.         END IF
  894.  
  895.         IF i$ = "d" THEN
  896.             i$ = CHR$(255): debug = debug XOR 1
  897.             IF debug = 1 THEN
  898.                 q = 28: xq = q: yq = q '                             size of squares
  899.                 xc = 1100: yc = 160 '                                top left corner of board
  900.             ELSE
  901.                 q = 80: xq = q: yq = q '                             size of squares
  902.                 xc = 600: yc = 460 '                                 top left corner of board
  903.             END IF
  904.             CLS: PlotAll
  905.         END IF
  906.  
  907.         IF i$ = "s" THEN i$ = "": SHELL _DONTWAIT "notepad chtemp.txt"
  908.  
  909.         IF i$ = Esc$ THEN CLOSE: END
  910.     END IF
  911.  
  912. SUB ShowAlgebraic (m$)
  913.     IF WorB = 1 THEN ' white=1, black=0
  914.         Move = Move + 1 ' number the moves
  915.         PRINT #1, RIGHT$("  " + STR$(Move), 3);
  916.         PRINT #1, RIGHT$(SPACE$(10) + m$, 7);
  917.         MoveLog$(Move) = SPACE$(15)
  918.         MID$(MoveLog$(Move), 1, 3) = rjust$(Move, 3)
  919.         MID$(MoveLog$(Move), 5, LEN(m$)) = m$
  920.     ELSE
  921.         MID$(MoveLog$(Move), 11, LEN(m$)) = m$
  922.         PRINT #1, " "; m$
  923.         IF (Move MOD 5) = 0 THEN PRINT #1, ""
  924.     END IF
  925.  
  926.     BeginAt = Move - 39
  927.     IF BeginAt < 1 THEN BeginAt = 1
  928.     dr = 17: dc = 123
  929.     FOR t = BeginAt TO Move
  930.         ShowMe dr + 1, dc, MoveLog$(t)
  931.         dr = dr + 1
  932.         IF dr > 36 THEN
  933.             dr = 17: dc = dc + 15
  934.             IF dc > 138 THEN dr = 36: dc = 138
  935.         END IF
  936.     NEXT t
  937.  
  938. SUB ShowMe (dr, dc, t$)
  939.     sr = CSRLIN '                                                    save row
  940.     sc = POS(0) '                                                    save column
  941.     IF (dr > 0) AND (dr < 50) AND (dc > 0) AND (dc < 150) THEN
  942.         LOCATE dr, dc '                                              display row & column
  943.         PRINT t$;
  944.     END IF
  945.     IF NOT (OnAuto) THEN KeyGet
  946.     LOCATE sr, sc '                                                  restore to old location
  947.  
  948. SUB ShowTime (trow, t!, Desc$)
  949.     s! = t!
  950.     SELECT CASE s!
  951.         CASE IS > 3600
  952.             unit$ = "h"
  953.             s! = s! / 3600
  954.         CASE IS > 60
  955.             unit$ = "m"
  956.             s! = s! / 60
  957.         CASE ELSE
  958.             unit$ = "s"
  959.     END SELECT
  960.  
  961.     trow = trow + 3
  962.     LOCATE trow, 34 - LEN(Desc$): PRINT Desc$;
  963.     LOCATE trow, 34
  964.     PRINT USING "###.#"; s!;
  965.     PRINT unit$
  966.  
  967. SUB TakeBest (Level)
  968.     FOR scram = 0 TO 99
  969.         s1 = RND * (Moves(Level) - 1) + 1
  970.         s2 = RND * (Moves(Level) - 1) + 1
  971.         SWAP Score(Level, s1), Score(Level, s2)
  972.         SWAP Move$(Level, s1), Move$(Level, s2)
  973.         SWAP Index(Level, s1), Index(Level, s2)
  974.     NEXT scram
  975.  
  976.     passes = 0
  977.     ReSort:
  978.     Score = -999 '                                                   assume no moves
  979.     DO
  980.         Sorted = true
  981.         FOR s = 2 TO Moves(Level)
  982.             IF Score(Level, s - 1) < Score(Level, s) THEN
  983.                 Sorted = false
  984.                 SWAP Score(Level, s - 1), Score(Level, s)
  985.                 SWAP Move$(Level, s - 1), Move$(Level, s)
  986.                 SWAP Index(Level, s - 1), Index(Level, s)
  987.             END IF
  988.         NEXT s
  989.     LOOP UNTIL Sorted
  990.  
  991.     m$ = Move$(Level, 1)
  992.     Score = Score(Level, 1)
  993.     Index = Index(Level, 1)
  994.  
  995.     IF Level = 0 THEN
  996.         FOR lb = 0 TO 2 '                                            stop repeats
  997.             IF INSTR(MoveLog$(Move - lb), m$) THEN
  998.                 Score(Level, 1) = Score(Level, 2) - 1 '              best = 2nd best-1
  999.                 passes = passes + 1
  1000.                 IF passes < 5 THEN GOTO ReSort '                     repeat may be only move
  1001.             END IF
  1002.         NEXT lb
  1003.     END IF
  1004.  
  1005.     IF Level = 0 THEN
  1006.         IF Score = -777 THEN '                                       in check, no escape
  1007.             mess$ = "Mate"
  1008.         ELSEIF Score = -999 THEN '                                   no moves
  1009.             mess$ = "Stalemate"
  1010.         END IF
  1011.     END IF
  1012.  
  1013.     IF (Level = 1) AND (Score = 777) THEN Score(0, TieTo(1)) = -777
  1014.  
  1015. 'FUNCTION TextCol (xc)
  1016. '    TextCol = (xc - 1) * 2 + 25
  1017. 'END FUNCTION
  1018.  
  1019. 'FUNCTION TextRow (xr)
  1020. '    TextRow = (8 - xr) * 1 + 8
  1021. 'END FUNCTION
  1022.  
  1023. 'FUNCTION TextVal (xr, xc)
  1024. '    i = b(xr, xc)
  1025. '    i = i + (i > 6) * 6
  1026. '    TextVal = i
  1027. 'END FUNCTION
  1028.  
  1029. SUB fprint (t$)
  1030.     tf = FREEFILE
  1031.     OPEN "chtemp.txt" FOR APPEND AS #tf
  1032.     PRINT #tf, t$;
  1033.     CLOSE #tf
  1034.     IF INSTR(t$, Enter$) THEN
  1035.         linesprinted&& = linesprinted&& + 1
  1036.         IF (linesprinted&& MOD 1000) = 0 THEN LOCATE 1, 130: PRINT linesprinted&&;
  1037.     END IF
  1038.  
  1039. SUB MiscInfo
  1040.     LOCATE 1, 124: PRINT "Plies: "; COMMAND$; "  LP:"; linesprinted&&; redo$;
  1041.  
  1042. SUB TryMove (Level, fr, fc) '                                        from row, from column
  1043.     mp = b(fr, fc)
  1044.     IF mp = 0 THEN END
  1045.     mc = -(mp > 6) - (mp = 0) * 2 '                                  moving color
  1046.     IF mc = 2 THEN END
  1047.     mp = mp + (mp > 6) * 6
  1048.     IF mc = 1 THEN s = -1 ELSE s = 1 '                               direction a pawn moves
  1049.  
  1050.     FOR n = 0 TO 7 '                                                 possible 8 dirs
  1051.         udlr$ = mp$(mp, n) '                                         up/down/left/right
  1052.         IF udlr$ = "0000" THEN EXIT FOR '                            added 2Jan95
  1053.         du = VAL(MID$(udlr$, 1, 1)) '                                direction up
  1054.         dd = VAL(MID$(udlr$, 2, 1)) '                                direction down
  1055.         dl = VAL(MID$(udlr$, 3, 1)) '                                direction left
  1056.         dr = VAL(MID$(udlr$, 4, 1)) '                                direction right
  1057.         IF mp <> Knight THEN '                                       not knight
  1058.             du = SGN(du) * s '                                       one square at a time
  1059.             dd = SGN(dd) * s
  1060.             dl = SGN(dl) * s
  1061.             dr = SGN(dr) * s
  1062.         END IF
  1063.         IF INSTR(udlr$, "8") THEN TrySq = 8 ELSE TrySq = 1
  1064.         IF (mp = Pawn) AND (n = 0) THEN '                            pawn first move?
  1065.             IF (fr = 2) AND (WorB = 1) THEN TrySq = 2 '              gambit for white
  1066.             IF (fr = 7) AND (WorB = 0) THEN TrySq = 2 '              gambit for black
  1067.         END IF
  1068.         tr = fr: tc = fc '                                           row, column
  1069.         'IF TrySq = 0 THEN END
  1070.         FOR sq = 1 TO TrySq '                                        up to 8 loops
  1071.             capture = false
  1072.             Score = 0 '                                              must init
  1073.             tr = tr - du + dd '                                      row=row-up+down
  1074.             tc = tc - dl + dr '                                      column=column-left+right
  1075.             IF (tr < 1) OR (tr > 8) OR (tc < 1) OR (tc > 8) THEN EXIT FOR
  1076.             cp = b(tr, tc) '                                         capture piece
  1077.             cc = -(cp > 6) - (cp = 0) * 2 '                          capture color
  1078.             cp = cp + (cp > 6) * 6
  1079.             IF mc = cc THEN '                                        own piece!
  1080.                 EXIT FOR
  1081.             ELSEIF (mc XOR 1) = cc THEN '                            capture
  1082.                 IF (mp = Pawn) AND (n = 0) THEN EXIT FOR '           no diag, no cap!
  1083.                 capture = true
  1084.                 '                 RNBQKP
  1085.                 Score = VAL(MID$("533901", cp, 1)) * 10
  1086.                 IF (Score > 0) AND (Level = 0) THEN Score = Score + 2
  1087.                 IF Score = 0 THEN Score = 777 '                      king capture
  1088.                 ' IF redo AND (Score = 777) THEN Score = 25
  1089.             ELSE
  1090.                 IF (mp = Pawn) AND (n > 0) THEN EXIT FOR
  1091.             END IF
  1092.             IF mp = Pawn THEN
  1093.                 IF (tr = 1) OR (tr = 8) THEN '                       promote pawn
  1094.                     IF Score <> 777 THEN Score = Score + 99
  1095.                 END IF
  1096.             END IF
  1097.  
  1098.             InCheck = (mc = SaveWorB) AND check
  1099.             ' small plus for king moving out of check
  1100.             IF (mp = King) AND InCheck THEN Score = Score + 2
  1101.  
  1102.             ' leave king cap scores, also normal bonuses if in check
  1103.             IF (Score <> 777) AND (NOT (InCheck)) AND (mp <> King) THEN
  1104.                 dis1 = ABS(fr - kr) + ABS(fc - kc) '                 get closer to king
  1105.                 dis2 = ABS(tr - kr) + ABS(tc - kc)
  1106.                 ' IF dis2 < dis1 THEN Score = Score + (dis1 - dis2)
  1107.                 Score = Score + dis1 - dis2
  1108.  
  1109.                 IF Move < 30 THEN
  1110.                     dir = SGN((fr - tr) * s)
  1111.                     IF dir = 1 THEN Score = Score + 2 '              move ahead at begin & mid
  1112.                 END IF
  1113.  
  1114.                 IF mp <> Rook THEN '                                 priority to getting a piece first moved
  1115.                     IF b(fr, fc) = o(fr, fc) THEN Score = Score + 1
  1116.                 END IF
  1117.  
  1118.                 ' priority to getting a piece off the bottom rank
  1119.                 IF (fr = 1) AND (tr > 1) AND (WorB = 1) THEN Score = Score + 1
  1120.                 IF (fr = 8) AND (tf < 8) AND (WorB = 0) THEN Score = Score + 1
  1121.             END IF
  1122.  
  1123.             fs$ = MID$("abcdefgh", fc, 1) + CHR$(48 + fr) '          from square
  1124.             ts$ = MID$("abcdefgh", tc, 1) + CHR$(48 + tr) '          to square
  1125.             AddIt Level, fs$ + ts$, Score
  1126.             'IF capture AND (mp <> Pawn) THEN EXIT FOR '             stop looking
  1127.         NEXT sq
  1128.     NEXT n
  1129.  
Title: Re: A 90% complete chess engine
Post by: romichess on January 25, 2020, 12:07:31 pm
I wish that I had the time to study your code. I'm not fast. Never have been. What you report to have done in a couple hours would take me weeks. But, I have a different take on one issue.

Quote
I think some folks might need to be reminded of the so-called chess algorithm. Computers are stupid, they have no intuition, and certainly can't play chess like a person.

Here is one of many post about my engine RomiChess.

Quote
While Romi made Alfil look like an amateur with his mature positional play!

Look at that good knight vs bad bishop scenario - very human-like, the way Romi seems to be angling for this outcome.

One can look at the game here: http://talkchess.com/forum3/viewtopic.php?f=2&t=66154&p=745438&hilit=romichess+human#p745438 (http://talkchess.com/forum3/viewtopic.php?f=2&t=66154&p=745438&hilit=romichess+human#p745438)

I'm sure that I can find a couple dozen more if I look.
Title: Re: A 90% complete chess engine
Post by: bplus on January 26, 2020, 10:40:51 am
I wish that I had the time to study your code. I'm not fast. Never have been. What you report to have done in a couple hours would take me weeks. But, I have a different take on one issue.

Here is one of many post about my engine RomiChess.

One can look at the game here: http://talkchess.com/forum3/viewtopic.php?f=2&t=66154&p=745438&hilit=romichess+human#p745438 (http://talkchess.com/forum3/viewtopic.php?f=2&t=66154&p=745438&hilit=romichess+human#p745438)

I'm sure that I can find a couple dozen more if I look.

Ha! A least one week would be more believable but maybe he Trumped up his memory. ;-))


@ Richard Frost, do you check the code before you post? (I ask because this is 2nd time in row I try your code and run smack into error but I know the forum code editor sometimes changes code too though rare). Does the computer only play with itself? Here is screen shot of my Run, is the board supposed to be all the way to right with extra row of squares and run into the play listing? The chess pieces and board look great though tiny for this old man's eyes. I know you said bugs but man!

Quote
The code is entirely mine,...
I am big fan of this approach, I will show you mine.
Title: Re: A 90% complete chess engine
Post by: bplus on January 26, 2020, 10:53:10 am
Here is mine with kibitzing from TempodiBasic and Adrian's chess pieces, an extended study of the chess program that came with QB64 samples. Actually TempodiBasic did much more than kibitz (no, I am not Jewish but I seem to gravitate towards... maybe it's the Jewish comedians?), TempodiBasic's help prolonged my interest enough to get this 800+ more lines than it was and some of the bugs of chess engine fixed (still plenty more!), see development notes. Speaking of comedians, this should give our resident chess expert, Romichess, a good laugh! ;-))

Code: QB64: [Select]
  1. _TITLE "Chess 2017-11-22 T .bas     Ctrl+K for Keyboard input"
  2. '2017-10-10 raw patch of Interface to Chess.bas post update with mouse troubles
  3.  
  4. ' 22 10 2017 New fix to Incheck function, I hope the last!
  5. ' 22 10 2017  empowered promotion by mouse
  6. ' 22 10 2017  fix promotion visible only after move of black
  7. ' 22 10 2017 castle by mouse
  8. ' 22 10 2017  empowered castling control, now you cannot castle if they are in check
  9. '             or across a square that is under Black control
  10. ' 22 10 2017 translated in sub Info_Help screen
  11. ' 22 10 2017  translate in sub Fellippe's Wait click and key
  12. ' 22 10 2017 added logical end to the main of program
  13. ' 22 10 2017 put away all code REMMED not yet used
  14.  
  15. '2017 10 24 changed board graphics, arranged alpha order subs, updated highlite square
  16. ' Thanks Adrian Huang
  17. ' http://www.thejoyfulprogrammer.com/qb64/forum/showthread.php?tid=401&rndtime=1508625987687357559
  18.  
  19. '2017 10 24 Incorporate TempodiBasic's legalShow and legalHide routines
  20. ' fix pawn promotions see Ppromote$
  21. ' count pieces captured and show with board
  22. ' install game recorder
  23.  
  24. ' 27 10 2017 color of chessboard are CONST
  25. ' resizing square and character size to  42
  26. ' moving list of piece captured at top right
  27. ' moving output at bottom right
  28. ' new SUB ShowSetup that shows whole setup to choose pieces for white and black,
  29. ' or only pieces capturable (No king because when a King falls game stops!)
  30. ' or only pieces for promotion (Knight Bishop Rook Queen) for both colors
  31. ' now if Black resigns the flow of program ends after main do loop to let replay the game
  32. ' play again label structure and initialization instruction (it is possible to use a DO LOOP)
  33. ' Added ButtonMenuBar at bottom using MakeButton SUB
  34. ' Button QUIT working, button PLAY works for now let us play only as WHITE
  35. ' Build an area for list of moves
  36. ' build an area for output/feedback of program
  37. ' Changed Helpscreen instruction including mouse selection
  38. ' >>>> wow lots of new stuff
  39.  
  40. '2017-10-29/30 fixed dots in empty squares, highlight piece clicked, thing crawling under board while computer thinks
  41. ' now if we can only get the colors ;-)) Outer loop to restart game, elimate some boxes, less cluttered looking.
  42. ' change title to version = date easier to track
  43.  
  44. '2017 10 31 T  Yes I follow you in using date also if in my country I use DD-MM-YYYY   :-)
  45. '  YES fixed BIG BUG about restart and Play Again lasting the last moves in memory... and in File Recorder
  46.  
  47. '2017-11-01 B review TempodiBasic's BIG BUG fix, clean up lines, comments and variables
  48. ' I (bplus) see some work also done in IO for checking checks, I assume.
  49.  
  50. '2017-11-03 B Move Intro to before main program loop, fix some things with promotion
  51. ' prompt for pieces, pWflag$, pBflag$ to add to move list
  52.  
  53. '2017-11-04 B hack AI this is just an experiment for my cat who is always curious specially
  54. ' because it exists in another universe.
  55.  
  56. '2017-11-06 A 2nd post (really posted 11-05) Added/revised code for rotating board to play Black.
  57. ' Adrain has change 5000 number to 9000 im several places and I don't know if this fixes castle
  58. ' It did fix notation in the moves list correctly
  59.  
  60. '2017-11-05 B  from Adrian's 2nd post 2017-11-06( posted 11-05) A #2   continuing with hackBlack hacks!
  61. ' I noticed that code changes were very alike and one fuction would save quite a bit of code FIXED
  62. ' I also noticed the captured pieces were backwards when Black plays FIXED
  63. ' I noticed Black cant castle yet BIGGEST FIX of them all!!!
  64. ' I noticed Ctrl+K for human playing Black did not work, well had to translate move back so
  65. ' IO can reverse again!!  FIXED!
  66. ' Check pawn promotion and track down source of mystery q added to computer's moves.
  67. ' Still allot of goofy things...
  68.  
  69. '2017-11-07 A - removed fake 1st move while playing black
  70.  
  71. '2017-11-07 B hack 2 using above mod but with EXIT SUB instead of GOTO
  72. ' fix capture counts so that only positive counts show
  73. ' Ah found source of allot of goofyness!  hackBlack > playBlack per Adrian
  74. ' I think I have this working correctly through Play Again Y/N?
  75.  
  76. '2017-11-07 T put away GOTO for label 100 to play again
  77. ' moved in main loop AI resign (strange as white it capture by King and then when you takes King it resign!!!
  78. ' GOOD first AI goes on playing without king :-)
  79. '
  80. '2017-11-07 2B removed 100 next to loop since no goto, fixed comments on separate line
  81. ' and added some comments, I think I have finally tracked down source of extra q's!!! FIXED
  82.  
  83. ' 2017-11-10 T  fixed promotion  failure with strange choose made clicking on the other side of window of program
  84. ' at the Y of piece to get by promotion
  85. '   Restored  MAXLEVEL at beginning of program to set power of AI
  86. '
  87. ' 2017-11-10 2T cutting some old comments no more useful for use about issues yet resolved
  88. ' packing the 2 initboard to one (they do the same work with 2 different labels)
  89. '
  90. '2017-11-11 B Put T comments on separate line from code.
  91. 'Recommend making MAXLEVEL a CONST if we will not change it ever.
  92. 'Tell why two different boards are needed to initialize the board positions.
  93. 'Fix pWfalg$ again! that AI has no business changing BUT OK save ElSE block because AI
  94. 'may need to plan for eventual pawn promotion and assuming a Queen is smart assumption.
  95. '
  96. ' 2017-11-13 T  fixed incheck failure and strange moves of king under check using a new shared flag Turn
  97. ' to let analize only the important pieces by INCHECK Function, they are different for White and for Black
  98. ' re-written in MAKEMOVE SUB (sub that makes the move on the board and check for promotion and makes the promotion if is the case
  99. ' the ELSE.. END IF part for white (Human) player is needed together INTFLAG  =1 humang chooses by himself piece in promotion, =0 autochoosed Queen
  100. ' also fixed extra q by inizilization of pWflag$ at start of SUB
  101. '
  102. '2017-11-15 B start work on Undo, Save and Load
  103. ' 2 functions cp2n(piece$), cn2p$(number), for converting a board to a bString$ letter and vice versa
  104. ' bString$ will get all board positions loaded in 64 character string
  105. ' bSetyp will setup a board from a bString$ used for UNDO, Save, Load and future SETUP
  106. ' Center text in a button
  107. ' Now reworked initBoard so initBlack sub can be eliminated and initBoard shrunk, now eliminated also!
  108. ' Now add stuff to make UNDO possible. new Boards$() array works along with Move$(), Boards$() has bString$ of board positions
  109. ' Incorp TempodiBasic changes to AI checking for Check (Chess 2_17-11-13 T) :
  110. '    Use new glabal varaible Turn = 1 for White's and -1 for Black, might come in handy! Yes on loading Game
  111. '        Eliminate the infinite crap I'd rather have AI King commiting suicide as a form of Resign for testing all other stuff
  112. '           Except Then AI plays old trick of putting oppenent into Check for which human is not allowed to take AI KING because in check!!! phooey!
  113. ' Moved ShowButton Bar and showMoveList into ShowBd and gave showMoveList a diet
  114. ' No more File recorder, eliminate Datetime, fix UNDO for trying to go less than 1
  115. ' Remove InitBoard sub, all done in getInput button section
  116.  
  117. ' Fix a ton of bugs to get all this integrated and working together but more keep popping up, blah!
  118. ' Make Result global to fix Y/N question to start over when Y
  119. ' Modify restart to clean slate the entire program, then use buttons to set particular settings needed
  120. ' Bug Loading a game right after Loading a game may cause an error
  121. ' Bug sometimes QB64 _FILEEXISTS says a real file that you typed correctly can't be found, just type it in again.
  122. ' I put a double _FILEEXISTS call in with delay between, helps but still the bug remains!!!
  123. ' Bug missing line when human loads a file playing black and starts game from there.
  124. ' Ugly fix that I doubt will work in other cases
  125.  
  126. '2017-11-16 A Tried to fix bug when AI is checkmated by modifying INCHECK function
  127. '             Minor changes - removed 1 set of board labels. display pieces centrally on squares
  128.  
  129. '2017-11-16 B Adrian some nice changes to board but please no PlayAgain: label, no GOTO unless best way
  130. ' I do not like ending the whole application in the InCheck sub,  nor do I think one time result <-2500 is cause to quit??
  131. ' Remember AI checks many moves with InCheck, I am afraid it might quit first time it gets result < -2500 with better result left.
  132. ' Also I fix my omission with loadFlag code in IO, and it turns out with UNDO we have to clear the capture amounts, fixed.
  133.  
  134. '2017-11-18 A1: Changed White King Value to 4500, Black King value to -9000. Added test for AI's resignation in IO SUB. This should fix the AI check bug, and probably means that the
  135. '           IN CHECK function need not check for checks to AI's king.
  136.  
  137. '2017-11-19 T: fixing the covering of the left border of buttonbar (Movelist too large passed from 700 to 680)
  138. ' 2017-11-22 T: fixing dummy _fileexists, it seems we don't need it yet
  139. ' 2017 11 22 T : coded manageDummySystem on save file, 1. now you can save only a game in progress  (no game = nothing to save)
  140. '                                                      2. now you can overwrite an existing file only if you confirm to overwrite it
  141. '                coded  feedback LoadFile in areaoutput
  142.  
  143.  
  144. CONST XMAX = 900
  145. CONST YMAX = 600
  146. CONST WHITE& = &HFFDDDDDD
  147. CONST BLACK& = &HFF000000
  148. CONST LITE& = &HFFFFFF00
  149. CONST LITE2& = _RGB32(78, 161, 72)
  150. CONST WHITES& = _RGB32(140, 160, 190)
  151. CONST BLACKS& = _RGB32(0, 130, 70)
  152. CONST SQ = 42
  153. 'T here (B out side of restart sub) we need a Maxlevel
  154. CONST MAXLEVEL = 5
  155. 'B might as well make constant!
  156.  
  157. 'B For fonts
  158. COMMON SHARED FW, FH, normal&, maxCol, bArial&, bFW, bFH
  159.  
  160. 'B For human playing Black
  161. COMMON SHARED playBlack, bmoves$, bFirst
  162.  
  163. 'B from original QB64 samples: chess.bas
  164. DIM SHARED BOARD(0 TO 7, 0 TO 7)
  165. DIM SHARED BESTA(0 TO 7), BESTB(0 TO 7), BESTX(0 TO 7), BESTY(0 TO 7)
  166. DIM SHARED LEVEL, SCORE, result
  167. DIM SHARED wcKsflag, wcQsflag, INTFLAG
  168. DIM SHARED wcKsold, wcQsold
  169.  
  170. 'B For saving moves to file
  171. DIM SHARED whiteMove$, blackMove$, pWflag$, pBflag$, GameFile$, Turn
  172.  
  173. 'B For displaying T's on screen list of moves, last 8 shown from Moves$() array
  174. DIM SHARED InGame, countMove, loadFlag
  175. REDIM SHARED Move$(1 TO 300)
  176.  
  177. 'B for Undo
  178. REDIM SHARED Boards$(1 TO 300)
  179.  
  180. 'B Using updated Graphics Screen instead of Screen 0 text program
  181. SCREEN _NEWIMAGE(XMAX, YMAX, 32)
  182. _SCREENMOVE 360, 60
  183.  
  184. 'B Checking fonts normal, big, and chess
  185. 'B load and check our normal font
  186. normal& = _LOADFONT("C:\windows\fonts\arial.ttf", 20)
  187. IF normal& <= 0 THEN PRINT "Trouble with arial.ttf size 16 file, goodbye.": SLEEP: END
  188. _FONT normal&
  189. FW = 11: FH = _FONTHEIGHT(normal&)
  190. maxCol = XMAX / FW
  191.  
  192. 'B load and check SQ size font
  193. bArial& = _LOADFONT("C:\windows\fonts\arial.ttf", SQ, "MONOSPACE")
  194. IF bArial& <= 0 THEN PRINT "Trouble with arial.ttf size "; SQ; " file, goodbye.": SLEEP: END
  195. bFW = _FONTWIDTH(bArial&): bFH = _FONTHEIGHT(bArial&)
  196.  
  197. Intro
  198. Wait_Click_Key
  199.     SCORE = 0
  200.     CALL IO(A, b, x, Y, result)
  201.     'B   HERE IS WHERE CHECKMATE NEEDS TO BE DETERMINED!!!
  202.     IF result < -2500 THEN
  203.         'T & B Human has won
  204.         AreaOutput "I RESIGN!! YOU WIN!!!", " Play Again? Y/N "
  205.         DO
  206.             Revenge$ = UCASE$(INKEY$)
  207.         LOOP UNTIL Revenge$ = "Y" OR Revenge$ = "N"
  208.         IF Revenge$ = "N" THEN
  209.             AreaOutput "Thanks for playing,", "Good Bye!"
  210.             SLEEP 2
  211.             SYSTEM
  212.         END IF
  213.         restart
  214.         InGame = 0
  215.     ELSE
  216.         result = EVALUATE(-1, 10000)
  217.         A = BESTA(1)
  218.         b = BESTB(1)
  219.         x = BESTX(1)
  220.         Y = BESTY(1)
  221.     END IF
  222.     CALL SHOWBD
  223.  
  224. '==========================================================
  225.  
  226. 'B sub for user communications area, T has made it for two strings
  227. SUB AreaOutput (outText$, out2$)
  228.     LINE (480, 510)-(XMAX, YMAX), BLACK&, BF
  229.     lp 26, 46, outText$
  230.     lp 27, 46, out2$
  231.  
  232. SUB BISHOP (A, B, XX(), YY(), NDX)
  233.     ID = SGN(BOARD(B, A))
  234.     FOR DXY = 1 TO 7
  235.         X = A - DXY
  236.         Y = B + DXY
  237.         IF X < 0 OR X > 7 OR Y < 0 OR Y > 7 THEN EXIT FOR
  238.         GOSUB 3
  239.         IF BOARD(Y, X) <> 0 THEN EXIT FOR
  240.     NEXT
  241.     FOR DXY = 1 TO 7
  242.         X = A + DXY
  243.         Y = B + DXY
  244.         IF X < 0 OR X > 7 OR Y < 0 OR Y > 7 THEN EXIT FOR
  245.         GOSUB 3
  246.         IF BOARD(Y, X) <> 0 THEN EXIT FOR
  247.     NEXT
  248.     FOR DXY = 1 TO 7
  249.         X = A - DXY
  250.         Y = B - DXY
  251.         IF X < 0 OR X > 7 OR Y < 0 OR Y > 7 THEN EXIT FOR
  252.         GOSUB 3
  253.         IF BOARD(Y, X) <> 0 THEN EXIT FOR
  254.     NEXT
  255.     FOR DXY = 1 TO 7
  256.         X = A + DXY
  257.         Y = B - DXY
  258.         IF X < 0 OR X > 7 OR Y < 0 OR Y > 7 THEN EXIT FOR
  259.         GOSUB 3
  260.         IF BOARD(Y, X) <> 0 THEN EXIT FOR
  261.     NEXT
  262.     EXIT SUB
  263.  
  264.     'sub gosub subroutine
  265.    3 REM
  266.     IF ID <> SGN(BOARD(Y, X)) THEN
  267.         NDX = NDX + 1
  268.         XX(NDX) = X
  269.         YY(NDX) = Y
  270.     END IF
  271.     RETURN
  272.  
  273. SUB bSetup (bStr$)
  274.     FOR X = 0 TO 7
  275.         FOR Y = 0 TO 7
  276.             p$ = MID$(bStr$, 8 * X + Y + 1, 1)
  277.             BOARD(X, Y) = cp2n(p$)
  278.         NEXT
  279.     NEXT
  280.  
  281. FUNCTION bString$
  282.     r$ = ""
  283.     FOR X = 0 TO 7
  284.         FOR Y = 0 TO 7
  285.             num = BOARD(X, Y)
  286.             r$ = r$ + cn2p$(num)
  287.         NEXT
  288.     NEXT
  289.     bString$ = r$
  290.  
  291. FUNCTION Castleincheck (x)
  292.     'T added to improve short castle control
  293.     IF playBlack THEN
  294.         BOARD(7, 1) = 4500
  295.         'T first square acrossed
  296.         null = INCHECK(x)
  297.         BOARD(7, 1) = 0
  298.         'T original square void
  299.         IF null = 0 THEN
  300.             'T if already in first test King is in check we skip second test
  301.             BOARD(7, 2) = 4500
  302.             'T second square acrossed
  303.             null = INCHECK(x)
  304.             BOARD(7, 2) = 0
  305.         END IF
  306.         Castleincheck = null
  307.     ELSE
  308.         BOARD(7, 6) = 4500
  309.         'T first square acrossed
  310.         null = INCHECK(x)
  311.         BOARD(7, 6) = 0
  312.         'T original square void
  313.         IF null = 0 THEN
  314.             'T if already in first test King is in check we skip second test
  315.             BOARD(7, 5) = 4500
  316.             'T second square acrossed
  317.             null = INCHECK(x)
  318.             BOARD(7, 5) = 0
  319.         END IF
  320.         Castleincheck = null
  321.     END IF
  322.  
  323. FUNCTION CastleincheckL (x)
  324.     'T added to improve long castle control
  325.     IF playBlack THEN
  326.         BOARD(7, 4) = 4500
  327.         null = INCHECK(x)
  328.         BOARD(7, 4) = 0
  329.         'T original square void
  330.         IF null = 0 THEN
  331.             'T if already in first test King is in check we skip second test
  332.             BOARD(7, 5) = 4500
  333.             'T C1 square
  334.             null = INCHECK(x)
  335.             BOARD(7, 5) = 0
  336.         END IF
  337.         CastleincheckL = null
  338.     ELSE
  339.         BOARD(7, 3) = 4500
  340.         'T or B or A D1 square
  341.         null = INCHECK(x)
  342.         BOARD(7, 3) = 0
  343.         'T original square void
  344.         IF null = 0 THEN
  345.             'T if already in first test King is in check we skip second test
  346.             BOARD(7, 2) = 4500
  347.             'T C1 square
  348.             null = INCHECK(x)
  349.             BOARD(7, 2) = 0
  350.         END IF
  351.         CastleincheckL = null
  352.     END IF
  353.  
  354. FUNCTION cn2p$ (n)
  355.     SELECT CASE n
  356.         CASE 0: r$ = "z"
  357.         CASE 100: r$ = "P"
  358.         CASE 270: r$ = "N"
  359.         CASE 300: r$ = "B"
  360.         CASE 500: r$ = "R"
  361.         CASE 900: r$ = "Q"
  362.         CASE 4500: r$ = "K"
  363.         CASE -100: r$ = "p"
  364.         CASE -270: r$ = "n"
  365.         CASE -300: r$ = "b"
  366.         CASE -500: r$ = "r"
  367.         CASE -900: r$ = "q"
  368.         CASE -9000: r$ = "k"
  369.     END SELECT
  370.     cn2p$ = r$
  371.  
  372. FUNCTION cp2n (piece$)
  373.     SELECT CASE piece$
  374.         CASE "z": r = 0
  375.         CASE "P": r = 100
  376.         CASE "N": r = 270
  377.         CASE "B": r = 300
  378.         CASE "R": r = 500
  379.         CASE "Q": r = 900
  380.         CASE "K": r = 4500
  381.         CASE "p": r = -100
  382.         CASE "n": r = -270
  383.         CASE "b": r = -300
  384.         CASE "r": r = -500
  385.         CASE "q": r = -900
  386.         CASE "k": r = -9000
  387.     END SELECT
  388.     cp2n = r
  389.  
  390. SUB cP (row, txt$)
  391.     'B on row center Print txt$
  392.     col = (maxCol - LEN(txt$)) / 2
  393.     _PRINTSTRING ((XMAX - _PRINTWIDTH(txt$)) / 2, row * FH), txt$
  394.  
  395. FUNCTION EVALUATE (ID, PRUNE)
  396.     DIM XX(0 TO 26), YY(0 TO 26)
  397.     LEVEL = LEVEL + 1
  398.     BESTSCORE = 10000 * ID
  399.     FOR b = 7 TO 0 STEP -1
  400.         FOR A = 7 TO 0 STEP -1
  401.             IF SGN(BOARD(b, A)) <> ID THEN GOTO 1
  402.             'Orig IF (LEVEL = 1) THEN CALL SHOWMAN(A, B)
  403.             'B this might be human versus human level?
  404.  
  405.             CALL MOVELIST(A, b, XX(), YY(), NDX)
  406.             FOR I = 0 TO NDX
  407.                 X = XX(I)
  408.                 Y = YY(I)
  409.                 IF LEVEL = 1 THEN
  410.                     AreaOutput "TRYING: " + CHR$(65 + A) + RIGHT$(STR$(8 - b), 1) + "-" + CHR$(65 + X) + RIGHT$(STR$(8 - Y), 1), ""
  411.                     'B Might as well make this look nice too, without the space
  412.                 END IF
  413.                 OLDSCORE = SCORE
  414.                 MOVER = BOARD(b, A)
  415.                 TARGET = BOARD(Y, X)
  416.                 CALL MAKEMOVE(A, b, X, Y)
  417.                 IF (LEVEL < MAXLEVEL) THEN SCORE = SCORE + EVALUATE(-ID, BESTSCORE - TARGET + ID * (8 - ABS(4 - X) - ABS(4 - Y)))
  418.                 SCORE = SCORE + TARGET - ID * (8 - ABS(4 - X) - ABS(4 - Y))
  419.                 IF (ID < 0 AND SCORE > BESTSCORE) OR (ID > 0 AND SCORE < BESTSCORE) THEN
  420.                     BESTA(LEVEL) = A
  421.                     BESTB(LEVEL) = b
  422.                     BESTX(LEVEL) = X
  423.                     BESTY(LEVEL) = Y
  424.                     BESTSCORE = SCORE
  425.                     IF (ID < 0 AND BESTSCORE >= PRUNE) OR (ID > 0 AND BESTSCORE <= PRUNE) THEN
  426.                         BOARD(b, A) = MOVER
  427.                         BOARD(Y, X) = TARGET
  428.                         SCORE = OLDSCORE
  429.                         LEVEL = LEVEL - 1
  430.                         EVALUATE = BESTSCORE
  431.                         EXIT FUNCTION
  432.                     END IF
  433.                 END IF
  434.                 BOARD(b, A) = MOVER
  435.                 BOARD(Y, X) = TARGET
  436.                 SCORE = OLDSCORE
  437.             NEXT
  438.        1 NEXT
  439.     NEXT
  440.     LEVEL = LEVEL - 1
  441.     EVALUATE = BESTSCORE
  442.  
  443. FUNCTION getInput$
  444.     DIM pieceChosen AS _BYTE
  445.     DO
  446.         'B Update board
  447.         SHOWBD
  448.  
  449.         'B gather mouse input
  450.         DO WHILE _MOUSEINPUT
  451.             mouseButton = _MOUSEBUTTON(1)
  452.             tx = _MOUSEX \ SQ - 1: ty = _MOUSEY \ SQ - 1
  453.             ux = tx: uy = ty
  454.         LOOP
  455.  
  456.         'T area of managing Button Bar
  457.         IF _MOUSEBUTTON(1) THEN
  458.             IF _MOUSEX > 700 THEN
  459.                 IF _MOUSEY < 120 THEN
  460.                     'B PLAY WHITE
  461.                     restart
  462.                     InGame = -1
  463.                     Turn = 1
  464.                     playBlack = 0
  465.                     bSetup "rnbqkbnrppppppppzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzPPPPPPPPRNBQKBNR"
  466.                     AreaOutput "Your move.", ""
  467.                     getInput$ = ""
  468.                     EXIT FUNCTION
  469.                 ELSEIF _MOUSEY < 180 THEN
  470.                     'B PLAY BLACK there was a FEN around here also
  471.  
  472.                     'T this is the FEN of initial game setup
  473.                     '  [rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1]
  474.                     restart
  475.                     InGame = -1
  476.                     Turn = -1
  477.                     playBlack = -1
  478.                     bSetup "rnbkqbnrppppppppzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzPPPPPPPPRNBKQBNR"
  479.                     getInput$ = ""
  480.                     EXIT FUNCTION
  481.                 ELSEIF _MOUSEY < 240 THEN
  482.                     'B UNDO
  483.                     IF countMove - 1 > 1 THEN
  484.                         Move$(countMove) = ""
  485.                         Boards$(countMove) = ""
  486.                         countMove = countMove - 1
  487.                         whiteMove$ = "": blackMove$ = "": bmoves$ = "": bFirst = -1
  488.                         bSetup Boards$(countMove)
  489.                         IF playBlack = 0 THEN AreaOutput "Your move.", ""
  490.                         '_DISPLAY
  491.                         EXIT FUNCTION
  492.                     END IF
  493.                 ELSEIF _MOUSEY < 300 THEN
  494.                     'B SAVE BOARD
  495.                     'T if you are not in game what are you saving in a file?
  496.                     IF InGame = 0 THEN EXIT FUNCTION
  497.                     ' T file exists, overwirte? Y/N
  498.                     DO
  499.                         in$ = ""
  500.                         in$ = screenInput(50 * FW, 4 * FH, "Enter Save Filename > ")
  501.                         IF _FILEEXISTS(in$) = -1 AND in$ <> "" THEN
  502.                             COLOR LITE&
  503.                             AreaOutput "File exists...", " Overwrite Y/N?"
  504.                             _DISPLAY
  505.                             COLOR WHITE&
  506.                             choice$ = UCASE$(INPUT$(1))
  507.                             IF choice$ = "Y" THEN EXIT DO
  508.                         ELSE
  509.                             ' case _fileexists(in$) = 0
  510.                             EXIT DO
  511.                         END IF
  512.  
  513.                     LOOP
  514.  
  515.                     OPEN in$ FOR OUTPUT AS #1
  516.                     IF playBlack THEN PRINT #1, "Black" ELSE PRINT #1, "White"
  517.                     PRINT #1, blackMove$
  518.                     'we need AI's move made if any since last Move$() entry
  519.                     FOR i = 1 TO countMove
  520.                         PRINT #1, Move$(i)
  521.                     NEXT
  522.                     FOR i = 1 TO countMove
  523.                         PRINT #1, Boards$(i)
  524.                     NEXT
  525.                     CLOSE #1
  526.                     AreaOutput "File " + ins$, "loaded"
  527.                     _DELAY 1
  528.                     IF playBlack = 0 THEN
  529.                         AreaOutput "Your move.", ""
  530.                     ELSE
  531.                         bmove$ = blackMove$
  532.                         bFirst = 0
  533.                     END IF
  534.                     getInput$ = ""
  535.                     EXIT FUNCTION
  536.                 ELSEIF _MOUSEY < 360 THEN
  537.                     'B  LOAD Board
  538.                     in$ = screenInput(50 * FW, 4 * FH, "Enter Load Filename > ")
  539.                     'B  for some damn reason the first time you try _FILEEXISTS with real file it says 0 nope!
  540.                     'B                 but try again and is OK ?????????????????????????????????????????
  541.                     'B                 So f... IT!
  542.                     ' dummy = _FILEEXISTS(in$)
  543.                     '_DELAY 1
  544.                     'B  once is not enough, damn this sucks!!!!!!
  545.                     'dummy = _FILEEXISTS(in$)
  546.                     '_DELAY 1
  547.                     'B  nope didn't help with 2nd call and delay, just try LOAD GAME again!
  548.                     IF _FILEEXISTS(in$) = -1 THEN
  549.  
  550.                         count = 0
  551.                         OPEN in$ FOR INPUT AS #1
  552.                         WHILE EOF(1) = 0
  553.                             INPUT #1, l$
  554.                             count = count + 1
  555.                         WEND
  556.                         CLOSE #1
  557.  
  558.                         ' T feedback to user
  559.                         COLOR LITE&
  560.                         AreaOutput "File loaded", in$
  561.                         COLOR WHITE&
  562.                         _DISPLAY
  563.                         _DELAY 1
  564.  
  565.                         restart
  566.                         countMove = (count - 2) / 2
  567.                         'B This gets needed data items before loading 2 arrays of size countMove
  568.                         OPEN in$ FOR INPUT AS #1
  569.                         INPUT #1, BW$
  570.                         IF LEFT$(BW$, 1) = "B" THEN playBlack = -1 ELSE playBlack = 0
  571.                         INPUT #1, blackMove$
  572.                         'B  this gets AI's last move (if any) not recorded in Move$()
  573.                         '   OK maybe we have to pretend the blackMove$ is whiteMove$ so IO can reverse it when recording in Move$()
  574.                         FOR i = 1 TO countMove
  575.                             INPUT #1, Move$(i)
  576.                         NEXT
  577.                         FOR i = 1 TO countMove
  578.                             INPUT #1, Boards$(i)
  579.                         NEXT
  580.                         CLOSE #1
  581.                         CLS
  582.                         bSetup Boards$(countMove)
  583.                         'B loadFlag is ugly way to fix a missing line in move list that occurs loading a game with human playing Black
  584.                         IF playBlack = 0 THEN AreaOutput "Your move.", "" ELSE loadFlag = -1
  585.                         InGame = -1
  586.                     ELSE
  587.                         AreaOutput in$, "File not found."
  588.                     END IF
  589.                 ELSEIF _MOUSEY < 420 THEN
  590.                     'B MANUAL SET
  591.                 ELSEIF _MOUSEY < 480 THEN
  592.                     'T quit
  593.                     getInput$ = "QUIT"
  594.                     EXIT FUNCTION
  595.                 END IF
  596.             END IF
  597.         END IF
  598.  
  599.         IF InGame = -1 THEN
  600.             IF pieceChosen = 0 THEN
  601.                 IF 1 <= ty AND ty <= 8 THEN
  602.                     'Fellippe or B translate hovered coordinate to chess notation letter + digit
  603.                     d$ = RIGHT$(STR$(9 - ty), 1)
  604.                     IF 1 <= tx AND tx <= 8 THEN
  605.                         l$ = CHR$(64 + tx)
  606.                         ld$ = l$ + d$
  607.                         'B letter + digit
  608.                         ld2xy ld$, bx, by
  609.                         'B translate notation to board$(x, y)
  610.                         IF BOARD(by, bx) > 0 THEN
  611.                             LegalShow bx, by
  612.                             highLightSq bx, by, LITE2&
  613.                             'Fellippe hover highlight
  614.                             IF mouseButton THEN
  615.                                 DO WHILE mouseButton
  616.                                     'Fellippe wait for release
  617.                                     i = _MOUSEINPUT
  618.                                     mouseButton = _MOUSEBUTTON(1)
  619.                                     newtx = _MOUSEX \ SQ - 1: newty = _MOUSEY \ SQ - 1
  620.                                 LOOP
  621.                                 IF newtx = tx AND newty = ty THEN
  622.                                     'Fellippe the mouse was released in the same square
  623.                                     pieceChosen = -1: chosenBX = bx: chosenBY = by
  624.                                 END IF
  625.                             END IF
  626.                         END IF
  627.                     END IF
  628.                 END IF
  629.             ELSE
  630.                 LegalShow chosenBX, chosenBY
  631.                 highLightSq chosenBX, chosenBY, LITE&
  632.                 IF 1 <= uy AND uy <= 8 THEN
  633.                     'B translate click to chess notation letter + digit
  634.                     d2$ = RIGHT$(STR$(9 - uy), 1)
  635.                     IF 1 <= ux AND ux <= 8 THEN
  636.                         l2$ = CHR$(64 + ux)
  637.                         ld2$ = l2$ + d2$
  638.                         'B letter + digit
  639.                         ld2xy ld2$, bx2, by2
  640.                         highLightSq bx2, by2, LITE2&
  641.                         'Fellippe hover highlight
  642.                         IF mouseButton THEN
  643.                             DO WHILE mouseButton
  644.                                 'Fellippe wait for release
  645.                                 i = _MOUSEINPUT
  646.                                 mouseButton = _MOUSEBUTTON(1)
  647.                                 newtx = _MOUSEX \ SQ - 1: newty = _MOUSEY \ SQ - 1
  648.                             LOOP
  649.                             IF newtx = tx AND newty = ty THEN
  650.                                 'Fellippe the mouse was released in the same square
  651.                                 IF ld$ <> ld2$ THEN
  652.                                     getInput$ = ld$ + "-" + ld2$
  653.                                     'T this let AI to castle for white
  654.                                     IF BOARD(by, bx) = 4500 THEN
  655.                                         IF ld$ = "E1" AND ld2$ = "G1" THEN getInput$ = "O-O"
  656.                                         IF ld$ = "E1" AND ld2$ = "C1" THEN getInput$ = "O-O-O"
  657.                                         IF playBlack = -1 THEN
  658.                                             IF ld$ = "D1" AND ld2$ = "B1" THEN getInput$ = "O-O"
  659.                                             IF ld$ = "D1" AND ld2$ = "F1" THEN getInput$ = "O-O-O"
  660.                                         END IF
  661.                                     END IF
  662.                                     _AUTODISPLAY
  663.                                     EXIT FUNCTION
  664.                                 ELSE
  665.                                     LegalHide bx, by
  666.                                     SHOWMAN bx, by
  667.                                     EXIT DO
  668.                                 END IF
  669.                                 'B ld compare
  670.                             END IF
  671.                         END IF
  672.                     END IF
  673.                     'B ux compare
  674.                 END IF
  675.                 'B uy compare
  676.             END IF
  677.             'B piece chosen yet
  678.  
  679.             'B handle keyboard input
  680.             k$ = INKEY$
  681.             IF k$ <> "" THEN
  682.                 IF LEN(k$) = 1 THEN
  683.                     IF ASC(k$) = 11 THEN
  684.                         in$ = screenInput(50 * FW, 4 * FH, "(Esc to quit) Enter Move > ")
  685.                         in$ = UCASE$(in$)
  686.                         spac = INSTR(in$, " ")
  687.                         IF spac THEN in$ = MID$(in$, 1, spac - 1) + "-" + MID$(in$, spac + 1)
  688.                         IF playBlack THEN in$ = w2b$(in$)
  689.                         getInput$ = in$
  690.                         EXIT FUNCTION
  691.                     ELSEIF ASC(k$) = 27 THEN
  692.                         END
  693.                     END IF
  694.                 END IF
  695.             END IF
  696.         END IF
  697.         'B if InGame
  698.         _DISPLAY
  699.     LOOP
  700.     lastLD$ = ""
  701.     getInput$ = in$
  702.  
  703. SUB highLightSq (bx, by, c&)
  704.     LINE ((bx + 2) * SQ, (by + 2) * SQ)-((bx + 3) * SQ, (by + 3) * SQ), , B
  705.     LINE ((bx + 2) * SQ + 1, (by + 2) * SQ + 1)-((bx + 3) * SQ - 1, (by + 3) * SQ - 1), c&, B
  706.     LINE ((bx + 2) * SQ + 2, (by + 2) * SQ + 2)-((bx + 3) * SQ - 2, (by + 3) * SQ - 2), c&, B
  707.  
  708. FUNCTION INCHECK (X)
  709.     DIM XX(27), YY(27), NDX
  710.     FOR b = 0 TO 7
  711.         FOR A = 0 TO 7
  712.  
  713.             IF BOARD(b, A) = 0 THEN GOTO 6
  714.             'T original code BOARD(b,A) >= 0  if white piece or void square skip test
  715.             'A: omit square skip test
  716.             'B Adrian next line is OK, it just skips empty spaces in board
  717.  
  718.             CALL MOVELIST(A, b, XX(), YY(), NDX)
  719.             FOR I = 0 TO NDX STEP 1
  720.                 X = XX(I)
  721.                 Y = YY(I)
  722.                 IF BOARD(Y, X) = 4500 AND Turn = 1 THEN
  723.                     'B ^^^ 2017-11-13 T has added and turn = 1 but turn = 1 is same as playBlack = 0
  724.                     AreaOutput "YOU ARE IN CHECK!", ""
  725.                     INCHECK = 1
  726.                     EXIT FUNCTION
  727.                 END IF
  728.                 IF BOARD(Y, X) = -9000 AND Turn = -1 THEN
  729.                     'B ^^^ 2017-11-13 T has added and turn = -1 but turn = -1 is same as playBlack = -1
  730.                     ' T in my last read of code posted playBack is used to note that Human plays as black
  731.                     ' T Turn is used for knowing if the move  has been made by black Turn = -1 or by White Turn = 1
  732.                     AreaOutput "I AM IN CHECK!", ""
  733.  
  734.                     'T this show Black status incheck
  735.                     INCHECK = -1 'A: this is probably no longer needed
  736.                     'T this should stop failed moves under check attack
  737.                     'EXIT FUNCTION
  738.                     'B exit now and get infinite loop?
  739.                     ' T AI force must exit from loop
  740.                 END IF
  741.             NEXT
  742.        6 NEXT
  743.     NEXT
  744.     INCHECK = 0
  745.  
  746. SUB initBoard
  747.     IF playBlack THEN
  748.         b$ = "rnbkqbnrppppppppzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzPPPPPPPPRNBKQBNR"
  749.     ELSE
  750.         b$ = "rnbqkbnrppppppppzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzPPPPPPPPRNBQKBNR"
  751.     END IF
  752.     bSetup b$
  753.  
  754. SUB Intro
  755.     'T better have a subroutine that we can use as many as we want
  756.     COLOR WHITE&, BLACK&
  757.     cP 3, "QB64 CHESS"
  758.     lp 5, 8, "CHESS is a game played between two players on a board of 64 squares."
  759.     lp 6, 4, "Chess was first invented in its current form in Europe during the late"
  760.     lp 7, 4, "fifteenth century. It evolved from much earlier forms invented in India"
  761.     lp 8, 4, "and Persia."
  762.     lp 9, 8, "The pieces are divided into Black and White.  Each player has 16 pieces:"
  763.     lp 10, 4, "1 king, 1 queen, 2 rooks, 2 bishops, 2 knights, and 8 pawns.  White makes"
  764.     lp 11, 4, "the first move.  The players alternate moving one piece at a time.  Pieces"
  765.     lp 12, 4, "are moved to an unoccupied square, or moved onto a square occupied by an"
  766.     lp 13, 4, "opponent's piece, capturing it.  When the king is under attack, he is in"
  767.     lp 14, 4, "CHECK.  The player cannot put his king in check.  The object is to CHECKMATE"
  768.     lp 15, 4, "the opponent.  This occurs when the king is in check and there is no way to"
  769.     lp 16, 4, "remove the king from attack."
  770.     lp 17, 8, "To move the pieces on the chessboard, click by mouse or type after Ctrl+K"
  771.     lp 18, 4, "notation, e.g. E2-E4 (not in English notation like P-K4).  To castle, type O-O"
  772.     lp 19, 4, "to castle kingside or O-O-O to castle queenside like in English notation."
  773.     lp 20, 4, "To exit the game, type QUIT or press ESCAPE key."
  774.     cP 25, "Click or press any key to continue."
  775.  
  776. SUB IO (A, B, X, Y, RESULT)
  777.     DIM XX(0 TO 26), YY(0 TO 26)
  778.     IF InGame THEN
  779.         'B ugly fix to get a missing line recorded in move list when load file and human playing black
  780.         IF loadFlag AND blackMove$ <> "" THEN
  781.             loadFlag = 0
  782.             countMove = countMove + 1
  783.             Move$(countMove) = blackMove$ + pBflag$ + "  " + whiteMove$ + pWflag$
  784.             'B this above is so ugly I even have to reverse black and white to get it right!
  785.             Boards$(countMove) = bString$
  786.             'B this above was omitted in versions before 11-16, still not right???
  787.         END IF
  788.  
  789.         IF A >= 0 THEN
  790.             Turn = -1
  791.             IF RESULT < -2500 THEN EXIT SUB 'AI should resign
  792.             PIECE = BOARD(Y, X)
  793.             CALL MAKEMOVE(A, B, X, Y)
  794.             'T (chess2_17-11-13 T) this will fix illegal moves of AI under check
  795.             NULL = INCHECK(0)
  796.             'T (chess2_17-11-13 T) we must search for check after choosing a move
  797.  
  798.             'B Adrian, can't have game end here, many moves are checked can't quit if one is bad
  799.             'IF NULL = -1 AND RESULT < -2500 THEN
  800.             '    AreaOutput "AI resigns!", ""
  801.             '    EXIT SUB
  802.             'END IF
  803.  
  804.             IF NULL THEN
  805.                 'T (chess2_17-11-13 T) if there is a check for AI we must restore situation before move
  806.                 BOARD(B, A) = BOARD(Y, X)
  807.                 BOARD(Y, X) = PIECE
  808.                 EXIT SUB
  809.                 'T (chess2_17-11-13 T) if it is check move is illegal
  810.             END IF
  811.             'T this show Black status incheck
  812.  
  813.             mymove$ = CHR$(65 + A) + RIGHT$(STR$(8 - B), 1) + "-" + CHR$(65 + X) + RIGHT$(STR$(8 - Y), 1)
  814.  
  815.             'B ??? next line not used
  816.             'AICHECK = 0 'reset AI check flag
  817.  
  818.             IF playBlack THEN mymove$ = w2b$(mymove$)
  819.             AreaOutput "MY MOVE: " + mymove$, ""
  820.             blackMove$ = mymove$
  821.             IF whiteMove$ <> "" THEN
  822.                 IF playBlack THEN whiteMove$ = w2b$(whiteMove$)
  823.             END IF
  824.             WriteEntry
  825.         END IF
  826.         'B & T >>> it saves the last moves to file and to list I move this IF HERE TO GET THE COUPLE WHITE+BLACK
  827.  
  828.         IF PIECE <> 0 THEN
  829.             s$ = "I TOOK YOUR "
  830.             IF PIECE = 100 THEN s$ = s$ + "PAWN           "
  831.             IF PIECE = 270 THEN s$ = s$ + "KNIGHT         "
  832.             IF PIECE = 300 THEN s$ = s$ + "BISHOP         "
  833.             IF PIECE = 500 THEN s$ = s$ + "ROOK           "
  834.             IF PIECE = 900 THEN s$ = s$ + "QUEEN          "
  835.             IF PIECE = 4500 THEN s$ = s$ + "KING          "
  836.             AreaOutput "", s$
  837.         END IF
  838.  
  839.     END IF
  840.  
  841.     DO
  842.         'B I think this was help from Adrian, so we didn't have to fake a move
  843.         IF playBlack = -1 AND countMove = 0 THEN countMove = 1: EXIT SUB
  844.  
  845.         'B Here we get Human's move but might be illegal so AI has to check before shown
  846.         in$ = getInput$
  847.         'T getinput$ takes user's input also for BUTTONBAR
  848.         'B which is why we have to have to check InGame
  849.  
  850.         IF UCASE$(in$) = "QUIT" THEN END
  851.  
  852.         IF InGame = -1 THEN
  853.             whiteMove$ = in$
  854.             'B ^^^ Human's move who now plays Black or White, don't be fooled by variable name>
  855.             'B Originally human always played white>
  856.             Turn = 1
  857.             IF UCASE$(in$) = "O-O" OR in$ = "0-0" THEN
  858.                 'T short castle rules... here we improve control of check and moves
  859.                 IF wcKsflag <> 0 THEN GOTO 16
  860.                 ' T it skips white castle king
  861.                 IF playBlack THEN
  862.                     IF BOARD(7, 0) <> 500 THEN GOTO 16
  863.                     IF BOARD(7, 1) <> 0 OR BOARD(7, 2) <> 0 THEN GOTO 16
  864.                 ELSE
  865.                     IF BOARD(7, 7) <> 500 THEN GOTO 16
  866.                     IF BOARD(7, 6) <> 0 OR BOARD(7, 5) <> 0 THEN GOTO 16
  867.                 END IF
  868.                 'T now we test if there is a check along the path of king
  869.                 NULL = Castleincheck(0)
  870.                 IF NULL = 0 THEN
  871.                     'B you can castle king side
  872.                     IF playBlack THEN
  873.                         BOARD(7, 1) = 4500
  874.                         BOARD(7, 3) = 0
  875.                         BOARD(7, 2) = 500
  876.                         BOARD(7, 0) = 0
  877.                         wcKsflag = -1
  878.                         'T black castle king side
  879.                         whiteMove$ = "O-O"
  880.                         EXIT SUB
  881.                     ELSE
  882.                         BOARD(7, 6) = 4500
  883.                         BOARD(7, 4) = 0
  884.                         BOARD(7, 5) = 500
  885.                         BOARD(7, 7) = 0
  886.                         wcKsflag = -1
  887.                         'T white castle king side
  888.                         whiteMove$ = "O-O"
  889.                         EXIT SUB
  890.                     END IF
  891.                 END IF
  892.             END IF
  893.             IF UCASE$(in$) = "O-O-O" OR in$ = "0-0-0" THEN
  894.                 'T long castle rules... here we improve control of check and moves
  895.                 IF wcQsflag <> 0 THEN GOTO 16
  896.                 IF playBlack THEN
  897.                     IF BOARD(7, 7) <> 500 THEN GOTO 16
  898.                     IF BOARD(7, 6) <> 0 OR BOARD(7, 5) <> 0 OR BOARD(7, 4) <> 0 THEN GOTO 16
  899.                 ELSE
  900.                     IF BOARD(7, 0) <> 500 THEN GOTO 16
  901.                     IF BOARD(7, 1) <> 0 OR BOARD(7, 2) <> 0 OR BOARD(7, 3) <> 0 THEN GOTO 16
  902.                 END IF
  903.                 'T now we test if there is a check along the path of king
  904.                 NULL = CastleincheckL(0)
  905.                 IF NULL = 0 THEN
  906.                     'B you can castle queen side
  907.                     IF playBlack THEN
  908.                         BOARD(7, 5) = 4500
  909.                         BOARD(7, 3) = 0
  910.                         BOARD(7, 4) = 500
  911.                         BOARD(7, 7) = 0
  912.                         wcQsflag = -1
  913.                         'T black castle queen side
  914.                         whiteMove$ = "O-O-O"
  915.                         EXIT SUB
  916.                     ELSE
  917.                         'T you can castle if there are no check to the king to the start or during the movement of castle
  918.                         BOARD(7, 2) = 4500
  919.                         BOARD(7, 4) = 0
  920.                         BOARD(7, 3) = 500
  921.                         BOARD(7, 0) = 0
  922.                         wcQsflag = -1
  923.                         'T white castle queen side
  924.                         whiteMove$ = "O-O-O"
  925.                         EXIT SUB
  926.                     END IF
  927.                 END IF
  928.             END IF
  929.             IF LEN(in$) < 5 THEN GOTO 16
  930.             B = 8 - (ASC(MID$(in$, 2, 1)) - 48)
  931.             A = ASC(UCASE$(MID$(in$, 1, 1))) - 65
  932.             X = ASC(UCASE$(MID$(in$, 4, 1))) - 65
  933.             Y = 8 - (ASC(MID$(in$, 5, 1)) - 48)
  934.             IF B > 7 OR B < 0 OR A > 7 OR A < 0 OR X > 7 OR X < 0 OR Y > 7 OR Y < 0 THEN GOTO 16
  935.             IF BOARD(B, A) <= 0 THEN GOTO 16
  936.             IF Y = 2 AND B = 3 AND (X = A - 1 OR X = A + 1) THEN
  937.                 IF BOARD(B, A) = 100 AND BOARD(Y, X) = 0 AND BOARD(Y + 1, X) = -100 THEN
  938.                     IF BESTB(1) = 1 AND BESTA(1) = X THEN
  939.                         MOVER = BOARD(B, A)
  940.                         TARGET = BOARD(Y, X)
  941.                         CALL MAKEMOVE(A, B, X, Y)
  942.                         BOARD(Y + 1, X) = 0
  943.                         ENPASSANT = -1
  944.                         GOTO 15
  945.                     END IF
  946.                 END IF
  947.             END IF
  948.             CALL MOVELIST(A, B, XX(), YY(), NDX)
  949.             FOR K = 0 TO NDX STEP 1
  950.                 IF X = XX(K) AND Y = YY(K) THEN
  951.                     MOVER = BOARD(B, A)
  952.                     TARGET = BOARD(Y, X)
  953.  
  954.                     INTFLAG = -1
  955.                     'B so this is where INTFLAG is set
  956.  
  957.                     CALL MAKEMOVE(A, B, X, Y)
  958.                     IF MOVER = 4500 THEN
  959.                         wcQsold = wcQsflag
  960.                         wcKsold = wcKsflag
  961.                         wcKsflag = -1
  962.                         wcQsflag = -1
  963.                     END IF
  964.                     IF (A = 0) AND (B = 7) AND (MOVER = 500) THEN
  965.                         wcQsold = wcQsflag
  966.                         wcQsflag = -1
  967.                     END IF
  968.                     IF (A = 7) AND (B = 7) AND (MOVER = 500) THEN
  969.                         wcKsold = wcKsflag
  970.                         wcKsflag = -1
  971.                     END IF
  972.  
  973.                     INTFLAG = 0
  974.                     'B and this is where INTFLAG is unset!
  975.  
  976.                     15 IF INCHECK(0) = 0 THEN EXIT SUB
  977.  
  978.                     BOARD(B, A) = MOVER
  979.                     BOARD(Y, X) = TARGET
  980.                     IF ENPASSANT THEN BOARD(Y + 1, X) = -100: ENPASSANT = 0
  981.                     IF (A = 0) AND (B = 7) AND (MOVER = 500) THEN wcQsflag = wcQsold
  982.                     IF (A = 7) AND (B = 7) AND (MOVER = 500) THEN wcKsflag = wcKsold
  983.                     IF MOVER = 4500 THEN wcQsflag = wcQsold
  984.                     GOTO 16
  985.                 END IF
  986.             NEXT
  987.         END IF
  988.        16
  989.  
  990.     LOOP
  991.     'B OK so this keeps looping until white makes legal move?
  992.  
  993.  
  994. FUNCTION isWhite (x, y)
  995.     'B for squares and old for chess font
  996.     yes = 0
  997.     IF y MOD 2 = 0 THEN
  998.         IF x MOD 2 = 0 THEN
  999.             yes = -1
  1000.         END IF
  1001.     ELSE
  1002.         IF x MOD 2 = 1 THEN
  1003.             yes = -1
  1004.         END IF
  1005.     END IF
  1006.     isWhite = yes
  1007.  
  1008. SUB KING (A, B, XX(), YY(), NDX)
  1009.     ID = SGN(BOARD(B, A))
  1010.     FOR DY = -1 TO 1
  1011.         IF B + DY < 0 OR B + DY > 7 THEN GOTO 12
  1012.         FOR DX = -1 TO 1
  1013.             IF A + DX < 0 OR A + DX > 7 THEN GOTO 11
  1014.             IF ID <> SGN(BOARD(B + DY, A + DX)) THEN
  1015.                 NDX = NDX + 1
  1016.                 XX(NDX) = A + DX
  1017.                 YY(NDX) = B + DY
  1018.             END IF
  1019.        11 NEXT
  1020.    12 NEXT
  1021.  
  1022. SUB KNIGHT (A, B, XX(), YY(), NDX)
  1023.     ID = SGN(BOARD(B, A))
  1024.     X = A - 1
  1025.     Y = B - 2
  1026.     GOSUB 5
  1027.     X = A - 2
  1028.     Y = B - 1
  1029.     GOSUB 5
  1030.     X = A + 1
  1031.     Y = B - 2
  1032.     GOSUB 5
  1033.     X = A + 2
  1034.     Y = B - 1
  1035.     GOSUB 5
  1036.     X = A - 1
  1037.     Y = B + 2
  1038.     GOSUB 5
  1039.     X = A - 2
  1040.     Y = B + 1
  1041.     GOSUB 5
  1042.     X = A + 1
  1043.     Y = B + 2
  1044.     GOSUB 5
  1045.     X = A + 2
  1046.     Y = B + 1
  1047.     GOSUB 5
  1048.     EXIT SUB
  1049.    5 REM
  1050.     IF X < 0 OR X > 7 OR Y < 0 OR Y > 7 THEN RETURN
  1051.     IF ID <> SGN(BOARD(Y, X)) THEN NDX = NDX + 1: XX(NDX) = X: YY(NDX) = Y
  1052.     RETURN
  1053.  
  1054. SUB ld2xy (ld$, dx, dy)
  1055.     'B dx and dy are going to be changed to find
  1056.     'B position (and thus type) of piece on the board from ld$
  1057.     letter$ = UCASE$(LEFT$(ld$, 1))
  1058.     dx = ASC(letter$) - 65
  1059.     digit = VAL(RIGHT$(ld$, 1))
  1060.     dy = 8 - digit
  1061.  
  1062. SUB LegalHide (x, y)
  1063.     DIM XX(0 TO 26), YY(0 TO 26)
  1064.     CALL MOVELIST(x, y, XX(), YY(), NDX)
  1065.     FOR a = 0 TO NDX STEP 1
  1066.         IF XX(a) >= 0 AND YY(a) >= 0 THEN SHOWMAN YY(a), XX(a)
  1067.     NEXT
  1068.  
  1069. 'T THIS SUB calculates legal position of piece in the board cell x,y
  1070. SUB LegalShow (x, y)
  1071.     DIM XX(0 TO 26), YY(0 TO 26)
  1072.     CALL MOVELIST(x, y, XX(), YY(), NDX)
  1073.     FOR a = 0 TO NDX STEP 1
  1074.         IF XX(a) >= 0 AND YY(a) >= 0 THEN highLightSq XX(a), YY(a), LITE2&
  1075.     NEXT
  1076.  
  1077. 'B graphics version of Locate col, row : Print txt$
  1078. SUB lp (row, col, txt$)
  1079.     _PRINTSTRING (col * FW, row * FH), txt$
  1080.  
  1081. SUB MakeButton (x1, y1, x2, y2, txt$, Col&)
  1082.     LINE (x1, y1)-(x2, y2), Col&, BF
  1083.     LINE (x1, y1)-(x2, y2), WHITE&, B
  1084.     LINE (x1 + 4, y2 - 4)-(x2 - 4, y2 - 4), _RGB32(222, 238, 227), B
  1085.     LINE (x2 - 4, y2 - 4)-(x2 - 4, y1 + 4), _RGB32(222, 238, 227), B
  1086.     'B VVV let's print button labels in middle of button
  1087.     _PRINTSTRING (x1 + 15, y2 - 1.35 * FH), txt$
  1088.  
  1089. SUB MAKEMOVE (A, B, X, Y)
  1090.     'B makemove is called many times, the last decides whether pBflag$ gets set or NOT
  1091.     'B the pWflag$ should only be set by user, no automatic setting allowed by AI.
  1092.     pBflag$ = ""
  1093.     BOARD(Y, X) = BOARD(B, A)
  1094.     BOARD(B, A) = 0
  1095.     IF Y = 0 AND BOARD(Y, X) = 100 THEN
  1096.         ' T it is the row 8
  1097.         IF INTFLAG THEN
  1098.             DO
  1099.                 AreaOutput "Promote to:", ""
  1100.                 I$ = Ppromote$
  1101.                 SELECT CASE UCASE$(I$)
  1102.                     CASE "KNIGHT", "N", "KT", "KT.", "N."
  1103.                         PROMOTE = 270: pWflag$ = "N"
  1104.                     CASE "BISHOP", "B", "B."
  1105.                         PROMOTE = 300: pWflag$ = "B"
  1106.                     CASE "ROOK", "R", "R."
  1107.                         PROMOTE = 500: pWflag$ = "R"
  1108.                     CASE "QUEEN", "Q", "Q."
  1109.                         PROMOTE = 900: pWflag$ = "Q"
  1110.                 END SELECT
  1111.             LOOP UNTIL PROMOTE <> 0
  1112.             IF playBlack THEN pWflag$ = LCASE$(pWflag$)
  1113.             'B       only the human can set the pWflag$
  1114.  
  1115.             BOARD(Y, X) = PROMOTE
  1116.             CLS
  1117.             SHOWBD
  1118.             _DISPLAY
  1119.         ELSE
  1120.             BOARD(Y, X) = 900
  1121.             'B ^^^^ OK AI need the line for checking FUTURE!!! moves
  1122.         END IF
  1123.     END IF
  1124.  
  1125.     IF Y = 7 AND BOARD(Y, X) = -100 THEN
  1126.         rap = -1
  1127.         BOARD(Y, X) = -900
  1128.         IF playBlack THEN pBflag$ = "Q" ELSE pBflag$ = "q"
  1129.     END IF
  1130.  
  1131.  
  1132. SUB MOVELIST (A, B, XX(), YY(), NDX)
  1133.     PIECE = INT(ABS(BOARD(B, A)))
  1134.     NDX = -1
  1135.     SELECT CASE PIECE
  1136.         CASE IS = 100
  1137.             CALL PAWN(A, B, XX(), YY(), NDX)
  1138.         CASE IS = 270
  1139.             CALL KNIGHT(A, B, XX(), YY(), NDX)
  1140.         CASE IS = 300
  1141.             CALL BISHOP(A, B, XX(), YY(), NDX)
  1142.         CASE IS = 500
  1143.             CALL ROOK(A, B, XX(), YY(), NDX)
  1144.         CASE IS = 900
  1145.             CALL QUEEN(A, B, XX(), YY(), NDX)
  1146.         CASE IS = 4500
  1147.             CALL KING(A, B, XX(), YY(), NDX)
  1148.         CASE IS = 9000
  1149.             CALL KING(A, B, XX(), YY(), NDX)
  1150.     END SELECT
  1151.  
  1152. SUB PAWN (A, B, XX(), YY(), NDX)
  1153.     ID = SGN(BOARD(B, A))
  1154.     ' T ID 1 for white piece and -1 for black piece
  1155.     IF (A - 1) >= 0 AND (A - 1) <= 7 AND (B - ID) >= 0 AND (B - ID) <= 7 THEN
  1156.         IF SGN(BOARD((B - ID), (A - 1))) = -ID THEN
  1157.             NDX = NDX + 1
  1158.             XX(NDX) = A - 1
  1159.             YY(NDX) = B - ID
  1160.         END IF
  1161.     END IF
  1162.     IF (A + 1) >= 0 AND (A + 1) <= 7 AND (B - ID) >= 0 AND (B - ID) <= 7 THEN
  1163.         IF SGN(BOARD((B - ID), (A + 1))) = -ID THEN
  1164.             NDX = NDX + 1
  1165.             XX(NDX) = A + 1
  1166.             YY(NDX) = B - ID
  1167.         END IF
  1168.     END IF
  1169.     IF A >= 0 AND A <= 7 AND (B - ID) >= 0 AND (B - ID) <= 7 THEN
  1170.         IF BOARD((B - ID), A) = 0 THEN
  1171.             NDX = NDX + 1
  1172.             XX(NDX) = A
  1173.             YY(NDX) = B - ID
  1174.             IF (ID < 0 AND B = 1) OR (ID > 0 AND B = 6) THEN
  1175.                 IF BOARD((B - ID - ID), A) = 0 THEN
  1176.                     NDX = NDX + 1
  1177.                     XX(NDX) = A
  1178.                     YY(NDX) = B - ID - ID
  1179.                 END IF
  1180.             END IF
  1181.         END IF
  1182.     END IF
  1183.  
  1184.  
  1185. 'B a pawn needs promotion to a piece, which? use mouse or keyboard
  1186. FUNCTION Ppromote$
  1187.     inp$ = "": ky = 0: oldtext$ = prompt$ + " {" + inp$ + "}"
  1188.     newText$ = oldtext$
  1189.     DO WHILE ky <> 13
  1190.         i = _MOUSEINPUT
  1191.         ty = (_MOUSEY + 24) / SQ
  1192.         ' T we must control also X dimension not only Y dimension for mouse in Area Promotion
  1193.         IF _MOUSEBUTTON(1) = -1 AND (_MOUSEX >= 500 AND _MOUSEX <= 700) THEN
  1194.             IF ty > 1 THEN
  1195.                 IF ty = 2 THEN inp$ = "Q": EXIT DO
  1196.                 IF ty = 3 THEN inp$ = "R": EXIT DO
  1197.                 IF ty = 4 THEN inp$ = "B": EXIT DO
  1198.                 IF ty = 5 THEN inp$ = "N": EXIT DO
  1199.             ELSE
  1200.                 inp$ = ""
  1201.                 'T no good click
  1202.             END IF
  1203.         END IF
  1204.         AreaOutput "Promote Enter Q R B N", newText$
  1205.         _DISPLAY
  1206.         oldtext$ = newText$
  1207.         k$ = INKEY$
  1208.         IF LEN(k$) THEN
  1209.             ky = ASC(RIGHT$(k$, 1))
  1210.             IF 31 < ky AND ky < 127 THEN
  1211.                 inp$ = inp$ + CHR$(ky)
  1212.             ELSEIF ky = 8 THEN
  1213.                 IF LEN(inp$) THEN inp$ = LEFT$(inp$, LEN(inp$) - 1)
  1214.             END IF
  1215.             newText$ = prompt$ + " {" + inp$ + "}"
  1216.         END IF
  1217.     LOOP
  1218.     Ppromote$ = inp$
  1219.     'B don't worry about case, it gets checked later
  1220.  
  1221. SUB QUEEN (A, B, XX(), YY(), NDX)
  1222.     CALL BISHOP(A, B, XX(), YY(), NDX)
  1223.     CALL ROOK(A, B, XX(), YY(), NDX)
  1224.  
  1225. SUB restart
  1226.     'B restart variables
  1227.     CLS
  1228.     ERASE BOARD
  1229.     REDIM Move$(1 TO 300)
  1230.     REDIM Boards$(1 TO 300)
  1231.     'B need to start array at 1 not 0
  1232.     result = -2500
  1233.     wcKsflag = 0: wcQsflag = 0: wcKsold = 0: wcQsold = 0
  1234.     LEVEL = 0: INTFLAG = 0: countMove = 0
  1235.     whiteMove$ = "": blackMove$ = "": bmoves$ = "": bFirst = -1
  1236.  
  1237. SUB ROOK (A, B, XX(), YY(), NDX)
  1238.     ID = SGN(BOARD(B, A))
  1239.     FOR X = A - 1 TO 0 STEP -1
  1240.         IF ID <> SGN(BOARD(B, X)) THEN
  1241.             NDX = NDX + 1
  1242.             XX(NDX) = X
  1243.             YY(NDX) = B
  1244.         END IF
  1245.         IF (BOARD(B, X)) <> 0 THEN EXIT FOR
  1246.     NEXT
  1247.     FOR X = A + 1 TO 7 STEP 1
  1248.         IF ID <> SGN(BOARD(B, X)) THEN
  1249.             NDX = NDX + 1
  1250.             XX(NDX) = X
  1251.             YY(NDX) = B
  1252.         END IF
  1253.         IF (BOARD(B, X)) <> 0 THEN EXIT FOR
  1254.     NEXT
  1255.     FOR Y = B - 1 TO 0 STEP -1
  1256.         IF ID <> SGN(BOARD(Y, A)) THEN
  1257.             NDX = NDX + 1
  1258.             XX(NDX) = A
  1259.             YY(NDX) = Y
  1260.         END IF
  1261.         IF (BOARD(Y, A)) <> 0 THEN EXIT FOR
  1262.     NEXT
  1263.     FOR Y = B + 1 TO 7 STEP 1
  1264.         IF ID <> SGN(BOARD(Y, A)) THEN
  1265.             NDX = NDX + 1
  1266.             XX(NDX) = A
  1267.             YY(NDX) = Y
  1268.         END IF
  1269.         IF (BOARD(Y, A)) <> 0 THEN EXIT FOR
  1270.     NEXT
  1271.  
  1272. 'B This is INPUT for graphic screens
  1273. FUNCTION screenInput$ (pixelX, pixelY, prompt$)
  1274.     inp$ = ""
  1275.     ky = 0: oldtext$ = prompt$ + " {" + inp$ + "}"
  1276.     newText$ = oldtext$
  1277.     COLOR LITE&
  1278.     WHILE ky <> 13
  1279.         AreaOutput newText$, ""
  1280.         _DISPLAY
  1281.         oldtext$ = newText$
  1282.         k$ = INKEY$
  1283.         IF LEN(k$) THEN
  1284.             ky = ASC(RIGHT$(k$, 1))
  1285.             IF 31 < ky AND ky < 127 THEN
  1286.                 inp$ = inp$ + CHR$(ky)
  1287.             ELSEIF ky = 8 THEN
  1288.                 IF LEN(inp$) THEN inp$ = LEFT$(inp$, LEN(inp$) - 1)
  1289.             END IF
  1290.             newText$ = prompt$ + " {" + inp$ + "}    "
  1291.         END IF
  1292.     WEND
  1293.     COLOR WHITE&
  1294.     screenInput$ = inp$
  1295.  
  1296. 'B show entire board captured pieces also used for pawn promotion, Move List, Buttons, Debug Info
  1297. SUB SHOWBD
  1298.     COLOR WHITE&, 0
  1299.     _FONT bArial&
  1300.     'B print board labels for files
  1301.     LOCATE 2, 3:
  1302.     IF playBlack = -1 THEN PRINT "HGFEDCBA" ELSE PRINT "ABCDEFGH";
  1303.     'LOCATE 11, 3:                                                          ' A: display 1 set of labels only
  1304.     'IF playBlack = -1 THEN PRINT "HGFEDCBA" ELSE PRINT "ABCDEFGH";
  1305.     'B print board labels for ranks
  1306.     FOR i = 8 TO 1 STEP -1
  1307.         BLR$ = RIGHT$(STR$(i), 1)
  1308.         IF playBlack THEN BLR$ = w2b$(BLR$)
  1309.         LOCATE 8 - i + 3, 2: PRINT BLR$;
  1310.         '    LOCATE 8 - i + 3, 11: PRINT BLR$;
  1311.     NEXT
  1312.     'B Count captures by start of standard set on board and deduct each piece on board
  1313.     DIM c(-6 TO 6)
  1314.     c(-6) = 1: c(-5) = 2: c(-4) = 2: c(-3) = 2: c(-2) = 8: c(-1) = 1
  1315.     c(6) = 1: c(5) = 2: c(4) = 2: c(3) = 2: c(2) = 8: c(1) = 1
  1316.     FOR x = 0 TO 7
  1317.         FOR y = 0 TO 7
  1318.             SHOWMAN x, y
  1319.             _FONT bArial&
  1320.             SELECT CASE BOARD(x, y)
  1321.                 CASE -900: IF c(-6) THEN c(-6) = c(-6) - 1
  1322.                 CASE -500: IF c(-5) THEN c(-5) = c(-5) - 1
  1323.                 CASE -300: IF c(-4) THEN c(-4) = c(-4) - 1
  1324.                 CASE -270: IF c(-3) THEN c(-3) = c(-3) - 1
  1325.                 CASE -100: IF c(-2) THEN c(-2) = c(-2) - 1
  1326.                 CASE -9000: IF c(-1) THEN c(-1) = c(-1) - 1
  1327.                 CASE 4500: IF c(1) THEN c(1) = c(1) - 1
  1328.                 CASE 100: IF c(2) THEN c(2) = c(2) - 1
  1329.                 CASE 270: IF c(3) THEN c(3) = c(3) - 1
  1330.                 CASE 300: IF c(4) THEN c(4) = c(4) - 1
  1331.                 CASE 500: IF c(5) THEN c(5) = c(5) - 1
  1332.                 CASE 900: IF c(6) THEN c(6) = c(6) - 1
  1333.             END SELECT
  1334.         NEXT
  1335.     NEXT
  1336.     'B below need to blackout captures in case UNDO undoes one
  1337.     LINE (12 * SQ, 0)-(700, 9 * SQ), BLACK&, BF
  1338.     'Draw Capture pieces section
  1339.     FOR b = 0 TO 4
  1340.         FOR a = 1 TO 2
  1341.             IF isWhite(a, b) THEN COLOR WHITES& ELSE COLOR BLACKS&
  1342.             LINE (((a * 2) + 10) * SQ, (b + 1) * SQ)-STEP(SQ, SQ), , BF
  1343.             PRESET (((a * 2) + 10) * SQ + 8, (b + 1) * SQ + 36) 'A: centralise pieces
  1344.             IF a = 2 THEN DRAW "C" + STR$(BLACK&) ELSE DRAW "C" + STR$(WHITE&)
  1345.             SELECT CASE b
  1346.                 'A  draw outlines for captured area
  1347.                 CASE 0: DRAW "R26U5H2L6E9U11G4H6G4H4G6H4D11F9L6G2D5"
  1348.                 CASE 1: DRAW "R26U5H2L5U7E3R4U10L6D3L4U3L6D3L4U3L6D10R4F3D7L5G2D5"
  1349.                 CASE 2: DRAW "R26U5H2L8E6U9H2G8H2E8H2L6G6D9F6L8G2D5"
  1350.                 CASE 3: DRAW "R26U5H2U4E2U9H6L9G10D4F2R4E3R4G8L4G2D5"
  1351.                 CASE 4: DRAW "R26U5H2L6U7E3U6H3L10G3D6F3D7L6G2D5"
  1352.                 CASE 5: DRAW "R26U5H2L5E7U6H4L5G3U5R2U2L2U2L2D2L2D2R2D5H3L5G4D6F7L5G2D5"
  1353.             END SELECT
  1354.             DRAW "BE2"
  1355.             'A  MOVE PEN INSIDE
  1356.             IF a = 2 THEN DRAW "P" + STR$(BLACK&) + "," + STR$(BLACK&)
  1357.             IF a = 1 THEN DRAW "P" + STR$(WHITE&) + "," + STR$(WHITE&)
  1358.             COLOR WHITE&, BLACK&
  1359.             IF a = 1 THEN cindex = 6 - b ELSE cindex = -1 * (6 - b)
  1360.             IF playBlack THEN cindex = cindex * -1
  1361.             digit$ = RIGHT$(STR$(c(cindex)), 1)
  1362.             IF digit$ <> "0" THEN LOCATE b + 2, (a * 2) + 12: PRINT digit$;
  1363.         NEXT
  1364.     NEXT
  1365.     COLOR WHITE&, BLACK&
  1366.     _FONT normal&
  1367.     showButtonBar
  1368.     showMoveList
  1369.     'B Some debug stuff also needed for UNDO  Save file
  1370.     LINE (0, 25 * FH)-(46 * FW, YMAX), BLACK&, BF
  1371.     lp 25, 2, "Last move by AI: " + blackMove$
  1372.     lp 26, 2, "Move Count:" + STR$(countMove) + "   Turn:" + STR$(Turn) + "   Result:" + STR$(result)
  1373.     lp 27, 2, "Castle: K flag:" + STR$(wcKsflag) + "   Q flag:" + STR$(wcQsflag) + "   K old:" + STR$(wcKsold) + "   Q old:" + STR$(wcQsold)
  1374.     lp 28, 2, "Last move by Human: " + whiteMove$
  1375.  
  1376. SUB showButtonBar
  1377.     MakeButton 700, 60, 880, 100, "PLAY WHITE", LITE2&
  1378.     MakeButton 700, 120, 880, 160, "PLAY BLACK", LITE2&
  1379.     MakeButton 700, 180, 880, 220, "UNDO", LITE2&
  1380.     MakeButton 700, 240, 880, 280, "SAVE GAME", LITE2&
  1381.     MakeButton 700, 300, 880, 340, "LOAD GAME", LITE2&
  1382.     MakeButton 700, 360, 880, 400, "MANUAL SETUP", LITE2&
  1383.     MakeButton 700, 420, 880, 460, "QUIT", LITE2&
  1384.  
  1385. 'B set this up with Adrian's Draw Strings
  1386. SUB SHOWMAN (A, B)
  1387.     IF isWhite(B, A) THEN COLOR WHITES& ELSE COLOR BLACKS&
  1388.     LINE ((A + 2) * SQ, (B + 2) * SQ)-STEP(SQ, SQ), , BF
  1389.     ZZ = ABS(BOARD(B, A))
  1390.     IF ZZ THEN
  1391.         PRESET ((A + 2) * SQ + 8, (B + 2) * SQ + 36) 'A: centralise pieces
  1392.         IF BOARD(B, A) < 0 THEN
  1393.             IF playBlack THEN DRAW "C" + STR$(WHITE&) ELSE DRAW "C" + STR$(BLACK&)
  1394.         ELSE
  1395.             IF playBlack THEN DRAW "C" + STR$(BLACK&) ELSE DRAW "C" + STR$(WHITE&)
  1396.         END IF
  1397.         SELECT CASE ZZ
  1398.             'A  draw outlines for pieces on board
  1399.             CASE 100: DRAW "R26U5H2L6U7E3U6H3L10G3D6F3D7L6G2D5"
  1400.             CASE 500: DRAW "R26U5H2L5U7E3R4U10L6D3L4U3L6D3L4U3L6D10R4F3D7L5G2D5"
  1401.             CASE 270: DRAW "R26U5H2U4E2U9H6L9G10D4F2R4E3R4G8L4G2D5"
  1402.             CASE 300: DRAW "R26U5H2L8E6U9H2G8H2E8H2L6G6D9F6L8G2D5"
  1403.             CASE 900: DRAW "R26U5H2L6E9U11G4H6G4H4G6H4D11F9L6G2D5"
  1404.             CASE 4500: DRAW "R26U5H2L5E7U6H4L5G3U5R2U2L2U2L2D2L2D2R2D5H3L5G4D6F7L5G2D5"
  1405.             CASE 9000: DRAW "R26U5H2L5E7U6H4L5G3U5R2U2L2U2L2D2L2D2R2D5H3L5G4D6F7L5G2D5"
  1406.         END SELECT
  1407.         DRAW "BE2"
  1408.         'A  MOVE PEN INSIDE and color fill
  1409.         IF BOARD(B, A) < 0 THEN
  1410.             IF playBlack THEN DRAW "P" + STR$(WHITE&) + "," + STR$(WHITE&) ELSE DRAW "P" + STR$(BLACK&) + "," + STR$(BLACK&)
  1411.         END IF
  1412.         IF BOARD(B, A) > 0 THEN
  1413.             IF playBlack THEN DRAW "P" + STR$(BLACK&) + "," + STR$(BLACK&) ELSE DRAW "P" + STR$(WHITE&) + "," + STR$(WHITE&)
  1414.         END IF
  1415.     END IF
  1416.     COLOR WHITE&, BLACK&
  1417.     _FONT normal&
  1418.  
  1419. 'B  T set this up to show last 8 moves of White and Black
  1420. SUB showMoveList
  1421.     IF countMove < 9 THEN z = 8 ELSE z = countMove
  1422.     LINE (500, 300)-(680, 500), BLACK&, BF ' T if we use 700 it covers left border of buttonbar
  1423.     COLOR _RGB(0, 180, 220)
  1424.     FOR a = 0 TO 7
  1425.         lp 22 - a, 46, Move$(z - a)
  1426.     NEXT
  1427.     COLOR WHITE&
  1428.  
  1429. 'B convert BINGO for human playing Black
  1430. FUNCTION w2b$ (s$)
  1431.     b$ = ""
  1432.     FOR i = 1 TO LEN(s$)
  1433.         here = INSTR("ABCDEFGH12345678", MID$(s$, i, 1))
  1434.         IF here THEN b$ = b$ + MID$("HGFEDCBA87654321", here, 1) ELSE b$ = b$ + MID$(s$, i, 1)
  1435.     NEXT
  1436.     w2b$ = b$
  1437.  
  1438. SUB Wait_Click_Key
  1439.     'B handy sub to reuse in other programs
  1440.     DO
  1441.         k = _KEYHIT
  1442.         WHILE _MOUSEINPUT: WEND
  1443.         _LIMIT 30
  1444.     LOOP UNTIL k <> 0 OR _MOUSEBUTTON(1)
  1445.  
  1446. SUB WriteEntry
  1447.     'B  Record game in both Move$() and Boards$() at countMove
  1448.     IF playBlack THEN
  1449.         IF bFirst THEN
  1450.             bFirst = 0
  1451.             bmoves$ = blackMove$ + pBflag$
  1452.         ELSE
  1453.             r$ = bmoves$ + "   " + whiteMove$ + pWflag$
  1454.             countMove = countMove + 1
  1455.             Move$(countMove) = r$
  1456.             bmoves$ = blackMove$ + pBflag$
  1457.         END IF
  1458.     ELSE
  1459.         countMove = countMove + 1
  1460.         Move$(countMove) = whiteMove$ + pWflag$ + " " + blackMove$ + pBflag$
  1461.     END IF
  1462.     Boards$(countMove) = bString$
  1463.     'B clear flags for promoted pawns
  1464.     pWflag$ = "": pBflag$ = ""
  1465.  

Here is screen shot of what it is supposed to look like when you start the program and choose to play Black:
Update: Ha! oops it says last move was by human, nope the computer is playing White, hmm...
Title: Re: A 90% complete chess engine
Post by: TempodiBasic on January 26, 2020, 11:22:58 am
@Bplus
thanks to remember me that our adventure!
Thanks to let me understand how to code in cooperation!

I really stop working on it because I don't understand  well the logic behind the IO so I cannot modify or improve what I don't understand.
Surely the original program (CHESS.BAS into folder of examples of QB64) is uncomplete!
I think because the original coder have no too time to write it, because I find some prebuild options that gives me the opportunity to let fight AI vs AI, but the evaluation routine is not so strong!
Moreover when also in buggy way, the original coder has written an Incheck control for White, there is nothing for the black! In fact both black is Ai both black is Human, Black is not able to castle or to take en passant!
I have no knowledge of reverse ingeneering, so I cannot understand the IO routine!  In it must be added the castle and enpassant option for black (it is simple using new flags!) and the evaluation of positional themes... and it is quiet difficult to me.
I'm able to play chess ranging 1200-1500 Elo on the tournament online, so not so much theory to translate into code for AI.

Reading on www.chessprogrammin.org there are so many informations and methods to write a chess program! There is no one way! And for now I have no found a way like that of CHESS.BAS.
Title: Re: A 90% complete chess engine
Post by: bplus on January 26, 2020, 11:33:37 am
Hi TempodiBasic,

Yeah, working on code together was great experience! My memory does not recall problems with castling with Black AND en passant (someone tell the spell checker not to underline, I got that one right) too?

My memory tells me the biggest failure was the King was recognizing being in check but thinking that counter checking was OK! :D :D :D that was when I started to look for another chess engine and got distracted (saved) by other things.

Title: Re: A 90% complete chess engine
Post by: SierraKen on January 26, 2020, 12:26:36 pm
Awesome games everyone! All you guys are geniuses. I started on Checkers 2 days ago but don't want any help on it unless I ask later. I got the board and the ability to move pieces so far. Might take a few weeks because I'm working slow on it. But I hope to finish sometime soon.
Title: Re: A 90% complete chess engine
Post by: bplus on January 26, 2020, 12:39:17 pm
Go for it Ken!

I've been thinking about checkers ever since I created a perfect looking checkerboard, but OK, I won't show ;-)
Title: Re: A 90% complete chess engine
Post by: SierraKen on January 26, 2020, 12:41:02 pm
Robert Frost, I got one error on yours though, I can't remember off hand though.
Bplus,  when I was in Check by the computer, I couldn't get out of it so I had to end the game as a stand-still.
Title: Re: A 90% complete chess engine
Post by: SierraKen on January 26, 2020, 12:44:25 pm
Thanks B+! It will be a learning experience. I already have where you can't move onto the same space as the opponent or to one of your other pieces. I have to add a few more of those (like not to move on a red square). I'm using a coordinate system (without using the mouse) and it uses 1 variable for both horizontal and vertical, like on the space 1 x 2 it just uses the number 12 for the variable. I'll use that variable for the computer turn, etc. 
Title: Re: A 90% complete chess engine
Post by: bplus on January 26, 2020, 02:11:16 pm
Robert Frost, I got one error on yours though, I can't remember off hand though.
Bplus,  when I was in Check by the computer, I couldn't get out of it so I had to end the game as a stand-still.

Ken, I don't think there is a single line in program that says Checkmate! If you are in check and can't get out of it then you are done, why rub it in? :-)) yeah, sure, call it a "stand-still".
Title: Re: A 90% complete chess engine
Post by: STxAxTIC on January 26, 2020, 03:38:25 pm
Quote
Ha! A least one week would be more believable but maybe he Trumped up his memory. ;-))

Think Ima let that slide bplus?

... 15 minutes later...

Welp, no help from the wayback machine. You just have to imagine me without a full time job in the middle of July. A lot of stuff happens in a 24 hour period.

While this is proof by no means, I tried to fit my weird development cycle in one screenshot. I suppose technically the work took place over two calendar days, but for completeness:
Title: Re: A 90% complete chess engine
Post by: bplus on January 26, 2020, 03:59:19 pm
OK I believe! 700+ lines of code is probably possible, specially no check, castle, pawn promo and stopping to play? :) still nice chunk of code to get done.

Is that about 6 hours? One long sitting...
Title: Re: A 90% complete chess engine
Post by: SierraKen on January 26, 2020, 05:08:02 pm
Ken, I don't think there is a single line in program that says Checkmate! If you are in check and can't get out of it then you are done, why rub it in? :-)) yeah, sure, call it a "stand-still".

ROFL... well then it wasn't a stand-still. :)
Title: Re: A 90% complete chess engine
Post by: SierraKen on January 26, 2020, 05:11:01 pm
OK I believe! 700+ lines of code is probably possible, specially no check, castle, pawn promo and stopping to play? :) still nice chunk of code to get done.

Is that about 6 hours? One long sitting...

The only way I could ever do 700+ lines of code in 1 day is to use my Picture to .BAS converter. It changes a picture to all PSET lines, 1 PSET per line.... like 10,000 lines or something like that.
Title: Re: A 90% complete chess engine
Post by: Richard Frost on January 29, 2020, 12:44:05 am
Update using Bplus's graphics.  Castling works properly.  Still no checkmate.  Has "t" for take back move.
Still a long way to go, like years of my spare time.

Code: QB64: [Select]
  1. _TITLE "Chess"
  2.  
  3. DEFINT A-Z
  4.  
  5. CONST true = -1, false = 0
  6. CONST Rook = 1, Knight = 2, Bishop = 3, Queen = 4, King = 5, Pawn = 6
  7.  
  8. COMMON SHARED WorB, Move, Score, Index, opening
  9. COMMON SHARED m$, i$, mess$
  10. COMMON SHARED MaxRow, xq, yq, xc, yc, xm, ym
  11. COMMON SHARED speed, WaitForKey, Studying
  12. COMMON SHARED Castle$, OtherK$, mkr, mkc, okr, okc, invert
  13. COMMON SHARED MasterLevel, SaveWorB
  14. COMMON SHARED GameFile$, RunWith, check, redo, b1, b2, b1$, b2$
  15. COMMON SHARED debug, DebugR, DebugC
  16. COMMON SHARED Start1&, Start2&, MaxElapse!
  17. COMMON SHARED human, humanc, OnAuto, sillyf, rflag
  18. COMMON SHARED boardwhite&, boardblack&
  19. COMMON SHARED black&, red&, green&, blue&, white&
  20. COMMON SHARED Enter$, Esc$, lf$, crlf$
  21. COMMON SHARED debug$, tbf, tbc
  22.  
  23. l = 5: p = 6: b = 8: q1 = 200: q2 = 500
  24. DIM SHARED b(b, b), t(b, b, l), o(b, b), mp$(p, 7), tb(b, b, 10)
  25. DIM SHARED Moves(l), Move$(l, q1), Score(l, q1), TieTo(l), Index(l, q1)
  26. DIM SHARED x(p, q2), y(p, q2), c(12, q2), MoveLog$(q2)
  27. DIM SHARED gm$(999)
  28. DIM SHARED cp&(32)
  29.  
  30. 'ON ERROR GOTO Oops
  31.  
  32. 'GameFile$ = "'chessx.alg"
  33.  
  34. sillyf = 1 '                                            Moire effect, toggle with "z", or just default this to 0
  35.  
  36. Begin:
  37. Init
  38. gm = 1
  39.     SaveWorB = WorB
  40.     IF LEN(GameFile$) THEN
  41.         opening = 1
  42.         ScanKey
  43.         m$ = gm$(gm)
  44.         'LOCATE 1, 1: PRINT gm; "*"; m$; "*";
  45.         _DISPLAY
  46.         SLEEP
  47.         Score = 0
  48.         IF RIGHT$(m$, 1) = "+" THEN
  49.             Score = 777
  50.             check = true
  51.             m$ = LEFT$(m$, LEN(m$) - 1)
  52.         END IF
  53.         gm = gm + 1
  54.         IF LEN(m$) = 0 THEN opening = 0: GameFile$ = ""
  55.     END IF
  56.  
  57.     'IF opening > 0 THEN
  58.     '    READ m$
  59.     'IF m$ = "end" THEN opening = 0
  60.     'END IF
  61.  
  62.     IF opening = 0 THEN
  63.         IF Start1& = 0 THEN Start1& = TIMER
  64.         Start2& = TIMER
  65.         SaveForTakeBack
  66.         redo:
  67.         WorB = WorB XOR 1
  68.         CheckBoard 1
  69.         WorB = WorB XOR 1
  70.         CheckBoard 0
  71.         IF Moves(0) = 0 THEN mess$ = "Stalemate"
  72.         IF LEN(mess$) > 0 THEN EXIT DO
  73.         'LOCATE 1, 1: PRINT debug$;
  74.         IF human AND (humanc = WorB) THEN
  75.             woof:
  76.             IF tbf THEN
  77.                 takeback
  78.                 PlotAll
  79.                 tbf = 0
  80.                 GOTO redo
  81.             END IF
  82.             'LOCATE 1, 1: PRINT tbc; " ";
  83.             HumanMove
  84.             IF tbf THEN GOTO woof
  85.             ok = 0
  86.             FOR i = 1 TO Moves(0)
  87.                 IF m$ = Move$(0, i) THEN ok = 1: EXIT FOR
  88.             NEXT i
  89.             IF ok = 0 THEN SOUND 200, 1: GOTO woof
  90.         ELSE
  91.             DebugR = 99
  92.             IF sillyf THEN silly
  93.             rflag = 1
  94.             Recurse 1
  95.             rflag = 0
  96.             TakeBest 0
  97.             IF debug THEN Debug1
  98.             PlotAll
  99.         END IF
  100.     END IF
  101.     WorB = SaveWorB
  102.     DispTime
  103.  
  104.     fr = VAL(MID$(m$, 2, 1)) '                                       from row
  105.     IF invert THEN fr = 9 - fr
  106.     fc = INSTR("abcdefgh", LEFT$(m$, 1)) '                           from column
  107.     IF invert THEN fc = 9 - fc
  108.     IF LEFT$(m$, 1) = "O" THEN
  109.         IF (WorB = 0) AND (humanc = 0) THEN
  110.             fr = mkr: fc = mkc
  111.         ELSE
  112.             fr = okr: fc = okc
  113.         END IF
  114.     END IF
  115.  
  116.     DO: _LIMIT 10
  117.         ic = (ic + 1) MOD 10
  118.         IF ic > 5 THEN f$ = "clockx.png" ELSE f$ = "clockx2.png"
  119.         IF f$ <> oldf$ THEN
  120.             i& = _LOADIMAGE(f$): _ICON i&: _FREEIMAGE i&
  121.             oldf$ = f$
  122.         END IF
  123.         zz = zz XOR 1
  124.         IF zz THEN
  125.             c1& = _RGB32(RND * 155 + 100, RND * 155 + 100, RND * 155 + 100)
  126.             c2& = _RGB32(RND * 155 + 100, RND * 155 + 100, RND * 155 + 100)
  127.         ELSE
  128.             c1& = black&: c2& = black&
  129.         END IF
  130.         x1 = xc + (fc - 5) * xq
  131.         y1 = yc + (4 - fr) * yq
  132.         x2 = x1 + xq
  133.         y2 = y1 + yq
  134.         LINE (x1 + 1, y1 + 1)-(x2 - 1, y2 - 1), c1&, B
  135.         LINE (x1 + 2, y1 + 2)-(x2 - 2, y2 - 2), c1&, B
  136.  
  137.         IF LEFT$(m$, 1) <> "O" THEN '                                    castling
  138.             tr = VAL(MID$(m$, 4, 1))
  139.             IF invert THEN tr = 9 - tr
  140.             tc = INSTR("abcdefgh", MID$(m$, 3, 1))
  141.             IF invert THEN tc = 9 - tc
  142.             x1 = xc + (tc - 5) * xq
  143.             y1 = yc + (4 - tr) * yq
  144.             x2 = x1 + xq
  145.             y2 = y1 + yq
  146.             LINE (x1 + 1, y1 + 1)-(x2 - 1, y2 - 1), c2&, B
  147.             LINE (x1 + 2, y1 + 2)-(x2 - 2, y2 - 2), c2&, B
  148.         END IF
  149.         _DISPLAY
  150.         _DELAY .01
  151.         IF NOT ((WorB <> humanc) AND (opening = 0)) THEN EXIT DO
  152.         ScanKey
  153.         'IF tbf THEN GOTO begin2
  154.     LOOP UNTIL i$ = Enter$
  155.     f$ = "chess3.png": i& = _LOADIMAGE(f$): _ICON i&: _FREEIMAGE i&
  156.  
  157.     MoveIt m$, -1
  158.     ShowAlgebraic m$
  159.     IF sillyf THEN silly ELSE PlotAll
  160.     _DISPLAY
  161.  
  162.     IF opening = 0 THEN
  163.         check = false
  164.         CheckBoard 0
  165.         LOCATE 1, 58
  166.         IF Score = 777 THEN
  167.             check = true
  168.             PRINT "Check!";
  169.         ELSE
  170.             PRINT "      ";
  171.         END IF
  172.     END IF
  173.  
  174.     WorB = SaveWorB XOR 1 '                                          toggle white/black
  175.     'IF LEN(GameFile$) > 0 THEN KeyGet
  176.     'IF humanc = WorB THEN KeyGet
  177.     'WaitForKey = true
  178. LOOP UNTIL Move = 500
  179.  
  180. IF Move = 500 THEN mess$ = "Over 500 moves...."
  181. tc = 60 - LEN(mess$) \ 2
  182. LOCATE 22, tc: PRINT mess$;
  183. PRINT #1, ""
  184. PRINT #1, mess$
  185. ' IF Studying THEN KeyGet
  186. GOTO Begin
  187.  
  188. o1:
  189. DATA e2e4,e7e5,g1f3,b8c6,f1b5,a7a6,b5a4,b7b5,a4b3,g8f6,b1c3,f8e7,f3g5,h7h6
  190. 'DATA g5f7,O-O
  191. 'DATA f7d8,g8h7
  192.  
  193. SetUp:
  194. DATA 1,2,3,4,5,3,2,1
  195. DATA 6,6,6,6,6,6,6,6
  196. DATA 0,0,0,0,0,0,0,0
  197. DATA 0,0,0,0,0,0,0,0
  198. DATA 0,0,0,0,0,0,0,0
  199. DATA 0,0,0,0,0,0,0,0
  200. DATA 12,12,12,12,12,12,12,12
  201. DATA 7,8,9,10,11,9,8,7
  202.  
  203. Legal:
  204. '       udlr,udlr,udlr,udlr,udlr,udlr,udlr,udlr
  205. DATA R,8000,0800,0080,0008,0000,0000,0000,0000
  206. DATA N,2010,2001,0210,0201,1020,1002,0120,0102
  207. DATA B,8080,8008,0880,0808,0000,0000,0000,0000
  208. DATA Q,8000,0800,0080,0008,8080,8008,0880,0808
  209. DATA K,1000,0100,0010,0001,1010,1001,0110,0101
  210. DATA P,1000,1001,1010,0000,0000,0000,0000,0000
  211.  
  212. PiecePatterns:
  213. DATA ........................
  214. DATA ........................
  215. DATA ........................
  216. DATA ........................
  217. DATA ....X..XX..XX..XX..X....
  218. DATA ....X..XX..XX..XX..X....
  219. DATA ....X..XX..XX..XX..X....
  220. DATA ....X..XX..XX..XX..X....
  221. DATA ....X..XX..XX..XX..X....
  222. DATA .....X.XX..XX..XX.X.....
  223. DATA ......XXXXXXXXXXXX......
  224. DATA .....XX..........XX.....
  225. DATA ......X.XXXXXXXX.X......
  226. DATA ......X.XXXXXXXX.X......
  227. DATA ......X.XXXXXXXX.X......
  228. DATA ......X.XXXXXXXX.X......
  229. DATA .....X............X.....
  230. DATA .....X..XXXXXXXX..X.....
  231. DATA ....X..............X....
  232. DATA ...X..XXXXXXXXXXXX..X...
  233. DATA ...X................X...
  234. DATA ...XXXXXXXXXXXXXXXXXX...
  235.  
  236. DATA ........................
  237. DATA ........................
  238. DATA ........................
  239. DATA ........................
  240. DATA ............XXX.........
  241. DATA ..........XX.X.X........
  242. DATA .........X..X.X.XX......
  243. DATA ........X.X.XX.X..X.....
  244. DATA .......X.XXXX.X.X..X....
  245. DATA .......X.X...XXX.X..X...
  246. DATA .....X..XX..X.XXX.X.X...
  247. DATA ....X.XXXXXXX.XXX.X..X..
  248. DATA ...X.XXXXXX.X..XX.X..X..
  249. DATA ...X.XX..XXX.X.XX.X..X..
  250. DATA ....X..XXXX..X.XX.X..X..
  251. DATA .....XX..X..X.XXX.X..X..
  252. DATA ........X..XX.XX.XX.X...
  253. DATA .......X..XX.XX.XX.X....
  254. DATA ......XXXXXXXXXXXXXX....
  255. DATA .....X..............X...
  256. DATA ....X................X..
  257. DATA .....XXXXXXXXXXXXXXXX...
  258.  
  259. DATA ........................
  260. DATA ........................
  261. DATA ........................
  262. DATA ............X...........
  263. DATA ...........X.X..........
  264. DATA ..........X.X.X.........
  265. DATA ........X...XX..X.......
  266. DATA .......X..X..XX..X......
  267. DATA .......X.XXX..XX.X......
  268. DATA .......X.XXXX..X.X......
  269. DATA ........X.......X.......
  270. DATA .......XX.X.X.X.XX......
  271. DATA ......X...........X.....
  272. DATA .......X.XXX.XX.XX......
  273. DATA ........X.XX.XX.X.......
  274. DATA .......X.XXX.XXX.X......
  275. DATA .......X.XXX.XXX.X......
  276. DATA ......X.X.......X.X.....
  277. DATA .....X.XXXXX.XXXXX.X....
  278. DATA .....X.XXXXX.XXXXX.X....
  279. DATA .....X.............X....
  280. DATA ......XXXXXXXXXXXXX.....
  281.  
  282. DATA ............X...........
  283. DATA ...........X.X..........
  284. DATA .....X....X.X.X....X....
  285. DATA ....X.X.XX.XXX..X.X.X...
  286. DATA ...X.X.X..XX.XXX.X.X.X..
  287. DATA ...X.XX.XXX.X.XXX.XX.X..
  288. DATA ...X.XXX.X.XXX.X.XXX.X..
  289. DATA ...X.XXXX.XXXXX.XXXX.X..
  290. DATA ....X.XXXXXX..XXXXX.X...
  291. DATA .....X.XXXXX..XXXX.X....
  292. DATA .....X.............X....
  293. DATA ......XXXXXXXXXXXXX.....
  294. DATA ....X...............X...
  295. DATA ......XX.XXXXXXX.XX.....
  296. DATA .......X.X.XXX.X.X......
  297. DATA ......X.XX.XXX.XX.X.....
  298. DATA ......X.XX.XXX.XX.X.....
  299. DATA .....XXXXXXXXXXXXXXX....
  300. DATA ....X...............X...
  301. DATA ...X..XX.XX.XX.XX.X..X..
  302. DATA ...X.................X..
  303. DATA ....XXXXXXXXXXXXXXXXX...
  304.  
  305. DATA ...........XX...........
  306. DATA .........XX..XX.........
  307. DATA .......XX.X..X.XX.......
  308. DATA .....XX.X......X.XX.....
  309. DATA ....X..XX.X..X.XX..X....
  310. DATA ...X...XXXX..XXXX...X...
  311. DATA ..X...XX........XX...X..
  312. DATA .X..XXX.XXX..XXX.XXX..X.
  313. DATA X..XXX..XXX..XXX..XXX..X
  314. DATA X.XXXX..XXX..XXXX.XXXX.X
  315. DATA X.XXXX.XXXX..XXXX.XXXX.X
  316. DATA X.XXXX..XXXXXXXX..XXXX.X
  317. DATA .X.XXXX..XXXXXX..XXXX.X.
  318. DATA .X..XXXX..XXXX..XXXX..X.
  319. DATA ..X..XXXX......XXXX..X..
  320. DATA ...X....X......X....X...
  321. DATA ...XXXXXXXXXXXXXXXXXX...
  322. DATA ..X..................X..
  323. DATA .X..XXXXXXXXXXXXXXXX..X.
  324. DATA .X..XXXXXXXXXXXXXXXX..X.
  325. DATA ..X..................X..
  326. DATA ...XXXXXXXXXXXXXXXXXX...
  327.  
  328. DATA ........................
  329. DATA ........................
  330. DATA ........................
  331. DATA ..........XXXX..........
  332. DATA .........X....X.........
  333. DATA ........X.XXXX.X........
  334. DATA ........X.XXXX.X........
  335. DATA .........X....X.........
  336. DATA ........XXXXXXXX........
  337. DATA .......X........X.......
  338. DATA ........XXXXXXXX........
  339. DATA .........X.XX.X.........
  340. DATA .........X.XX.X.........
  341. DATA .........X.XX.X.........
  342. DATA ........X..XX..X........
  343. DATA .......X..XXXX..X.......
  344. DATA ......X.XXXXXXXX.X......
  345. DATA ......X.XXXXXXXX.X......
  346. DATA .....X............X.....
  347. DATA ......XXXXXXXXXXXX......
  348. DATA ........................
  349. DATA ........................
  350.  
  351. rgb:
  352. DATA 0,0,0,0,""
  353. DATA 1,30,60,20,"board white"
  354. DATA 2,1,1,1,"board black"
  355. DATA 3,92,92,92,"white bright"
  356. DATA 4,22,22,92,"white hightlight"
  357. DATA 5,0,0,0,"black bright"
  358. DATA 6,62,22,22,"black hightlight"
  359. DATA 7,63,20,20,"red"
  360. DATA 8,0,63,0,"green"
  361. DATA 9,0,0,63,"blue"
  362. DATA 10,63,63,63,"white"
  363. DATA 11,20,20,20,""
  364. DATA 12,20,20,20,""
  365. DATA 13,20,20,20,""
  366. DATA 14,20,20,20,""
  367. DATA 15,30,30,30,"printing"
  368.  
  369. Oops:
  370. gronk = gronk + 1
  371. IF gronk < 900 THEN
  372.     RESUME
  373.     PRINT "Error "; DATE$; "  "; TIME$;
  374.     END
  375.  
  376. SUB AddIt (Level, tm$, Score)
  377.     Moves(Level) = Moves(Level) + 1 '                                count ok
  378.     Move$(Level, Moves(Level)) = tm$ '                               save move
  379.     Score(Level, Moves(Level)) = Score
  380.     Index(Level, Moves(Level)) = TieTo(Level)
  381.  
  382. SUB BoRestore (Level)
  383.     FOR r = 1 TO 8
  384.         FOR c = 1 TO 8
  385.             b(r, c) = t(r, c, Level)
  386.         NEXT c
  387.     NEXT r
  388.  
  389. SUB BoSave (Level)
  390.     FOR r = 1 TO 8
  391.         FOR c = 1 TO 8
  392.             t(r, c, Level) = b(r, c)
  393.         NEXT c
  394.     NEXT r
  395.  
  396. SUB CheckBoard (Level)
  397.     Moves(Level) = 0
  398.     tking = 5: oking = 11
  399.     IF WorB THEN SWAP tking, oking
  400.     FOR r = 1 TO 8
  401.         FOR c = 1 TO 8
  402.             IF b(r, c) = tking THEN
  403.                 mkr = r
  404.                 mkc = c
  405.             END IF
  406.             IF b(r, c) = tking THEN
  407.                 okr = r
  408.                 okc = c
  409.             END IF
  410.         NEXT c
  411.     NEXT r
  412.  
  413.     FOR r = 1 TO 8
  414.         FOR c = 1 TO 8
  415.             mp = b(r, c)
  416.             mc = -(mp > 6) - (mp = 0) * 2
  417.             IF mc = WorB THEN TryMove Level, r, c
  418.         NEXT c
  419.     NEXT r
  420.  
  421.     '  BBWW
  422.     '  QKQK
  423.     IF MID$(Castle$, WorB * 2 + 1, 1) = " " THEN cq = true ELSE cq = false ' blank means ok
  424.     IF MID$(Castle$, WorB * 2 + 2, 1) = " " THEN ck = true ELSE ck = false
  425.  
  426.     neks$ = "" '  not empty kingside
  427.     neqs$ = "" '  not empty queenside
  428.     qsc$ = "" '   queenside control
  429.     ksc$ = "" '   kingside control
  430.     kic$ = "" '   king in check
  431.     nok$ = "" '   king not there
  432.     nrq$ = "" '   no rook queenside
  433.     nrk$ = "" '   no rook kingside
  434.  
  435.     FOR Castle = 0 TO 1 '                                            queenside, then kingside
  436.         '                         bcd              fg
  437.         IF Castle = 0 THEN ca$ = "234" ELSE ca$ = "67" '             column number
  438.         IF WorB THEN rn$ = "1" ELSE rn$ = "8" '                      row number
  439.         tp = b(VAL(rn$), 5): tp = tp + (tp > 6) * 6
  440.         IF tp <> 5 THEN nok$ = "nok "
  441.         tp = b(VAL(rn$), 1): tp = tp + (tp > 6) * 6
  442.         IF tp <> 1 THEN nrq$ = "nrq "
  443.         tp = b(VAL(rn$), 8): tp = tp + (tp > 6) * 6
  444.         IF tp <> 1 THEN nrq$ = "nrk "
  445.         FOR cs = 1 TO LEN(ca$)
  446.             rn = VAL(rn$)
  447.             n$ = MID$(ca$, cs, 1)
  448.             cn = VAL(n$)
  449.             c$ = MID$("abcdefgh", cn, 1)
  450.             tp = b(rn, cn)
  451.             tp = tp + (tp > 6) * 6 '                                 convert >6 to 1-5
  452.             IF tp <> 0 THEN '                                        not empty
  453.                 IF Castle = 0 THEN cq = false ELSE ck = false
  454.                 IF Castle = 0 THEN neqs$ = neqs$ + "neq " + c$ + rn$ + " "
  455.                 IF Castle = 1 THEN neks$ = neks$ + "nek " + c$ + rn$ + " "
  456.             END IF
  457.             q$ = MID$("abcdefgh", cn, 1) + rn$
  458.             FOR lm = 1 TO Moves(1)
  459.                 IF q$ = RIGHT$(Move$(1, lm), 2) THEN
  460.                     IF Castle = 0 THEN cq = false ELSE ck = false
  461.                     IF Castle = 0 THEN qsc$ = "qsc" + Move$(1, lm) + " "
  462.                     IF Castle = 1 THEN ksc$ = "ksc " + Move$(1, lm) + " "
  463.                 END IF
  464.             NEXT lm
  465.             q$ = "e" + rn$
  466.             FOR lm = 1 TO Moves(1)
  467.                 IF q$ = RIGHT$(Move$(1, lm), 2) THEN cq = 0: ck = 0: kic$ = "kic " + Move$(1, lm) + " "
  468.             NEXT lm
  469.         NEXT cs
  470.     NEXT Castle
  471.     debug$ = nok$ + nrq$ + nrk$ + kic$ + neqs$ + neks$ + qsc$ + ksc$ + "     *"
  472.  
  473.     IF ck THEN AddIt Level, "O-O", 12
  474.     IF cq THEN AddIt Level, "O-O-O", 13
  475.  
  476.     'LOCATE 34 + WorB, 46: PRINT "*"; Castle$; "*";
  477.     'PRINT MID$("K ", ck + 2, 1);
  478.     'PRINT MID$("Q ", cq + 2, 1); cq; ck;
  479.  
  480.     TakeBest Level
  481.  
  482. SUB Debug1
  483.     sr = 32
  484.     r = sr
  485.     c = 4
  486.     FOR t = 1 TO 20
  487.         IF c < 75 THEN
  488.             LOCATE r, c: PRINT SPACE$(8);
  489.             IF t <= Moves(0) THEN
  490.                 LOCATE r, c
  491.                 PRINT Make4$(Move$(0, t)); rjust$(Score(0, t), 4);
  492.             END IF
  493.         END IF
  494.         r = r + 1
  495.         IF r > MaxRow THEN r = sr: c = c + 9
  496.     NEXT t
  497.  
  498. SUB Debug2 ()
  499.     'IF human AND (humanc = WorB) THEN EXIT SUB
  500.     DebugR = DebugR + 1
  501.     IF DebugR > MaxRow THEN
  502.         _DISPLAY
  503.         DebugR = 3: DebugC = 62
  504.         FOR r = 0 TO MaxRow - 2
  505.             LOCATE DebugR + r, DebugC
  506.             PRINT SPACE$(98 - DebugC);
  507.         NEXT r
  508.     END IF
  509.     ts = 0: s = 1
  510.     z$ = ""
  511.     FOR t = 1 TO 3
  512.         ti = TieTo(t)
  513.         z$ = z$ + Make4$(Move$(t - 1, ti)) + rjust$(Score(t - 1, ti), 3) + " "
  514.         ts = ts + Score(t - 1, ti) * s
  515.         's = -s
  516.     NEXT t
  517.     ts = ts - Score
  518.     z$ = z$ + Make4$(m$) + rjust$(Score, 3) + " " + rjust$(ts, 4)
  519.     LOCATE DebugR, DebugC
  520.     PRINT z$; "   ";
  521.     PRINT #7, z$
  522.  
  523. SUB DispText (zr, zc)
  524.     t$ = " RNBQKP"
  525.     LOCATE TextRow(zr), TextCol(zc)
  526.     IF b(zr, zc) > 6 THEN COLOR 0, 7
  527.     PRINT MID$(t$, TextVal(zr, zc) + 1, 1);
  528.     COLOR 7, 0
  529.  
  530. SUB DispTime
  531.     IF Start2& > 0 THEN
  532.         Elapse1! = TIMER - Start1&
  533.         Elapse2! = TIMER - Start2&
  534.         IF Elapse2! > MaxElapse! THEN MaxElapse! = Elapse2!
  535.         'ShowTime 3, Elapse1!, "Game:"
  536.         'ShowTime 4, Elapse2!, "This move:"
  537.         'ShowTime 5, MaxElapse!, "Max move:"
  538.     END IF
  539.  
  540. SUB FadePiece (tfr, tfc, ttr, ttc)
  541.     fr = tfr: fc = tfc: tr = ttr: tc = ttc
  542.     x1 = xc + (fc - 5) * xq
  543.     y1 = yc + (4 - fr) * yq
  544.     x2 = xc + (tc - 5) * xq
  545.     y2 = yc + (4 - tr) * yq
  546.     p = b(tr, tc)
  547.     IF invert THEN p = b(9 - tr, 9 - tc)
  548.     IF p > 6 THEN wb = 1: p = p - 6
  549.     i = p - (wb = 0) * 6
  550.  
  551.     FOR ps = 0 TO 1
  552.         IF ps = 0 THEN
  553.             c = fr + fc: tx = x1: ty = y1
  554.         ELSE
  555.             c = tr + tc: tx = x2: ty = y2
  556.         END IF
  557.         IF c MOD 2 THEN
  558.             LINE (tx, ty)-(tx + xq, ty + yq), boardwhite&, BF
  559.         ELSE
  560.             LINE (tx, ty)-(tx + xq, ty + yq), boardblack&, BF '      black square
  561.             LINE (tx, ty)-(tx + xq, ty + yq), boardwhite&, B '       border
  562.         END IF
  563.     NEXT ps
  564.  
  565.     FOR t = 1 TO c(p, 0)
  566.         tx = x1 + x(p, t) * 2
  567.         ty = y1 + y(p, t) * 2
  568.         LINE (tx, ty)-STEP(1, 1), cp&(c(i, t)), B
  569.     NEXT t
  570.  
  571. SUB HumanMove
  572.     getreal:
  573.     FOR i = 0 TO 1
  574.         IF i = 0 THEN
  575.             rr = 8: cc = 1
  576.             IF invert THEN rr = 9 - rr: cc = 9 - cc
  577.         ELSE
  578.             rr = fr: cc = fc
  579.         END IF
  580.         IF invert THEN rr = 9 - rr: cc = 9 - cc
  581.         mx = _MOUSEX
  582.         my = _MOUSEY
  583.         DO
  584.             x1 = xc - 4 * xq
  585.             y1 = yc - 4 * yq
  586.             x2 = xc + 4 * xq
  587.             y2 = yc + 4 * yq
  588.             LINE (x1, y1)-(x2, y2), boardwhite&, B
  589.             'LOCATE 1, 1: PRINT "Move ";
  590.             x1 = xc + (cc - 5) * xq
  591.             x2 = xc + (cc - 4) * xq
  592.             y1 = yc + (rr - 5) * yq
  593.             y2 = yc + (rr - 4) * yq
  594.             wc& = POINT(x1 + 1, y1 + 1)
  595.             FOR zz = 0 TO 1
  596.                 FOR zx = 1 TO 4
  597.                     IF zz THEN tc& = wc& ELSE tc& = red&
  598.                     LINE (x1 + zx, y1 + zx)-(x2 - zx, y2 - zx), tc&, B
  599.                 NEXT zx
  600.                 _DISPLAY
  601.                 _DELAY .01
  602.             NEXT zz
  603.             tmx = _MOUSEX
  604.             tmy = _MOUSEY
  605.             IF (ABS(mx - tmx) > 8) OR (ABS(my - tmy) > 8) THEN
  606.                 IF tmx > mx THEN cc = cc + 1
  607.                 IF tmx < mx THEN cc = cc - 1
  608.                 IF tmy > my THEN rr = rr + 1
  609.                 IF tmx < my THEN rr = rr - 1
  610.             END IF
  611.             ScanKey
  612.             IF tbf THEN EXIT SUB
  613.             IF LEN(i$) = 2 THEN
  614.                 kk = ASC(RIGHT$(i$, 1))
  615.                 cc = cc + (kk = 75) - (kk = 77) '                    left right
  616.                 rr = rr + (kk = 72) - (kk = 80) '                    up down
  617.             END IF
  618.             IF rr < 1 THEN rr = 1
  619.             IF rr > 8 THEN rr = 8
  620.             IF cc < 1 THEN cc = 1
  621.             IF cc > 8 THEN cc = 8
  622.         LOOP UNTIL (i$ = Enter$) OR (i$ = "d")
  623.         IF invert THEN rr = 9 - rr: cc = 9 - cc
  624.         IF i = 0 THEN
  625.             fr = rr: fc = cc
  626.         ELSE
  627.             tr = rr: tc = cc
  628.         END IF
  629.     NEXT i
  630.     fs$ = MID$("abcdefgh", fc, 1) + LTRIM$(STR$(9 - fr))
  631.     ts$ = MID$("abcdefgh", tc, 1) + LTRIM$(STR$(9 - tr))
  632.     'IF fs$ = ts$ THEN GOTO getreal
  633.     m$ = fs$ + ts$
  634.     IF m$ = "e1g1" THEN m$ = "O-O"
  635.     IF m$ = "e1c1" THEN m$ = "O-O-O"
  636.     IF m$ = "e8g1" THEN m$ = "O-O"
  637.     IF m$ = "e8c1" THEN m$ = "O-O-O"
  638.  
  639. SUB colorassign
  640.     black& = cp&(0)
  641.     boardwhite& = cp&(1)
  642.     boardblack& = cp&(2)
  643.     red& = _RGB32(255, 0, 0)
  644.     green& = cp&(8)
  645.     blue& = cp&(9)
  646.     white& = cp&(10)
  647.  
  648. SUB Init
  649.     IF highres THEN
  650.         xm = 1280: ym = 800
  651.     ELSE
  652.         xm = 800: ym = 600
  653.     END IF
  654.     SCREEN _NEWIMAGE(xm, ym, 32)
  655.     _DELAY .3
  656.     IF highres THEN _SCREENMOVE 0, 0 ELSE _SCREENMOVE 472, 20
  657.     MaxRow = ym \ 16 - 1
  658.     _DELAY .3
  659.  
  660.     f$ = "chess3.png": i& = _LOADIMAGE(f$): _ICON i&: _FREEIMAGE i&
  661.     _DELAY .3
  662.  
  663.     RESTORE rgb
  664.     FOR p = 0 TO 15
  665.         READ PalNum, r, g, b, Desc$
  666.         cp&(p) = _RGB32(r * 4, g * 4, b * 4)
  667.     NEXT p
  668.     colorassign '                                                    red&, green&, etc, easier to use than palette numbers
  669.  
  670.     RANDOMIZE TIMER '                                                seed generator
  671.     Move = 0
  672.     WorB = 1 '                                                       white=1, black=0
  673.     speed = 3
  674.     q = 28
  675.     q = q * 2
  676.     xq = q: yq = q
  677.     xc = 248: yc = 254 '                                             center of board
  678.  
  679.     Enter$ = CHR$(13)
  680.     Esc$ = CHR$(27) '                                                to quit program
  681.     lf$ = CHR$(10) '                                                 line feed
  682.     crlf$ = Enter$ + lf$
  683.  
  684.     Castle$ = SPACE$(4) '                                            flags QKQK (B then W)
  685.  
  686.     mess$ = ""
  687.     RESTORE PiecePatterns '                                          bit images
  688.     FOR p = 1 TO 6 ' RNBQKP
  689.         PRINT MID$("RNBQKP", p, 1); " ";
  690.         n = 0
  691.         FOR y = 0 TO 21 ' 22 rows
  692.             READ d$
  693.             p1 = INSTR(d$ + "X", "X") '                              find first "on" bit
  694.             FOR t = LEN(d$) TO 1 STEP -1 '                           find last "on" bit
  695.                 IF MID$(d$, t, 1) = "X" THEN
  696.                     p2 = t
  697.                     EXIT FOR
  698.                 END IF
  699.             NEXT t
  700.             FOR x = p1 TO p2
  701.                 pixel = INSTR(".X", MID$(d$, x, 1))
  702.                 n = n + 1
  703.                 IF pixel = 2 THEN c = 3 ELSE c = 4
  704.                 x(p, n) = x + 1
  705.                 y(p, n) = y + 2
  706.                 c(p, n) = c
  707.                 IF pixel = 2 THEN c = 5 ELSE c = 6
  708.                 c(p + 6, n) = c
  709.             NEXT x
  710.         NEXT y
  711.         c(p, 0) = n
  712.         FOR scram = 1 TO 256 '                                       scramble (moves nicer)
  713.             c1 = RND * (c(p, 0) - 1) + 1 '                           any bit
  714.             c2 = RND * (c(p, 0) - 1) + 1 '                           any other bit
  715.             SWAP x(p, c1), x(p, c2)
  716.             SWAP y(p, c1), y(p, c2)
  717.             SWAP c(p, c1), c(p, c2) '                                black
  718.             SWAP c(p + 6, c1), c(p + 6, c2) '                        white
  719.         NEXT scram
  720.     NEXT p
  721.  
  722.     RESTORE Legal '                                                  define how piece moves
  723.     FOR p = 1 TO 6 '                                                 RNBQKP
  724.         READ p$ '                                                    piece, not saved
  725.         FOR t = 0 TO 7 '                                             8 each
  726.             READ mp$(p, t) '                                         mp (move piece)
  727.         NEXT t
  728.     NEXT p
  729.  
  730.     RESTORE SetUp '                                                  initial board position
  731.     FOR r = 8 TO 1 STEP -1 '                                         row
  732.         FOR c = 1 TO 8 '                                             column
  733.             READ b(r, c)
  734.             o(r, c) = b(r, c)
  735.         NEXT c
  736.     NEXT r
  737.  
  738.     elim$ = " ,"
  739.     gm = 0: n = 0
  740.     IF LEN(GameFile$) > 0 THEN ReadGame
  741.     gm = 0
  742.  
  743.     f = f + 1
  744.     f$ = "chess" + LTRIM$(STR$(f))
  745.     OPEN f$ + ".alg" FOR OUTPUT AS #1 '                              algrebraic moves
  746.     OPEN "debug.txt" FOR OUTPUT AS #7
  747.     'MasterLevel = VAL(COMMAND$) '                                    only 4 really tested....
  748.     'GameFile$ = COMMAND$
  749.     'IF _FILEEXISTS(GameFile$) THEN ReadGame ELSE GameFile$ = ""
  750.     MasterLevel = VAL(COMMAND$)
  751.     IF MasterLevel = 0 THEN MasterLevel = 4
  752.     debug = true '                                                   someday I may turn this off
  753.  
  754.     m$ = "(w)hite  (b)lack  (n)one"
  755.     r = _HEIGHT \ 32: c = _WIDTH \ 16
  756.     CLS: LOCATE r, c - LEN(m$) \ 2: PRINT m$;
  757.     DO: _LIMIT 10
  758.         i$ = INKEY$
  759.         IF i$ = "" THEN i$ = " "
  760.         IF i$ = Esc$ THEN SYSTEM
  761.         p = INSTR("bwn", i$)
  762.     LOOP UNTIL p
  763.     IF p = 3 THEN
  764.         human = 0 '                                                  press n for none (watch computer play)
  765.     ELSE
  766.         human = 1
  767.         humanc = p - 1 '                                             0 black, 1 white
  768.         IF humanc = 0 THEN invert = 1 '                              if black, flip board to have black at bottom
  769.     END IF
  770.     CLS
  771.     PlotAll
  772.  
  773.     'opening = 1
  774.     'RESTORE o1
  775.  
  776. SUB KeyGet
  777.     EXIT SUB
  778.     sr = CSRLIN: sc = POS(0)
  779.     DO
  780.         ScanKey
  781.         star = star XOR 1
  782.         IF i$ > "" THEN star = 0
  783.         LOCATE sr, sc
  784.         IF LEN(GameFile$) = 0 THEN PRINT CHR$(32 + star * 10);
  785.     LOOP UNTIL i$ > ""
  786.     IF i$ = "s" THEN WaitForKey = false
  787.  
  788. FUNCTION Make4$ (t$)
  789.     Make4$ = LEFT$(t$ + SPACE$(4), 4)
  790.  
  791. SUB MoveIt (m$, real)
  792.     IF m$ = "res" THEN EXIT SUB '                                    resign?
  793.     fs$ = LEFT$(m$, 2) '                                             from square
  794.     ts$ = RIGHT$(m$, 2) '                                            to square
  795.     tzz = 1 - (LEFT$(m$, 1) = "O") '                                 two moves for a castle
  796.     FOR pass = 1 TO tzz
  797.         IF m$ = "O-O" THEN '                                         castle Kingside
  798.             IF WorB = 1 THEN '                                       white
  799.                 IF pass = 1 THEN '                                   first move of KS castle
  800.                     fs$ = "e1": ts$ = "g1"
  801.                 ELSE ' else 2nd
  802.                     fs$ = "h1": ts$ = "f1"
  803.                 END IF
  804.             ELSE ' black castle
  805.                 IF pass = 1 THEN
  806.                     fs$ = "e8": ts$ = "g8"
  807.                 ELSE
  808.                     fs$ = "h8": ts$ = "f8"
  809.                 END IF
  810.             END IF
  811.         END IF
  812.         IF m$ = "O-O-O" THEN '                                       castle Queenside
  813.             IF WorB THEN '                                           white
  814.                 IF pass = 1 THEN
  815.                     fs$ = "e1": ts$ = "c1"
  816.                 ELSE
  817.                     fs$ = "a1": ts$ = "d1"
  818.                 END IF
  819.             ELSE
  820.                 IF pass = 1 THEN
  821.                     fs$ = "e8": ts$ = "c8"
  822.                 ELSE
  823.                     fs$ = "a8": ts$ = "d8"
  824.                 END IF
  825.             END IF
  826.         END IF
  827.         fr = VAL(RIGHT$(fs$, 1)) '                                   from row
  828.         fc = INSTR("abcdefgh", LEFT$(fs$, 1)) '                      from column
  829.         pm = b(fr, fc) '                                             piece to move
  830.         p = pm + (pm > 6) * 6
  831.         tr = VAL(RIGHT$(ts$, 1)) '                                   to row
  832.         tc = INSTR("abcdefgh", LEFT$(ts$, 1)) '                      to column
  833.         b(tr, tc) = pm '                                             move piece in array
  834.         b(fr, fc) = 0 '                                              blank old array spot
  835.         IF real THEN
  836.             IF b(r, c) = o(r, c) THEN o(r, c) = -1
  837.             FadePiece fr, fc, tr, tc
  838.             IF p = King THEN MID$(Castle$, WorB * 2 + 1, 2) = "XX"
  839.             IF p = Rook THEN
  840.                 IF WorB = 0 THEN
  841.                     IF (fr = 8) AND (fc = 1) THEN MID$(Castle$, 1, 1) = "X"
  842.                     IF (fr = 8) AND (fc = 8) THEN MID$(Castle$, 2, 1) = "X"
  843.                 ELSE
  844.                     IF (fr = 1) AND (fc = 1) THEN MID$(Castle$, 3, 1) = "X"
  845.                     IF (fr = 1) AND (fc = 8) THEN MID$(Castle$, 4, 1) = "X"
  846.                 END IF
  847.             END IF
  848.         END IF
  849.         IF (p = Pawn) AND ((tr = 1) OR (tr = 8)) THEN
  850.             b(tr, tc) = Queen - (pm > 6) * 6 '                       promote to queen
  851.             IF real THEN FadePiece tr, tc, tr, tc '                  show queen
  852.         END IF
  853.     NEXT pass
  854.  
  855. SUB PlotAll
  856.     IF LEN(GameFile$) > 0 THEN
  857.         LOCATE 3, 40 - LEN(GameFile$) \ 2
  858.         PRINT GameFile$;
  859.     END IF
  860.     FOR zr = 1 TO 8
  861.         FOR zc = 1 TO 8
  862.             FadePiece zr, zc, zr, zc
  863.         NEXT zc
  864.     NEXT zr
  865.     'CIRCLE (xc, yc), 100, red&
  866.  
  867.     r = _RED32(boardwhite&) \ 2
  868.     g = _GREEN32(boardwhite&) \ 2
  869.     b = _BLUE32(boardwhite&) \ 2
  870.     COLOR _RGB32(r, g, b)
  871.     FOR i = 1 TO 8 '                                                 legend
  872.         IF invert THEN z = i ELSE z = 9 - i
  873.         n$ = LTRIM$(STR$(z))
  874.         IF invert THEN z = 9 - i ELSE z = i
  875.         a$ = MID$("abcdefgh", z, 1)
  876.         nx = xc - 4 * xq - 12
  877.         ny = yc + (i - 4) * yq - 34
  878.         ax = xc + (i - 5) * xq + 22
  879.         ay = yc + 4 * yq + 3
  880.         _PRINTSTRING (nx, ny), n$
  881.         _PRINTSTRING (ax, ay), a$
  882.     NEXT i
  883.     COLOR white&
  884.  
  885. SUB ReadGame
  886.     DIM g$(500)
  887.     CLS
  888.     OPEN GameFile$ FOR INPUT AS #8
  889.     WHILE NOT (EOF(8))
  890.         INPUT #8, mn, m1$, m2$
  891.         gm = gm + 1: g$(gm) = LTRIM$(m1$)
  892.         gm = gm + 1: g$(gm) = LTRIM$(m2$)
  893.         PRINT m1$; "*"; m2$
  894.     WEND
  895.     CLOSE #8
  896.     _DISPLAY
  897.     SLEEP
  898.     CLS
  899.     _DISPLAY
  900.  
  901. SUB Recurse (Level)
  902.     DispTime
  903.     IF Level = MasterLevel THEN EXIT SUB
  904.     'IF human AND (humanc = WorB) AND (Level = 2) THEN EXIT SUB
  905.  
  906.     FOR t = 1 TO Moves(Level - 1)
  907.         WorB = SaveWorB
  908.         IF (Level MOD 2) = 1 THEN WorB = WorB XOR 1
  909.         TieTo(Level) = t
  910.  
  911.         IF (Score(0, t) > -777) THEN
  912.             BoSave Level
  913.             m$ = Move$(Level - 1, t)
  914.             MoveIt m$, 0
  915.             t$ = rjust$(Moves(Level - 1), 3)
  916.             t$ = t$ + rjust$(t, 4) + " "
  917.             t$ = t$ + Make4$(m$)
  918.             t$ = t$ + rjust$(Score(Level - 1, t), 5)
  919.             ShowMe Level + 1, 24, t$
  920.             CheckBoard Level
  921.             Recurse Level + 1
  922.             TakeBest Level
  923.             Score = Score(Level, 1)
  924.             levm1 = Level - 1
  925.             i = Index
  926.             IF Score(levm, i) <> -777 THEN Score(levm1, i) = Score(levm1, i) - Score
  927.             IF Level = (MasterLevel - 1) THEN Debug2
  928.             BoRestore Level
  929.         END IF
  930.     NEXT t
  931.     ScanKey
  932.  
  933. FUNCTION rjust$ (t, n)
  934.     rjust$ = RIGHT$("   " + STR$(t), n)
  935.  
  936. SUB ScanKey
  937.     i$ = INKEY$
  938.     IF LEN(i$) = 1 THEN
  939.         IF i$ = Enter$ THEN EXIT SUB
  940.         IF i$ = Esc$ THEN CLOSE: SYSTEM
  941.         c = INSTR("123456789ABCDEF", i$)
  942.         IF c > 0 THEN cp&(c) = _RGB32(RND * 255, RND * 255, RND * 255): colorassign: PlotAll
  943.         IF i$ = "a" THEN OnAuto = NOT (OnAuto)
  944.         IF i$ = "i" THEN invert = invert XOR 1: PlotAll
  945.         IF i$ = "p" THEN
  946.             ShowMe 1, 72, "NoPause"
  947.             ShowMe 1, 72, "       "
  948.         END IF
  949.         IF i$ = "s" THEN SHELL _DONTWAIT "notepad debug.txt"
  950.         IF i$ = "t" THEN tbf = 1
  951.         IF i$ = "z" THEN
  952.             sillyf = sillyf XOR 1
  953.             IF sillyf = 0 THEN PlotAll
  954.         END IF
  955.         i$ = ""
  956.     END IF
  957.     IF sillyf AND (rflag = 0) THEN silly
  958.     IF rflag = 0 THEN _DISPLAY
  959.  
  960. SUB ShowAlgebraic (m$)
  961.     IF WorB THEN '                                                  white=1, black=0
  962.         Move = Move + 1 '                                            number the moves
  963.         PRINT #1, RIGHT$("  " + STR$(Move), 3);
  964.         PRINT #1, RIGHT$(SPACE$(10) + m$, 7);
  965.         MoveLog$(Move) = SPACE$(15)
  966.         MID$(MoveLog$(Move), 1, 3) = rjust$(Move, 3)
  967.         MID$(MoveLog$(Move), 5, LEN(m$)) = m$
  968.     ELSE
  969.         MID$(MoveLog$(Move), 11, LEN(m$)) = m$
  970.         PRINT #1, " "; m$
  971.         IF (Move MOD 5) = 0 THEN PRINT #1, ""
  972.     END IF
  973.  
  974.     BeginAt = Move - 18
  975.     IF BeginAt < 1 THEN BeginAt = 1
  976.     dr = 1
  977.     FOR t = BeginAt TO Move
  978.         ShowMe dr + 1, 1, MoveLog$(t)
  979.         dr = dr + 1
  980.     NEXT t
  981.  
  982. SUB ShowAsText (br)
  983.     FOR zr1 = 1 TO 8
  984.         FOR zc1 = 1 TO 8
  985.             zr2 = (10 - zr1) * 2 + 3
  986.             zc2 = zc1 * 3 + 17 + br * 32
  987.             tp = b(zr1, zc1)
  988.             IF tp = 0 THEN
  989.                 z$ = "  "
  990.             ELSEIF tp < 7 THEN
  991.                 z$ = "B" + MID$("RNBQKP", tp, 1)
  992.             ELSE
  993.                 z$ = "W" + MID$("RNBQKP", tp - 6, 1)
  994.             END IF
  995.             ShowMe zr2, zc2, z$
  996.         NEXT zc1
  997.     NEXT zr1
  998.  
  999. SUB ShowMe (dr, dc, t$)
  1000.     EXIT SUB
  1001.     sr = CSRLIN '                                                    save row
  1002.     sc = POS(0) '                                                    save column
  1003.     IF (dr > 0) AND (dr < MaxRow) AND (dc > 0) AND (dc < 76) THEN
  1004.         LOCATE dr, dc '                                              display row & column
  1005.         PRINT t$;
  1006.     END IF
  1007.     IF NOT (OnAuto) THEN KeyGet
  1008.     LOCATE sr, sc '                                                  restore to old location
  1009.     '   IF Pause THEN SLEEP
  1010.  
  1011. SUB ShowTime (trow, t!, Desc$)
  1012.     s! = t!
  1013.     SELECT CASE s!
  1014.         CASE IS > 3600
  1015.             unit$ = "h"
  1016.             s! = s! / 3600
  1017.         CASE IS > 60
  1018.             unit$ = "m"
  1019.             s! = s! / 60
  1020.         CASE ELSE
  1021.             unit$ = "s"
  1022.     END SELECT
  1023.     trow = trow + 3
  1024.     LOCATE trow, 34 - LEN(Desc$): PRINT Desc$;
  1025.     LOCATE trow, 34
  1026.     PRINT USING "###.#"; s!;
  1027.     PRINT unit$
  1028.  
  1029. SUB TakeBest (Level)
  1030.     FOR scram = 0 TO 99
  1031.         s1 = RND * (Moves(Level) - 1) + 1
  1032.         s2 = RND * (Moves(Level) - 1) + 1
  1033.         SWAP Score(Level, s1), Score(Level, s2)
  1034.         SWAP Move$(Level, s1), Move$(Level, s2)
  1035.         SWAP Index(Level, s1), Index(Level, s2)
  1036.     NEXT scram
  1037.  
  1038.     passes = 0
  1039.     ReSort:
  1040.     Score = -999 ' assume no moves
  1041.     DO
  1042.         Sorted = true
  1043.         FOR s = 2 TO Moves(Level)
  1044.             IF Score(Level, s - 1) < Score(Level, s) THEN
  1045.                 Sorted = false
  1046.                 SWAP Score(Level, s - 1), Score(Level, s)
  1047.                 SWAP Move$(Level, s - 1), Move$(Level, s)
  1048.                 SWAP Index(Level, s - 1), Index(Level, s)
  1049.             END IF
  1050.         NEXT s
  1051.     LOOP UNTIL Sorted
  1052.  
  1053.     m$ = Move$(Level, 1)
  1054.     Score = Score(Level, 1)
  1055.     Index = Index(Level, 1)
  1056.  
  1057.     'IF Level = -1 THEN
  1058.     '    FOR lb = 0 TO 2 '                                            stop repeats
  1059.     '        IF INSTR(MoveLog$(Move - lb), m$) THEN
  1060.     '            Score(Level, 1) = Score(Level, 2) - 1 '              best = 2nd best-1
  1061.     '            passes = passes + 1
  1062.     '            IF passes < 5 THEN GOTO ReSort '                     repeat may be only move
  1063.     '        END IF
  1064.     '    NEXT lb
  1065.     'END IF
  1066.  
  1067.     IF Level = 1 THEN
  1068.         IF Score = -777 THEN '                                       in check, no escape
  1069.             mess$ = "Mate"
  1070.         ELSEIF Score = -999 THEN '                                   no moves
  1071.             mess$ = "Stalemate"
  1072.         END IF
  1073.     END IF
  1074.  
  1075.     IF (Level = 1) AND (Score = 777) THEN Score(0, TieTo(1)) = -777
  1076.  
  1077. FUNCTION TextCol (xc)
  1078.     TextCol = (xc - 1) * 2 + 25
  1079.  
  1080. FUNCTION TextRow (xr)
  1081.     TextRow = (8 - xr) * 1 + 8
  1082.  
  1083. FUNCTION TextVal (xr, xc)
  1084.     i = b(xr, xc)
  1085.     i = i + (i > 6) * 6
  1086.     TextVal = i
  1087.  
  1088. SUB TryMove (Level, fr, fc) '                                        from row, from column
  1089.     mp = b(fr, fc)
  1090.     IF mp = 0 THEN END
  1091.     mc = -(mp > 6) - (mp = 0) * 2 '                                  moving color
  1092.     IF mc = 2 THEN END
  1093.     mp = mp + (mp > 6) * 6
  1094.     IF mc = 1 THEN s = -1 ELSE s = 1 '                               direction a pawn moves
  1095.  
  1096.     FOR n = 0 TO 7 '                                                 possible 8 dirs
  1097.         udlr$ = mp$(mp, n) '                                         up/down/left/right
  1098.         IF udlr$ = "0000" THEN EXIT FOR '                            added 2Jan95
  1099.         du = VAL(MID$(udlr$, 1, 1)) '                                direction up
  1100.         dd = VAL(MID$(udlr$, 2, 1)) '                                direction down
  1101.         dl = VAL(MID$(udlr$, 3, 1)) '                                direction left
  1102.         dr = VAL(MID$(udlr$, 4, 1)) '                                direction right
  1103.         IF mp <> Knight THEN '                                       not knight
  1104.             du = SGN(du) * s '                                       one square at a time
  1105.             dd = SGN(dd) * s
  1106.             dl = SGN(dl) * s
  1107.             dr = SGN(dr) * s
  1108.         END IF
  1109.         IF INSTR(udlr$, "8") THEN TrySq = 8 ELSE TrySq = 1
  1110.         IF (mp = Pawn) AND (n = 0) THEN '                            pawn first move?
  1111.             IF (fr = 2) AND (WorB = 1) THEN TrySq = 2 '              gambit for white
  1112.             IF (fr = 7) AND (WorB = 0) THEN TrySq = 2 '              gambit for black
  1113.         END IF
  1114.         tr = fr: tc = fc '                                           row, column
  1115.         IF TrySq = 0 THEN END
  1116.         FOR sq = 1 TO TrySq '                                        up to 8 loops
  1117.             cap = false
  1118.             Score = 0 '                                              must init
  1119.             tr = tr - du + dd '                                      row=row-up+down
  1120.             tc = tc - dl + dr '                                      column=column-left+right
  1121.             IF (tr < 1) OR (tr > 8) OR (tc < 1) OR (tc > 8) THEN EXIT FOR
  1122.             cp = b(tr, tc) '                                         capture piece
  1123.             cc = -(cp > 6) - (cp = 0) * 2 '                          capture color
  1124.             cp = cp + (cp > 6) * 6
  1125.             IF mc = cc THEN '                                        own piece!
  1126.                 EXIT FOR
  1127.             ELSEIF (mc XOR 1) = cc THEN '                            capture
  1128.                 IF (mp = Pawn) AND (n = 0) THEN EXIT FOR ' no diag, no cap!
  1129.                 cap = true
  1130.                 '                 RNBQKP
  1131.                 Score = VAL(MID$("533901", cp, 1)) * 10
  1132.                 IF (Score > 0) AND (Level = 0) THEN Score = Score + 2
  1133.                 IF Score = 0 THEN Score = 777 '                      king capture
  1134.                 ' IF redo AND (Score = 777) THEN Score = 25
  1135.             ELSE
  1136.                 IF (mp = Pawn) AND (n > 0) THEN EXIT FOR
  1137.             END IF
  1138.             IF mp = Pawn THEN
  1139.                 IF (tr = 1) OR (tr = 8) THEN '                       promote pawn
  1140.                     IF Score <> 777 THEN Score = Score + 99
  1141.                 END IF
  1142.             END IF
  1143.  
  1144.             ' usually not good to be moving the King
  1145.             IF mp = King THEN Score = Score - 4
  1146.  
  1147.             ' small plus for king moving out of check
  1148.             InCheck = (mc = SaveWorB) AND check
  1149.             IF (mp = King) AND InCheck THEN Score = Score + 2
  1150.  
  1151.             ' leave king cap scores, also normal bonuses if in check
  1152.             IF (Score <> 777) AND (NOT (InCheck)) AND (mp <> King) THEN
  1153.                 dis1 = ABS(fr - okr) + ABS(fc - okc) '                 get closer to king
  1154.                 dis2 = ABS(tr - okr) + ABS(tc - okc)
  1155.                 ' IF dis2 < dis1 THEN Score = Score + (dis1 - dis2)
  1156.                 Score = Score + dis1 - dis2
  1157.  
  1158.                 IF Move < 30 THEN
  1159.                     dir = SGN((fr - tr) * s)
  1160.                     IF dir = 1 THEN Score = Score + 2 '              move ahead at begin&mid
  1161.                 END IF
  1162.  
  1163.                 ' priority to getting a piece first moved
  1164.                 IF mp <> Rook THEN
  1165.                     IF b(fr, fc) = o(fr, fc) THEN Score = Score + 1
  1166.                 END IF
  1167.  
  1168.                 ' priority to getting a piece off the bottom rank
  1169.                 IF (fr = 1) AND (tr > 1) AND (WorB = 1) THEN Score = Score + 1
  1170.                 IF (fr = 8) AND (tf < 8) AND (WorB = 0) THEN Score = Score + 1
  1171.             END IF
  1172.  
  1173.             fs$ = MID$("abcdefgh", fc, 1) + CHR$(48 + fr) '          from square
  1174.             ts$ = MID$("abcdefgh", tc, 1) + CHR$(48 + tr) '          to square
  1175.             AddIt Level, fs$ + ts$, Score
  1176.             IF cap AND (mp <> Pawn) THEN EXIT FOR '                  stop looking
  1177.         NEXT sq
  1178.     NEXT n
  1179.  
  1180. SUB silly STATIC
  1181.     PlotAll
  1182.     br = 255
  1183.     zz = (zz + 1) MOD 50: IF zz = 1 THEN r! = RND: g! = RND: b! = RND
  1184.     x1 = xc - 4 * xq
  1185.     y1 = yc - 4 * yq
  1186.     x2 = x1 + 8 * xq
  1187.     y2 = y1 + 8 * yq
  1188.     'LINE (x1, y1)-(x2, y2), boardwhite&
  1189.     FOR sy = y1 TO y2
  1190.         FOR sx = x1 TO x2
  1191.             p& = POINT(sx, sy)
  1192.             IF p& = boardwhite& THEN
  1193.                 z = ABS((sx - xc - xq \ 2) * (sy - yc - yq \ 2))
  1194.                 PSET (sx, sy), _RGB32(br * SIN(.1 * r! * z + zz), br * SIN(.155 * g! * z + zz), br * SIN(2 * b! * z + zz))
  1195.             END IF
  1196.     NEXT sx: NEXT sy
  1197.  
  1198. SUB SaveForTakeBack STATIC
  1199.     FOR i = 10 TO 1 STEP -1
  1200.         FOR r = 1 TO 8
  1201.             FOR c = 1 TO 8
  1202.                 tb(r, c, i) = tb(r, c, i - 1)
  1203.             NEXT c
  1204.         NEXT r
  1205.     NEXT i
  1206.     FOR r = 1 TO 8
  1207.         FOR c = 1 TO 8
  1208.             tb(r, c, 0) = b(r, c)
  1209.         NEXT c
  1210.     NEXT r
  1211.     tbc = tbc + 1
  1212.     IF tbc > 10 THEN tbc = 10
  1213.  
  1214. SUB takeback
  1215.     IF tbc < 2 THEN EXIT SUB
  1216.     SOUND 777, 2
  1217.     FOR r = 1 TO 8
  1218.         FOR c = 1 TO 8
  1219.             b(r, c) = tb(r, c, 2)
  1220.         NEXT c
  1221.     NEXT r
  1222.     FOR i = 0 TO 9
  1223.         FOR r = 1 TO 8
  1224.             FOR c = 1 TO 8
  1225.                 tb(r, c, i) = tb(r, c, i + 1)
  1226.             NEXT c
  1227.         NEXT r
  1228.     NEXT i
  1229.     tbc = tbc - 1
  1230.  
Title: Eh? (Canadian)
Post by: Richard Frost on January 29, 2020, 12:51:47 am
Yes, I think the initial version only played itself, which is the ideal
way to improve the "smarts" of it.  The newest version posted lets
the user pick a side, or "none" for automation.  The purpose of
the initial post is to show the guts of an operating engine - the
approach I took with moving pieces legally and whatnot.  I still
don't even have the mouse working - arrow keys to move. 

I don't know how anyone got the notion that I created this in a day!
I got it to run in QB64 in a day.  It's old QB4.5 code of mine that
probably took me at least a  month to write.

How does one choose which resolution to use?  I had this in 1024*768
for awhile, but I like to see other windows, hence this 800*600.  The old
640*480 is too limiting - no room for big graphics AND text.  It's a problem
I never encounted with old QB4.5 - what to choose!  What factors do you
folk consider to choose a mode?  Or should everything be resizable?
Title: Re: A 90% complete chess engine
Post by: bplus on January 29, 2020, 10:27:54 am
Hi Richard Frost,

The comments about doing chess program in a day were meant for STxAxTIC whose post started this thread.

Hey! Your new one works (maybe I just needed to download png for icon file like for this one for last one. no, no png was provided) and it has a nicely sized board (800 x 600 is nice size until out grows all the options you start adding) and the vital question of doing something different with white squares has been answered! :D

 


So the AI calculates moves but you still have to press enter to get the oppositions pieces moved (after you see the blinking squares).

Hmm... how would plasma look for Black squares :)
Title: Re: A 90% complete chess engine
Post by: SMcNeill on January 29, 2020, 10:31:36 am
Who wants a chess board that looks like half the tiles are high on mushrooms?  White/Red on Black is fine for me, as it seems less distracting and non-seizure inducing.
Title: Re: A 90% complete chess engine
Post by: bplus on January 29, 2020, 11:53:58 am
Who wants a chess board that looks like half the tiles are high on mushrooms?  White/Red on Black is fine for me, as it seems less distracting and non-seizure inducing.

One is not stuck with mushrooms :D and it's not like he doesn't know silly ;-)
Code: QB64: [Select]
  1. sillyf = 1 '                                            Moire effect, toggle with "z", or just default this to 0
  2.  
Title: Re: A 90% complete chess engine
Post by: Richard Frost on January 29, 2020, 12:51:54 pm
Yes, the graphics are a bit distracting, until one gets used to it.  Normally I *do* have
it turned off.  I set the silly flag in the upload to make it easier for everyone to see
the mayhem without having to read or change any code. 

I saw a Queen jump across pawns to eat the other Queen recently....hope that bug isn't in
the upload.  And I'm wrong about the castling, it's still wonky. 

"Bugs spell job security." 
Title: Re: A 90% complete chess engine
Post by: bplus on January 29, 2020, 01:23:18 pm
Quote
"Bugs spell job security."

LOL played a decent game with White Castling, the moves see farther ahead than I which isn't saying too much.
Title: Re: A 90% complete chess engine
Post by: romichess on January 29, 2020, 05:02:58 pm
Now that it works it is more interesting! :)

I was wondering how many moves deep my engine RomiChess would have to see in order to win. I started off RomiChess at 2 moves deep. Note that finishing off capture sequences is part of a 2 ply search and is hard coded. RomiChess played the black pieces. At 2 ply deep RomiChess plays each move instantly.

1. d3 e5 2. c3 Bc5 3. Be3 Bxe3 4. fxe3 Qh4+ 5. Kd2 Ne7 6. g3 Qf6 7. Qe1 Qb6
8. b3 Rf8 9. Bg2 Nbc6 10. Nf3 Nf5 11. d4 Qa5 12. Nxe5 Nxe5 13. dxe5 Qxe5
14. e4 Nd6 15. Na3 Nxe4+ 16. Bxe4 Qxe4 17. Rf1 d5 18. Rf4 Qe7 19. Rd4 Qxa3
20. Qf2 Qb2+ 21. Kd1 Qxa1+ 22. Kd2 Qxa2+ 23. Kd1 Qxb3+ 24. Kc1 Qxc3+ 25.
Kb1 Bf5+ 26. Ka2 Be4 27. e3 c5 28. Ra4 Qe5 29. Qb2 Qxb2+ 30. Kxb2 Ke7 31.
Ra5 Rfc8 32. Ra1 Ke6 33. h3 Ke5 34. Ra4 a5 35. Ra1 b5 36. Ra3 a4 37. Ra1 b4
38. Ra2 a3+ 39. Kb3 h5 40. Ra1 Re8 41. Ra2 Re7 42. Ra1 Rae8 43. Ra2 Rd8 44.
h4 Rde8 45. Ra1 Re6 46. Ra2 R8e7 47. Ra1 Rg6 48. Ra2 Rxg3 49. Re2 Rg1 50.
Ra2 Re1 51. Rd2 Rxe3+ 52. Ka4 Re1 53. Ra2 Bd3 54. Rd2 Kd4 55. Ra2 Rh1 56.
Rd2 Rxh4 57. Ra2 Rh1 58. Rd2 Rhe1 59. Ra2 Re8 60. Rd2 g5 61. Ra2 f5 62. Rd2
f4 63. Ra2 f3 64. Rd2 R8e7 65. Ra2 Bf5 66. Rd2+ Ke5 67. Ra2 Bd3 68. Rd2 Be4
69. Ra2 Bf5 70. Rd2 Re8 71. Ra2 Kd4 72. Rd2+ Bd3 73. Ra2 R8e7 74. Rd2 g4
75. Ra2 h4 76. Rd2 Re8 77. Ra2 h3 78. Rd2 g3 79. Ra2 f2 80. Rxf2 gxf2 81.
Ka5 f1=Q 82. Kb6 a2 83. Kc7 a1=Q 84. Kc6 h2 85. Kc7 h1=Q 86. Kb7 b3 87. Kc6
Qa7 88. Kd6 Qf6# 0-1

I will be doing more with my chess tutorial in the coming days. Maybe I'll just steal this interface for my tutorial! :)

P.S. Romi tried to castle on move 8 so I just moved 8 ... Rf8 instead. Please do not think that Romi made that terrible move on its own volition. lol

P.P.S. I decided to play a quick game with the black pieces.

1. d3 e5 2. a3 Bc5 3. Be3 Bxe3 4. fxe3 Nf6 5. Nd2 d5 6. d4 Nc6 7. dxe5 Nxe5
8. h3 Qd6 9. Ngf3 Neg4 10. Nc4 Qg3+ 11. Kd2 Nf2 12. Qc1 N6e4+ 13. Ke1 Nd3+
14. Kd1 Qe1+ 15. Nxe1 Ndf2# 0-1
Title: Re: A 90% complete chess engine
Post by: TempodiBasic on February 02, 2020, 12:25:05 pm
Yes I confirm that there is the bug of EnterKeypressing for get the Black move,
but why does AI prefer always the Nimzowitsch to open game of white ?
https://it.wikipedia.org/wiki/Difesa_Nimzowitsch (https://it.wikipedia.org/wiki/Difesa_Nimzowitsch) It is a minor defence against E4!
I think you must use a book of opening to improve AI force.

Here my first game user's experience:

Fine the gameplay also if there are the distracting lights of white squares and  no support of mouse.
A big bug ... AI doesn't recognize the checkmate! See screenshot!
PS your program run away to Print key of Windows to capture the screen. So i must install SnapShot to get it...(I know that there is the SMcNeill Steve's library... but I don't want to write code, now I'm just a player)

  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Here the first game like White
Quote
1. e4 Nc6
2. d4 e6
3 Bc4 Na5
4 Bd3 Nc6
5 Nf3  h6
6 O-O Nge7
7 c4  Nb4
8 Be2 Nbc6
9 Nc3  b6
10 Re1 Bb7
11 d5 Nb8
12 dxe6 fxe6
13 e5  Nf5
14 g4  Nfe7
15 Nh4  g5
16 Nf3 Bg7
17 Bd3 O-O
18 Nc3 Qe8
19 Qe2 Qf7
20 Nxg5 hxg5
21 Nxg5 Qe8
22 Bh7+ Kh8
23 Qd3 Nc6
24 Qh3 Rd8
25 Bg6+ Bh6
26 Qxh6+ Kg8
27 Qh7#

moreover...
the game went on with this following moves...
Quote
27... Nb4
28 Qxg8 Qxg6

  [ This attachment cannot be displayed inline in 'Print Page' view ]  
so if you want improve that AI
1. not only it must be build the rule of checkmate (the king is under attack and it will be captured to the next move and there is no defence to this)
2. but also you must build the rule without King there is gameover (No King is equal No game for that color/side)

Thanks to share you chessprogram with a intermediate AI and any lack of some rules




Title: Re: A 90% complete chess engine
Post by: TempodiBasic on February 02, 2020, 12:53:49 pm
another bit feedback
in my first game as Black... I cannot castle
this is the sequence of moves
Quote
1 d3   d5
2 Be3  e5
3 a3   c5
4 c3  Nc6
5 Qb3 Nf6
6 f3  Bd6
7 Nd2

this is the screenshot
  [ This attachment cannot be displayed inline in 'Print Page' view ]  
here if I take King and I do 2 steps to the left the program takes my move but then it resets the input to me refusing my choice.

IMHO also this rules must be added to the AI (castle is for white and for black) .
I hope this is not so much for a positive feedback!
Title: Re: A 90% complete chess engine
Post by: TempodiBasic on February 02, 2020, 01:52:41 pm
About CHESS.BAS that follows the QB64 package of example of QB and Qbasic code runnable under QB64..

I and Bplus have worked more on adjurnament of the interface and of the input adding mouse support to input the move, a set of buttons to choose how to play, showing avaiabled moves of the piece that the mouse is pointing, but not so much improving  the AI because without understanding how it is structured the original AI there are poor opportunity to empower something, it is simpler  write again with your way. In fact Bplus wrote the most of the code to let choose and play with the Black the gamer  vs AI. And it was not so clear to me how to use the system  implemented into original AI to play with Black. AI  uses an 8x8 chess table miming the fisical chessboard and no a single array of 64 (0-63) elements. The moves are calculated on fly and not with a offset.
Also with its all limitations the original AI recognize an impossible to continue setting on the chessboard. See screenshots

Title: Re: A 90% complete chess engine
Post by: SierraKen on February 02, 2020, 04:46:59 pm
Bplus, I got pretty close to finishing a 2-person checkers game after a week of programming every day. But I can't figure out how to keep the king symbol on a king checker piece. The symbol shows up fine on it when you get to the other side, but then when you move again it's deleted. I'm sure I didn't do the variables the right way. I actually just tossed in variables not knowing exactly what they do which is totally not good. I also am getting hang-ups every once in awhile where it won't let you plot coordinates (I don't even use the mouse in this game). So, I will probably either take a long break on this game or just give up on it.
Feel free to have the code anyone, if you wish to do anything with it. Just remember the king symbol doesn't stay and once in awhile maybe it won't let you plot (not sure I may have fixed that). The only reason I'm posting the code today is to show everyone how good I actually did make it so far. You can jump, but only do 1 jump per move. So all in all, it's a very rough and bad way to play checkers, but it is the best one I've made so far. Oh also, it does say which player wins when they do win. I've only played 1 full game of it myself. And like 40 other tries of fixing things. lol Been a crazy little program. But for now, I'm finished with it myself.

Code: QB64: [Select]
  1. _TITLE "1 Jump - 2 Player Checkers - by Ken G."
  2. SCREEN _NEWIMAGE(800, 600, 32)
  3. DIM black2(88), red2(88), bking(88), rking(88)
  4.  
  5. 'Make checkerboard
  6. LINE (149, 49)-(651, 551), _RGB32(255, 255, 255), B
  7. FOR ly = 50 TO 487.5 STEP 125
  8.     FOR lx = 212.5 TO 650 STEP 125
  9.         LINE (lx - 62.5, ly)-(lx, ly + 62.5), _RGB32(255, 0, 0), BF
  10.     NEXT lx
  11.     FOR lx = 212.5 TO 650 STEP 125
  12.         LINE (lx, ly + 62.5)-(lx + 62.5, ly + 125), _RGB32(255, 0, 0), BF
  13.     NEXT lx
  14.     FOR lx = 275 TO 650 STEP 125
  15.         LINE (lx - 62.5, ly)-(lx, ly + 62.5), _RGB32(0, 0, 0), BF
  16.     NEXT lx
  17.     FOR lx = 150 TO 587.5 STEP 125
  18.         LINE (lx, ly + 62.5)-(lx + 62.5, ly + 125), _RGB32(0, 0, 0), BF
  19.     NEXT lx
  20. NEXT ly
  21. COLOR _RGB32(255, 255, 255)
  22. LOCATE 3, 87: PRINT "Red"
  23. LOCATE 4, 87: PRINT "From:"
  24. LOCATE 9, 87: PRINT "To:"
  25. LOCATE 3, 5: PRINT "Black"
  26. LOCATE 4, 5: PRINT "From:"
  27. LOCATE 9, 5: PRINT "To:"
  28.  
  29. COLOR _RGB32(127, 255, 255)
  30. FOR lx = 170 TO 607.5 STEP 62.5
  31.     h = h + 1
  32.     h$ = STR$(h)
  33.     _PRINTSTRING (lx, 30), h$
  34. NEXT lx
  35. COLOR _RGB32(128, 249, 127)
  36. FOR ly = 70 TO 507.5 STEP 62.5
  37.     v = v + 1
  38.     v$ = STR$(v)
  39.     _PRINTSTRING (120, ly), v$
  40. NEXT ly
  41. h = 0: v = 0
  42. COLOR _RGB32(127, 255, 255)
  43. FOR lx = 170 TO 607.5 STEP 62.5
  44.     h = h + 1
  45.     h$ = STR$(h)
  46.     _PRINTSTRING (lx, 560), h$
  47. NEXT lx
  48. COLOR _RGB32(128, 249, 127)
  49. FOR ly = 70 TO 507.5 STEP 62.5
  50.     v = v + 1
  51.     v$ = STR$(v)
  52.     _PRINTSTRING (660, ly), v$
  53. NEXT ly
  54.  
  55. 'setup pieces
  56. 'black
  57. ly = 50
  58. FOR lx = 212.5 TO 650 STEP 125
  59.     CIRCLE (lx + 31.25, ly + 31.25), 20, _RGB32(50, 50, 50)
  60.     PAINT (lx + 31.25, ly + 31.25), _RGB32(50, 50, 50)
  61. NEXT lx
  62. FOR lx = 212.5 TO 650 STEP 125
  63.     CIRCLE (lx - 31.25, ly + 93.75), 20, _RGB32(50, 50, 50)
  64.     PAINT (lx - 31.25, ly + 93.75), _RGB32(50, 50, 50)
  65. NEXT lx
  66. FOR lx = 212.5 TO 650 STEP 125
  67.     CIRCLE (lx + 31.25, ly + 156.25), 20, _RGB32(50, 50, 50)
  68.     PAINT (lx + 31.25, ly + 156.25), _RGB32(50, 50, 50)
  69. NEXT lx
  70. 'red
  71. ly = 206.25
  72. FOR lx = 212.5 TO 650 STEP 125
  73.     CIRCLE (lx - 31.25, ly + 187.5), 20, _RGB32(200, 50, 50)
  74.     PAINT (lx - 31.25, ly + 187.5), _RGB32(200, 50, 50)
  75. NEXT lx
  76. FOR lx = 212.5 TO 650 STEP 125
  77.     CIRCLE (lx + 31.25, ly + 250), 20, _RGB32(200, 50, 50)
  78.     PAINT (lx + 31.25, ly + 250), _RGB32(200, 50, 50)
  79. NEXT lx
  80. FOR lx = 212.5 TO 650 STEP 125
  81.     CIRCLE (lx - 31.25, ly + 312.5), 20, _RGB32(200, 50, 50)
  82.     PAINT (lx - 31.25, ly + 312.5), _RGB32(200, 50, 50)
  83. NEXT lx
  84.  
  85. 'The coordinate variables use a 2 digit number, the first digit is the horizon, the second is the vertical.
  86. black2(1) = 12
  87. black2(2) = 14
  88. black2(3) = 16
  89. black2(4) = 18
  90.  
  91. black2(5) = 21
  92. black2(6) = 23
  93. black2(7) = 25
  94. black2(8) = 27
  95.  
  96. black2(9) = 32
  97. black2(10) = 34
  98. black2(11) = 36
  99. black2(12) = 38
  100.  
  101. red2(9) = 81
  102. red2(10) = 83
  103. red2(11) = 85
  104. red2(12) = 87
  105.  
  106. red2(5) = 72
  107. red2(6) = 74
  108. red2(7) = 76
  109. red2(8) = 78
  110.  
  111. red2(1) = 61
  112. red2(2) = 63
  113. red2(3) = 65
  114. red2(4) = 67
  115.  
  116. '----------------------------------------------------------------------------
  117. 'Main Loop
  118.  
  119. _LIMIT 200
  120.  
  121. 'Player One
  122. one:
  123. COLOR _RGB32(128, 249, 127)
  124. LOCATE 5, 87: PRINT "Horizon": LOCATE 6, 87: INPUT ph
  125. IF ph > 8 OR ph < 1 THEN GOTO one:
  126. IF ph <> INT(ph) THEN GOTO one:
  127. COLOR _RGB32(127, 255, 255)
  128. LOCATE 7, 87: PRINT "Vertical": LOCATE 8, 87: INPUT pv
  129. IF pv > 8 OR pv < 1 THEN GOTO one:
  130. IF pv <> INT(pv) THEN GOTO one:
  131. ph$ = STR$(ph)
  132. pv$ = STR$(pv)
  133. sp$ = ph$ + pv$
  134. sp = VAL(sp$)
  135. FOR check = 1 TO 88
  136.     IF red2(check) = sp THEN ch = sp: GOTO move:
  137. NEXT check
  138. GOTO one:
  139.  
  140. 'Player Two
  141. two:
  142. COLOR _RGB32(128, 249, 127)
  143. LOCATE 5, 5: PRINT "Horizon": LOCATE 6, 5: INPUT ph3
  144. IF ph3 > 8 OR ph3 < 1 THEN GOTO two:
  145. IF ph3 <> INT(ph3) THEN GOTO two:
  146. COLOR _RGB32(127, 255, 255)
  147. LOCATE 7, 5: PRINT "Vertical": LOCATE 8, 5: INPUT pv3
  148. IF pv3 > 8 OR pv3 < 1 THEN GOTO two:
  149. IF pv3 <> INT(pv3) THEN GOTO two:
  150. ph3$ = STR$(ph3)
  151. pv3$ = STR$(pv3)
  152. sp3$ = ph3$ + pv3$
  153. sp3 = VAL(sp3$)
  154. FOR check2 = 1 TO 88
  155.     IF black2(check2) = sp3 THEN ch2 = sp3: GOTO move2:
  156. NEXT check2
  157. GOTO two:
  158.  
  159. '----------------------------------------------------------------------------
  160.  
  161. move:
  162. COLOR _RGB32(128, 249, 127)
  163. LOCATE 10, 87: PRINT "Horizon": LOCATE 11, 87: INPUT ph2
  164. IF ph2 > 8 OR ph2 < 1 THEN GOTO one:
  165. IF ph2 <> INT(ph2) THEN GOTO one:
  166.  
  167. COLOR _RGB32(127, 255, 255)
  168. LOCATE 12, 87: PRINT "Vertical": LOCATE 13, 87: INPUT pv2
  169. IF pv2 > 8 OR pv2 < 1 THEN GOTO one:
  170. IF pv2 <> INT(pv2) THEN GOTO one:
  171. ph2$ = STR$(ph2)
  172. pv2$ = STR$(pv2)
  173. sp2$ = ph2$ + pv2$
  174. sp2 = VAL(sp2$)
  175. IF sp = sp2 THEN GOTO one:
  176. IF pv = pv2 OR ph = ph2 THEN
  177.     COLOR _RGB32(255, 0, 0)
  178.     LOCATE 15, 87
  179.     PRINT "Illegal Move"
  180.     GOTO one:
  181.  
  182. 'Check for red squares.
  183. IF sp2 = 11 OR sp2 = 13 OR sp2 = 15 OR sp2 = 17 OR sp2 = 22 OR sp2 = 24 OR sp2 = 26 OR sp2 = 28 THEN
  184.     COLOR _RGB32(255, 0, 0)
  185.     LOCATE 15, 87
  186.     PRINT "Illegal Move"
  187.     GOTO one:
  188. IF sp2 = 31 OR sp2 = 33 OR sp2 = 35 OR sp2 = 37 OR sp2 = 42 OR sp2 = 44 OR sp2 = 46 OR sp2 = 48 THEN
  189.     COLOR _RGB32(255, 0, 0)
  190.     LOCATE 15, 87
  191.     PRINT "Illegal Move"
  192.     GOTO one:
  193. IF sp2 = 51 OR sp2 = 53 OR sp2 = 55 OR sp2 = 57 OR sp2 = 62 OR sp2 = 64 OR sp2 = 66 OR sp2 = 68 THEN
  194.     COLOR _RGB32(255, 0, 0)
  195.     LOCATE 15, 87
  196.     PRINT "Illegal Move"
  197.     GOTO one:
  198. IF sp2 = 71 OR sp2 = 73 OR sp2 = 75 OR sp2 = 77 OR sp2 = 82 OR sp2 = 84 OR sp2 = 86 OR sp2 = 88 THEN
  199.     COLOR _RGB32(255, 0, 0)
  200.     LOCATE 15, 87
  201.     PRINT "Illegal Move"
  202.     GOTO one:
  203.  
  204. red2(ch) = sp2
  205.  
  206. 'Draw player one checker in the new square.
  207. 'First erase the old checker.
  208. IF sp = 12 THEN CIRCLE (243.75, 81.25), 20, _RGB32(0, 0, 0): PAINT (243.75, 81.25), _RGB32(0, 0, 0): x1 = 243.75: y1 = 81.25
  209. IF sp = 14 THEN CIRCLE (368.75, 81.25), 20, _RGB32(0, 0, 0): PAINT (368.75, 81.25), _RGB32(0, 0, 0): x1 = 368.75: y1 = 81.25
  210. IF sp = 16 THEN CIRCLE (493.75, 81.25), 20, _RGB32(0, 0, 0): PAINT (493.75, 81.25), _RGB32(0, 0, 0): x1 = 493.75: y1 = 81.25
  211. IF sp = 18 THEN CIRCLE (618.75, 81.25), 20, _RGB32(0, 0, 0): PAINT (618.75, 81.25), _RGB32(0, 0, 0): x1 = 618.75: y1 = 81.25
  212. IF sp = 21 THEN CIRCLE (181.25, 143.75), 20, _RGB32(0, 0, 0): PAINT (181.25, 143.75), _RGB32(0, 0, 0): x1 = 181.25: y1 = 143.75
  213. IF sp = 23 THEN CIRCLE (306.25, 143.75), 20, _RGB32(0, 0, 0): PAINT (306.25, 143.75), _RGB32(0, 0, 0): x1 = 306.25: y1 = 143.75
  214. IF sp = 25 THEN CIRCLE (431.25, 143.75), 20, _RGB32(0, 0, 0): PAINT (431.25, 143.75), _RGB32(0, 0, 0): x1 = 431.25: y1 = 143.75
  215. IF sp = 27 THEN CIRCLE (556.25, 143.75), 20, _RGB32(0, 0, 0): PAINT (556.25, 143.75), _RGB32(0, 0, 0): x1 = 556.25: y1 = 143.75
  216. IF sp = 32 THEN CIRCLE (243.75, 206.25), 20, _RGB32(0, 0, 0): PAINT (243.75, 206.25), _RGB32(0, 0, 0): x1 = 243.75: y1 = 206.25
  217. IF sp = 34 THEN CIRCLE (368.75, 206.25), 20, _RGB32(0, 0, 0): PAINT (368.75, 206.25), _RGB32(0, 0, 0): x1 = 368.75: y1 = 206.25
  218. IF sp = 36 THEN CIRCLE (493.75, 206.25), 20, _RGB32(0, 0, 0): PAINT (493.75, 206.25), _RGB32(0, 0, 0): x1 = 493.75: y1 = 206.25
  219. IF sp = 38 THEN CIRCLE (618.75, 206.25), 20, _RGB32(0, 0, 0): PAINT (618.75, 206.25), _RGB32(0, 0, 0): x1 = 618.75: y1 = 206.25
  220. IF sp = 41 THEN CIRCLE (181.25, 268.75), 20, _RGB32(0, 0, 0): PAINT (181.25, 268.75), _RGB32(0, 0, 0): x1 = 181.25: y1 = 268.75
  221. IF sp = 43 THEN CIRCLE (306.25, 268.75), 20, _RGB32(0, 0, 0): PAINT (306.25, 268.75), _RGB32(0, 0, 0): x1 = 306.25: y1 = 268.75
  222. IF sp = 45 THEN CIRCLE (431.25, 268.75), 20, _RGB32(0, 0, 0): PAINT (431.25, 268.75), _RGB32(0, 0, 0): x1 = 431.25: y1 = 268.75
  223. IF sp = 47 THEN CIRCLE (556.25, 268.75), 20, _RGB32(0, 0, 0): PAINT (556.25, 268.75), _RGB32(0, 0, 0): x1 = 556.25: y1 = 268.75
  224. IF sp = 52 THEN CIRCLE (243.75, 331.25), 20, _RGB32(0, 0, 0): PAINT (243.75, 331.25), _RGB32(0, 0, 0): x1 = 243.75: y1 = 331.25
  225. IF sp = 54 THEN CIRCLE (368.75, 331.25), 20, _RGB32(0, 0, 0): PAINT (368.75, 331.25), _RGB32(0, 0, 0): x1 = 368.75: y1 = 331.25
  226. IF sp = 56 THEN CIRCLE (493.75, 331.25), 20, _RGB32(0, 0, 0): PAINT (493.75, 331.25), _RGB32(0, 0, 0): x1 = 493.75: y1 = 331.25
  227. IF sp = 58 THEN CIRCLE (618.75, 331.25), 20, _RGB32(0, 0, 0): PAINT (618.75, 331.25), _RGB32(0, 0, 0): x1 = 618.75: y1 = 331.25
  228. IF sp = 61 THEN CIRCLE (181.25, 393.75), 20, _RGB32(0, 0, 0): PAINT (181.25, 393.74), _RGB32(0, 0, 0): x1 = 181.25: y1 = 393.75
  229. IF sp = 63 THEN CIRCLE (306.25, 393.75), 20, _RGB32(0, 0, 0): PAINT (306.25, 393.75), _RGB32(0, 0, 0): x1 = 306.25: y1 = 393.75
  230. IF sp = 65 THEN CIRCLE (431.25, 393.75), 20, _RGB32(0, 0, 0): PAINT (431.25, 393.75), _RGB32(0, 0, 0): x1 = 431.25: y1 = 393.75
  231. IF sp = 67 THEN CIRCLE (556.25, 393.75), 20, _RGB32(0, 0, 0): PAINT (556.25, 393.75), _RGB32(0, 0, 0): x1 = 556.25: y1 = 393.75
  232. IF sp = 72 THEN CIRCLE (243.75, 456.25), 20, _RGB32(0, 0, 0): PAINT (243.75, 456.25), _RGB32(0, 0, 0): x1 = 243.75: y1 = 456.25
  233. IF sp = 74 THEN CIRCLE (368.75, 456.25), 20, _RGB32(0, 0, 0): PAINT (368.75, 456.25), _RGB32(0, 0, 0): x1 = 368.75: y1 = 456.25
  234. IF sp = 76 THEN CIRCLE (493.75, 456.25), 20, _RGB32(0, 0, 0): PAINT (493.75, 456.25), _RGB32(0, 0, 0): x1 = 493.75: y1 = 456.25
  235. IF sp = 78 THEN CIRCLE (618.75, 456.25), 20, _RGB32(0, 0, 0): PAINT (618.75, 456.25), _RGB32(0, 0, 0): x1 = 618.75: y1 = 456.25
  236. IF sp = 81 THEN CIRCLE (181.25, 518.75), 20, _RGB32(0, 0, 0): PAINT (181.25, 518.75), _RGB32(0, 0, 0): x1 = 181.25: y1 = 518.75
  237. IF sp = 83 THEN CIRCLE (306.25, 518.75), 20, _RGB32(0, 0, 0): PAINT (306.25, 518.75), _RGB32(0, 0, 0): x1 = 306.25: y1 = 518.75
  238. IF sp = 85 THEN CIRCLE (431.25, 518.75), 20, _RGB32(0, 0, 0): PAINT (431.25, 518.75), _RGB32(0, 0, 0): x1 = 431.25: y1 = 518.75
  239. IF sp = 87 THEN CIRCLE (556.25, 518.75), 20, _RGB32(0, 0, 0): PAINT (556.25, 518.75), _RGB32(0, 0, 0): x1 = 556.25: y1 = 518.75
  240.  
  241. 'Now draw the new checker.
  242. IF sp2 = 12 THEN CIRCLE (243.75, 81.25), 20, _RGB32(200, 50, 50): PAINT (243.75, 81.25), _RGB32(200, 50, 50): x2 = 243.75: y2 = 81.25
  243. IF sp2 = 14 THEN CIRCLE (368.75, 81.25), 20, _RGB32(200, 50, 50): PAINT (368.75, 81.25), _RGB32(200, 50, 50): x2 = 368.75: y2 = 81.25
  244. IF sp2 = 16 THEN CIRCLE (493.75, 81.25), 20, _RGB32(200, 50, 50): PAINT (493.75, 81.25), _RGB32(200, 50, 50): x2 = 493.75: y2 = 81.25
  245. IF sp2 = 18 THEN CIRCLE (618.75, 81.25), 20, _RGB32(200, 50, 50): PAINT (618.75, 81.25), _RGB32(200, 50, 50): x2 = 618.75: y2 = 81.25
  246. IF sp2 = 21 THEN CIRCLE (181.25, 143.75), 20, _RGB32(200, 50, 50): PAINT (181.25, 143.75), _RGB32(200, 50, 50): x2 = 181.25: y2 = 143.75
  247. IF sp2 = 23 THEN CIRCLE (306.25, 143.75), 20, _RGB32(200, 50, 50): PAINT (306.25, 143.75), _RGB32(200, 50, 50): x2 = 306.25: y2 = 143.75
  248. IF sp2 = 25 THEN CIRCLE (431.25, 143.75), 20, _RGB32(200, 50, 50): PAINT (431.25, 143.75), _RGB32(200, 50, 50): x2 = 431.25: y2 = 143.75
  249. IF sp2 = 27 THEN CIRCLE (556.25, 143.75), 20, _RGB32(200, 50, 50): PAINT (556.25, 143.75), _RGB32(200, 50, 50): x2 = 556.25: y2 = 143.75
  250. IF sp2 = 32 THEN CIRCLE (243.75, 206.25), 20, _RGB32(200, 50, 50): PAINT (243.75, 206.25), _RGB32(200, 50, 50): x2 = 243.75: y2 = 206.25
  251. IF sp2 = 34 THEN CIRCLE (368.75, 206.25), 20, _RGB32(200, 50, 50): PAINT (368.75, 206.25), _RGB32(200, 50, 50): x2 = 368.75: y2 = 206.25
  252. IF sp2 = 36 THEN CIRCLE (493.75, 206.25), 20, _RGB32(200, 50, 50): PAINT (493.75, 206.25), _RGB32(200, 50, 50): x2 = 493.75: y2 = 206.25
  253. IF sp2 = 38 THEN CIRCLE (618.75, 206.25), 20, _RGB32(200, 50, 50): PAINT (618.75, 206.25), _RGB32(200, 50, 50): x2 = 618.75: y2 = 206.25
  254. IF sp2 = 41 THEN CIRCLE (181.25, 268.75), 20, _RGB32(200, 50, 50): PAINT (181.25, 268.75), _RGB32(200, 50, 50): x2 = 181.25: y2 = 268.75
  255. IF sp2 = 43 THEN CIRCLE (306.25, 268.75), 20, _RGB32(200, 50, 50): PAINT (306.25, 268.75), _RGB32(200, 50, 50): x2 = 306.25: y2 = 268.75
  256. IF sp2 = 45 THEN CIRCLE (431.25, 268.75), 20, _RGB32(200, 50, 50): PAINT (431.25, 268.75), _RGB32(200, 50, 50): x2 = 431.25: y2 = 268.75
  257. IF sp2 = 47 THEN CIRCLE (556.25, 268.75), 20, _RGB32(200, 50, 50): PAINT (556.25, 268.75), _RGB32(200, 50, 50): x2 = 556.25: y2 = 268.75
  258. IF sp2 = 52 THEN CIRCLE (243.75, 331.25), 20, _RGB32(200, 50, 50): PAINT (243.75, 331.25), _RGB32(200, 50, 50): x2 = 243.75: y2 = 331.25
  259. IF sp2 = 54 THEN CIRCLE (368.75, 331.25), 20, _RGB32(200, 50, 50): PAINT (368.75, 331.25), _RGB32(200, 50, 50): x2 = 368.75: y2 = 331.25
  260. IF sp2 = 56 THEN CIRCLE (493.75, 331.25), 20, _RGB32(200, 50, 50): PAINT (493.75, 331.25), _RGB32(200, 50, 50): x2 = 493.75: y2 = 331.25
  261. IF sp2 = 58 THEN CIRCLE (618.75, 331.25), 20, _RGB32(200, 50, 50): PAINT (618.75, 331.25), _RGB32(200, 50, 50): x2 = 618.75: y2 = 331.25
  262. IF sp2 = 61 THEN CIRCLE (181.25, 393.75), 20, _RGB32(200, 50, 50): PAINT (181.25, 393.74), _RGB32(200, 50, 50): x2 = 181.25: y2 = 393.75
  263. IF sp2 = 63 THEN CIRCLE (306.25, 393.75), 20, _RGB32(200, 50, 50): PAINT (306.25, 393.75), _RGB32(200, 50, 50): x2 = 306.25: y2 = 393.75
  264. IF sp2 = 65 THEN CIRCLE (431.25, 393.75), 20, _RGB32(200, 50, 50): PAINT (431.25, 393.75), _RGB32(200, 50, 50): x2 = 431.25: y2 = 393.75
  265. IF sp2 = 67 THEN CIRCLE (556.25, 393.75), 20, _RGB32(200, 50, 50): PAINT (556.25, 393.75), _RGB32(200, 50, 50): x2 = 556.25: y2 = 393.75
  266. IF sp2 = 72 THEN CIRCLE (243.75, 456.25), 20, _RGB32(200, 50, 50): PAINT (243.75, 456.25), _RGB32(200, 50, 50): x2 = 243.75: y2 = 456.25
  267. IF sp2 = 74 THEN CIRCLE (368.75, 456.25), 20, _RGB32(200, 50, 50): PAINT (368.75, 456.25), _RGB32(200, 50, 50): x2 = 368.75: y2 = 456.25
  268. IF sp2 = 76 THEN CIRCLE (493.75, 456.25), 20, _RGB32(200, 50, 50): PAINT (493.75, 456.25), _RGB32(200, 50, 50): x2 = 493.75: y2 = 456.25
  269. IF sp2 = 78 THEN CIRCLE (618.75, 456.25), 20, _RGB32(200, 50, 50): PAINT (618.75, 456.25), _RGB32(200, 50, 50): x2 = 618.75: y2 = 456.25
  270. IF sp2 = 81 THEN CIRCLE (181.25, 518.75), 20, _RGB32(200, 50, 50): PAINT (181.25, 518.75), _RGB32(200, 50, 50): x2 = 181.25: y2 = 518.75
  271. IF sp2 = 83 THEN CIRCLE (306.25, 518.75), 20, _RGB32(200, 50, 50): PAINT (306.25, 518.75), _RGB32(200, 50, 50): x2 = 306.25: y2 = 518.75
  272. IF sp2 = 85 THEN CIRCLE (431.25, 518.75), 20, _RGB32(200, 50, 50): PAINT (431.25, 518.75), _RGB32(200, 50, 50): x2 = 431.25: y2 = 518.75
  273. IF sp2 = 87 THEN CIRCLE (556.25, 518.75), 20, _RGB32(200, 50, 50): PAINT (556.25, 518.75), _RGB32(200, 50, 50): x2 = 556.25: y2 = 518.75
  274.  
  275. 'Check for a jump.
  276. IF pv - pv2 = 2 OR pv2 - pv = 2 THEN
  277.     IF ph - ph2 = 2 OR ph2 - ph = 2 THEN
  278.         IF x1 > x2 THEN stp = -.25
  279.         IF x1 < x2 THEN stp = .25
  280.         IF y1 > y2 THEN stp2 = -.25
  281.         IF y1 < y2 THEN stp2 = .25
  282.         yy = y1
  283.         FOR xx = x1 TO x2 STEP stp
  284.             yy = yy + stp2
  285.             IF POINT(xx, yy) = _RGB32(50, 50, 50) THEN
  286.                 PAINT (xx, yy), _RGB32(0, 0, 0)
  287.                 GOTO nex:
  288.             END IF
  289.         NEXT xx
  290.     END IF
  291. nex:
  292.  
  293.  
  294. 'Check for a King.
  295. IF ph2 = 1 THEN
  296.     k1 = k1 + 1
  297.     rking(k1) = red2(ch)
  298.     GOSUB drawking:
  299. FOR cch = 1 TO 88
  300.     IF rking(cch) = red2(cch) AND rking(cch) <> 0 THEN GOSUB drawking:
  301. NEXT cch
  302.  
  303.  
  304. 'Check for a win.
  305. FOR wx = 0 TO 800
  306.     FOR wy = 0 TO 600
  307.         IF POINT(wx, wy) = _RGB32(50, 50, 50) THEN GOTO nex3:
  308.     NEXT wy
  309. NEXT wx
  310. COLOR _RGB32(255, 0, 0)
  311. LOCATE 3, 87: PRINT "Red Wins!"
  312.  
  313. nex3:
  314. LOCATE 5, 87: PRINT "           ": LOCATE 6, 87: PRINT "            "
  315. LOCATE 7, 87: PRINT "           ": LOCATE 8, 87: PRINT "            "
  316. LOCATE 10, 87: PRINT "           ": LOCATE 11, 87: PRINT "            "
  317. LOCATE 12, 87: PRINT "           ": LOCATE 13, 87: PRINT "            "
  318. LOCATE 15, 87: PRINT "            "
  319. GOTO two:
  320.  
  321. '-----------------------------------------------------------------------------------------------------------
  322. 'Player Two
  323.  
  324. move2:
  325. COLOR _RGB32(128, 249, 127)
  326. LOCATE 10, 5: PRINT "Horizon": LOCATE 11, 5: INPUT ph4
  327. IF ph4 > 8 OR ph4 < 1 THEN GOTO two:
  328. IF ph4 <> INT(ph4) THEN GOTO two:
  329. COLOR _RGB32(127, 255, 255)
  330. LOCATE 12, 5: PRINT "Vertical": LOCATE 13, 5: INPUT pv4
  331.  
  332. IF pv4 > 8 OR pv4 < 1 THEN GOTO two:
  333. IF pv4 <> INT(pv4) THEN GOTO two:
  334. ph4$ = STR$(ph4)
  335. pv4$ = STR$(pv4)
  336. sp4$ = ph4$ + pv4$
  337. sp4 = VAL(sp4$)
  338. IF sp3 = sp4 THEN GOTO two:
  339. IF pv3 = pv4 OR ph3 = ph4 THEN
  340.     COLOR _RGB32(255, 0, 0)
  341.     LOCATE 15, 5
  342.     PRINT "Illegal Move"
  343.     GOTO one:
  344.  
  345. 'Check for red squares.
  346. IF sp4 = 11 OR sp4 = 13 OR sp4 = 15 OR sp4 = 17 OR sp4 = 22 OR sp4 = 24 OR sp4 = 26 OR sp4 = 28 THEN
  347.     COLOR _RGB32(255, 0, 0)
  348.     LOCATE 15, 5
  349.     PRINT "Illegal Move"
  350.     GOTO two:
  351. IF sp4 = 31 OR sp4 = 33 OR sp4 = 35 OR sp4 = 37 OR sp4 = 42 OR sp4 = 44 OR sp4 = 46 OR sp4 = 48 THEN
  352.     COLOR _RGB32(255, 0, 0)
  353.     LOCATE 15, 5
  354.     PRINT "Illegal Move"
  355.     GOTO two:
  356. IF sp4 = 51 OR sp4 = 53 OR sp4 = 55 OR sp4 = 57 OR sp4 = 62 OR sp4 = 64 OR sp4 = 66 OR sp4 = 68 THEN
  357.     COLOR _RGB32(255, 0, 0)
  358.     LOCATE 15, 5
  359.     PRINT "Illegal Move"
  360.     GOTO two:
  361. IF sp4 = 71 OR sp4 = 73 OR sp4 = 75 OR sp4 = 77 OR sp4 = 82 OR sp4 = 84 OR sp4 = 86 OR sp4 = 88 THEN
  362.     COLOR _RGB32(255, 0, 0)
  363.     LOCATE 15, 5
  364.     PRINT "Illegal Move"
  365.     GOTO two:
  366.  
  367. black2(ch2) = sp4
  368.  
  369. 'Draw player two checker in the new square.
  370. 'First erase the old checker.
  371. IF sp3 = 12 THEN CIRCLE (243.75, 81.25), 20, _RGB32(0, 0, 0): PAINT (243.75, 81.25), _RGB32(0, 0, 0): x1 = 243.75: y1 = 81.25
  372. IF sp3 = 14 THEN CIRCLE (368.75, 81.25), 20, _RGB32(0, 0, 0): PAINT (368.75, 81.25), _RGB32(0, 0, 0): x1 = 368.75: y1 = 81.25
  373. IF sp3 = 16 THEN CIRCLE (493.75, 81.25), 20, _RGB32(0, 0, 0): PAINT (493.75, 81.25), _RGB32(0, 0, 0): x1 = 493.75: y1 = 81.25
  374. IF sp3 = 18 THEN CIRCLE (618.75, 81.25), 20, _RGB32(0, 0, 0): PAINT (618.75, 81.25), _RGB32(0, 0, 0): x1 = 618.75: y1 = 81.25
  375. IF sp3 = 21 THEN CIRCLE (181.25, 143.75), 20, _RGB32(0, 0, 0): PAINT (181.25, 143.75), _RGB32(0, 0, 0): x1 = 181.25: y1 = 143.75
  376. IF sp3 = 23 THEN CIRCLE (306.25, 143.75), 20, _RGB32(0, 0, 0): PAINT (306.25, 143.75), _RGB32(0, 0, 0): x1 = 306.25: y1 = 143.75
  377. IF sp3 = 25 THEN CIRCLE (431.25, 143.75), 20, _RGB32(0, 0, 0): PAINT (431.25, 143.75), _RGB32(0, 0, 0): x1 = 431.25: y1 = 143.75
  378. IF sp3 = 27 THEN CIRCLE (556.25, 143.75), 20, _RGB32(0, 0, 0): PAINT (556.25, 143.75), _RGB32(0, 0, 0): x1 = 556.25: y1 = 143.75
  379. IF sp3 = 32 THEN CIRCLE (243.75, 206.25), 20, _RGB32(0, 0, 0): PAINT (243.75, 206.25), _RGB32(0, 0, 0): x1 = 243.75: y1 = 206.25
  380. IF sp3 = 34 THEN CIRCLE (368.75, 206.25), 20, _RGB32(0, 0, 0): PAINT (368.75, 206.25), _RGB32(0, 0, 0): x1 = 368.75: y1 = 206.25
  381. IF sp3 = 36 THEN CIRCLE (493.75, 206.25), 20, _RGB32(0, 0, 0): PAINT (493.75, 206.25), _RGB32(0, 0, 0): x1 = 493.75: y1 = 206.25
  382. IF sp3 = 38 THEN CIRCLE (618.75, 206.25), 20, _RGB32(0, 0, 0): PAINT (618.75, 206.25), _RGB32(0, 0, 0): x1 = 618.75: y1 = 206.25
  383. IF sp3 = 41 THEN CIRCLE (181.25, 268.75), 20, _RGB32(0, 0, 0): PAINT (181.25, 268.75), _RGB32(0, 0, 0): x1 = 181.25: y1 = 268.75
  384. IF sp3 = 43 THEN CIRCLE (306.25, 268.75), 20, _RGB32(0, 0, 0): PAINT (306.25, 268.75), _RGB32(0, 0, 0): x1 = 306.25: y1 = 268.75
  385. IF sp3 = 45 THEN CIRCLE (431.25, 268.75), 20, _RGB32(0, 0, 0): PAINT (431.25, 268.75), _RGB32(0, 0, 0): x1 = 431.25: y1 = 268.75
  386. IF sp3 = 47 THEN CIRCLE (556.25, 268.75), 20, _RGB32(0, 0, 0): PAINT (556.25, 268.75), _RGB32(0, 0, 0): x1 = 556.25: y1 = 268.75
  387. IF sp3 = 52 THEN CIRCLE (243.75, 331.25), 20, _RGB32(0, 0, 0): PAINT (243.75, 331.25), _RGB32(0, 0, 0): x1 = 243.75: y1 = 331.25
  388. IF sp3 = 54 THEN CIRCLE (368.75, 331.25), 20, _RGB32(0, 0, 0): PAINT (368.75, 331.25), _RGB32(0, 0, 0): x1 = 368.75: y1 = 331.25
  389. IF sp3 = 56 THEN CIRCLE (493.75, 331.25), 20, _RGB32(0, 0, 0): PAINT (493.75, 331.25), _RGB32(0, 0, 0): x1 = 493.75: y1 = 331.25
  390. IF sp3 = 58 THEN CIRCLE (618.75, 331.25), 20, _RGB32(0, 0, 0): PAINT (618.75, 331.25), _RGB32(0, 0, 0): x1 = 618.75: y1 = 331.25
  391. IF sp3 = 61 THEN CIRCLE (181.25, 393.75), 20, _RGB32(0, 0, 0): PAINT (181.25, 393.74), _RGB32(0, 0, 0): x1 = 181.25: y1 = 393.75
  392. IF sp3 = 63 THEN CIRCLE (306.25, 393.75), 20, _RGB32(0, 0, 0): PAINT (306.25, 393.75), _RGB32(0, 0, 0): x1 = 306.25: y1 = 393.75
  393. IF sp3 = 65 THEN CIRCLE (431.25, 393.75), 20, _RGB32(0, 0, 0): PAINT (431.25, 393.75), _RGB32(0, 0, 0): x1 = 431.25: y1 = 393.75
  394. IF sp3 = 67 THEN CIRCLE (556.25, 393.75), 20, _RGB32(0, 0, 0): PAINT (556.25, 393.75), _RGB32(0, 0, 0): x1 = 556.25: y1 = 393.75
  395. IF sp3 = 72 THEN CIRCLE (243.75, 456.25), 20, _RGB32(0, 0, 0): PAINT (243.75, 456.25), _RGB32(0, 0, 0): x1 = 243.75: y1 = 456.25
  396. IF sp3 = 74 THEN CIRCLE (368.75, 456.25), 20, _RGB32(0, 0, 0): PAINT (368.75, 456.25), _RGB32(0, 0, 0): x1 = 368.75: y1 = 456.25
  397. IF sp3 = 76 THEN CIRCLE (493.75, 456.25), 20, _RGB32(0, 0, 0): PAINT (493.75, 456.25), _RGB32(0, 0, 0): x1 = 493.75: y1 = 456.25
  398. IF sp3 = 78 THEN CIRCLE (618.75, 456.25), 20, _RGB32(0, 0, 0): PAINT (618.75, 456.25), _RGB32(0, 0, 0): x1 = 618.75: y1 = 456.25
  399. IF sp3 = 81 THEN CIRCLE (181.25, 518.75), 20, _RGB32(0, 0, 0): PAINT (181.25, 518.75), _RGB32(0, 0, 0): x1 = 181.25: y1 = 518.75
  400. IF sp3 = 83 THEN CIRCLE (306.25, 518.75), 20, _RGB32(0, 0, 0): PAINT (306.25, 518.75), _RGB32(0, 0, 0): x1 = 306.25: y1 = 518.75
  401. IF sp3 = 85 THEN CIRCLE (431.25, 518.75), 20, _RGB32(0, 0, 0): PAINT (431.25, 518.75), _RGB32(0, 0, 0): x1 = 431.25: y1 = 518.75
  402. IF sp3 = 87 THEN CIRCLE (556.25, 518.75), 20, _RGB32(0, 0, 0): PAINT (556.25, 518.75), _RGB32(0, 0, 0): x1 = 556.25: y1 = 518.75
  403.  
  404. 'Now draw the new checker.
  405. IF sp4 = 12 THEN CIRCLE (243.75, 81.25), 20, _RGB32(50, 50, 50): PAINT (243.75, 81.25), _RGB32(50, 50, 50): x2 = 243.75: y2 = 81.25
  406. IF sp4 = 14 THEN CIRCLE (368.75, 81.25), 20, _RGB32(50, 50, 50): PAINT (368.75, 81.25), _RGB32(50, 50, 50): x2 = 368.75: y2 = 81.25
  407. IF sp4 = 16 THEN CIRCLE (493.75, 81.25), 20, _RGB32(50, 50, 50): PAINT (493.75, 81.25), _RGB32(50, 50, 50): x2 = 493.75: y2 = 81.25
  408. IF sp4 = 18 THEN CIRCLE (618.75, 81.25), 20, _RGB32(50, 50, 50): PAINT (618.75, 81.25), _RGB32(50, 50, 50): x2 = 618.75: y2 = 81.25
  409. IF sp4 = 21 THEN CIRCLE (181.25, 143.75), 20, _RGB32(50, 50, 50): PAINT (181.25, 143.75), _RGB32(50, 50, 50): x2 = 181.25: y2 = 143.75
  410. IF sp4 = 23 THEN CIRCLE (306.25, 143.75), 20, _RGB32(50, 50, 50): PAINT (306.25, 143.75), _RGB32(50, 50, 50): x2 = 306.25: y2 = 143.75
  411. IF sp4 = 25 THEN CIRCLE (431.25, 143.75), 20, _RGB32(50, 50, 50): PAINT (431.25, 143.75), _RGB32(50, 50, 50): x2 = 431.25: y2 = 143.75
  412. IF sp4 = 27 THEN CIRCLE (556.25, 143.75), 20, _RGB32(50, 50, 50): PAINT (556.25, 143.75), _RGB32(50, 50, 50): x2 = 556.25: y2 = 143.75
  413. IF sp4 = 32 THEN CIRCLE (243.75, 206.25), 20, _RGB32(50, 50, 50): PAINT (243.75, 206.25), _RGB32(50, 50, 50): x2 = 243.75: y2 = 206.25
  414. IF sp4 = 34 THEN CIRCLE (368.75, 206.25), 20, _RGB32(50, 50, 50): PAINT (368.75, 206.25), _RGB32(50, 50, 50): x2 = 368.75: y2 = 206.25
  415. IF sp4 = 36 THEN CIRCLE (493.75, 206.25), 20, _RGB32(50, 50, 50): PAINT (493.75, 206.25), _RGB32(50, 50, 50): x2 = 493.75: y2 = 206.25
  416. IF sp4 = 38 THEN CIRCLE (618.75, 206.25), 20, _RGB32(50, 50, 50): PAINT (618.75, 206.25), _RGB32(50, 50, 50): x2 = 618.75: y2 = 206.25
  417. IF sp4 = 41 THEN CIRCLE (181.25, 268.75), 20, _RGB32(50, 50, 50): PAINT (181.25, 268.75), _RGB32(50, 50, 50): x2 = 181.25: y2 = 268.75
  418. IF sp4 = 43 THEN CIRCLE (306.25, 268.75), 20, _RGB32(50, 50, 50): PAINT (306.25, 268.75), _RGB32(50, 50, 50): x2 = 306.25: y2 = 268.75
  419. IF sp4 = 45 THEN CIRCLE (431.25, 268.75), 20, _RGB32(50, 50, 50): PAINT (431.25, 268.75), _RGB32(50, 50, 50): x2 = 431.25: y2 = 268.75
  420. IF sp4 = 47 THEN CIRCLE (556.25, 268.75), 20, _RGB32(50, 50, 50): PAINT (556.25, 268.75), _RGB32(50, 50, 50): x2 = 556.25: y2 = 268.75
  421. IF sp4 = 52 THEN CIRCLE (243.75, 331.25), 20, _RGB32(50, 50, 50): PAINT (243.75, 331.25), _RGB32(50, 50, 50): x2 = 243.75: y2 = 331.25
  422. IF sp4 = 54 THEN CIRCLE (368.75, 331.25), 20, _RGB32(50, 50, 50): PAINT (368.75, 331.25), _RGB32(50, 50, 50): x2 = 368.75: y2 = 331.25
  423. IF sp4 = 56 THEN CIRCLE (493.75, 331.25), 20, _RGB32(50, 50, 50): PAINT (493.75, 331.25), _RGB32(50, 50, 50): x2 = 493.75: y2 = 331.25
  424. IF sp4 = 58 THEN CIRCLE (618.75, 331.25), 20, _RGB32(50, 50, 50): PAINT (618.75, 331.25), _RGB32(50, 50, 50): x2 = 618.75: y2 = 331.25
  425. IF sp4 = 61 THEN CIRCLE (181.25, 393.75), 20, _RGB32(50, 50, 50): PAINT (181.25, 393.74), _RGB32(50, 50, 50): x2 = 181.25: y2 = 393.75
  426. IF sp4 = 63 THEN CIRCLE (306.25, 393.75), 20, _RGB32(50, 50, 50): PAINT (306.25, 393.75), _RGB32(50, 50, 50): x2 = 306.25: y2 = 393.75
  427. IF sp4 = 65 THEN CIRCLE (431.25, 393.75), 20, _RGB32(50, 50, 50): PAINT (431.25, 393.75), _RGB32(50, 50, 50): x2 = 431.25: y2 = 393.75
  428. IF sp4 = 67 THEN CIRCLE (556.25, 393.75), 20, _RGB32(50, 50, 50): PAINT (556.25, 393.75), _RGB32(50, 50, 50): x2 = 556.25: y2 = 393.75
  429. IF sp4 = 72 THEN CIRCLE (243.75, 456.25), 20, _RGB32(50, 50, 50): PAINT (243.75, 456.25), _RGB32(50, 50, 50): x2 = 243.75: y2 = 456.25
  430. IF sp4 = 74 THEN CIRCLE (368.75, 456.25), 20, _RGB32(50, 50, 50): PAINT (368.75, 456.25), _RGB32(50, 50, 50): x2 = 368.75: y2 = 456.25
  431. IF sp4 = 76 THEN CIRCLE (493.75, 456.25), 20, _RGB32(50, 50, 50): PAINT (493.75, 456.25), _RGB32(50, 50, 50): x2 = 493.75: y2 = 456.25
  432. IF sp4 = 78 THEN CIRCLE (618.75, 456.25), 20, _RGB32(50, 50, 50): PAINT (618.75, 456.25), _RGB32(50, 50, 50): x2 = 618.75: y2 = 456.25
  433. IF sp4 = 81 THEN CIRCLE (181.25, 518.75), 20, _RGB32(50, 50, 50): PAINT (181.25, 518.75), _RGB32(50, 50, 50): x2 = 181.25: y2 = 518.75
  434. IF sp4 = 83 THEN CIRCLE (306.25, 518.75), 20, _RGB32(50, 50, 50): PAINT (306.25, 518.75), _RGB32(50, 50, 50): x2 = 306.25: y2 = 518.75
  435. IF sp4 = 85 THEN CIRCLE (431.25, 518.75), 20, _RGB32(50, 50, 50): PAINT (431.25, 518.75), _RGB32(50, 50, 50): x2 = 431.25: y2 = 518.75
  436. IF sp4 = 87 THEN CIRCLE (556.25, 518.75), 20, _RGB32(50, 50, 50): PAINT (556.25, 518.75), _RGB32(50, 50, 50): x2 = 556.25: y2 = 518.75
  437.  
  438. 'Check for a jump.
  439. IF pv3 - pv4 = 2 OR pv4 - pv3 = 2 THEN
  440.     IF ph3 - ph4 = 2 OR ph4 - ph3 = 2 THEN
  441.         IF x1 > x2 THEN stp = -.25
  442.         IF x1 < x2 THEN stp = .25
  443.         IF y1 > y2 THEN stp2 = -.25
  444.         IF y1 < y2 THEN stp2 = .25
  445.         yy = y1
  446.         FOR xx = x1 TO x2 STEP stp
  447.             yy = yy + stp2
  448.             IF POINT(xx, yy) = _RGB32(200, 50, 50) THEN
  449.                 PAINT (xx, yy), _RGB32(0, 0, 0)
  450.                 GOTO nex2:
  451.             END IF
  452.         NEXT xx
  453.     END IF
  454. nex2:
  455.  
  456. 'Check for a King.
  457. IF ph4 = 8 THEN
  458.     k2 = k2 + 1
  459.     bking(k2) = black2(ch2)
  460.     GOSUB drawking:
  461. FOR cch = 1 TO 88
  462.     IF bking(cch) = black2(cch) AND bking(cch) <> 0 THEN GOSUB drawking:
  463. NEXT cch
  464.  
  465. 'Check for a win.
  466. FOR wx = 0 TO 800
  467.     FOR wy = 0 TO 600
  468.         IF POINT(wx, wy) = _RGB32(200, 50, 50) THEN GOTO nex4:
  469.     NEXT wy
  470. NEXT wx
  471. COLOR _RGB32(255, 0, 0)
  472. LOCATE 3, 87: PRINT "Black Wins!"
  473.  
  474. nex4:
  475. LOCATE 5, 5: PRINT "           ": LOCATE 6, 5: PRINT "            "
  476. LOCATE 7, 5: PRINT "           ": LOCATE 8, 5: PRINT "            "
  477. LOCATE 10, 5: PRINT "           ": LOCATE 11, 5: PRINT "            "
  478. LOCATE 12, 5: PRINT "           ": LOCATE 13, 5: PRINT "            "
  479. LOCATE 15, 5: PRINT "            "
  480.  
  481. 'Go back to Player One
  482. GOTO one:
  483.  
  484. 'Draw the king symbol on the piece.
  485. drawking:
  486. LINE (x2 - 10, y2 + 10)-(x2 + 10, y2 + 10), _RGB32(255, 255, 255)
  487. LINE (x2 - 10, y2 + 7)-(x2 + 10, y2 + 7), _RGB32(255, 255, 255)
  488. LINE (x2 - 10, y2 + 7)-(x2 - 15, y2 - 2), _RGB32(255, 255, 255)
  489. CIRCLE (x2 - 15, y2 - 5), 3, _RGB32(255, 255, 255)
  490. LINE (x2 - 15, y2 - 2)-(x2 - 5, y2), _RGB32(255, 255, 255)
  491. LINE (x2 - 5, y2)-(x2, y2 - 4), _RGB32(255, 255, 255)
  492. CIRCLE (x2, y2 - 7), 3, _RGB32(255, 255, 255)
  493. LINE (x2 + 10, y2 + 7)-(x2 + 15, y2 - 2), _RGB32(255, 255, 255)
  494. CIRCLE (x2 + 15, y2 - 5), 3, _RGB32(255, 255, 255)
  495. LINE (x2 + 15, y2 - 2)-(x2 + 5, y2), _RGB32(255, 255, 255)
  496. LINE (x2 + 5, y2)-(x2, y2 - 4), _RGB32(255, 255, 255)
  497.  

Title: Re: A 90% complete chess engine
Post by: bplus on February 02, 2020, 04:50:27 pm
Hi Ken,

Ah so that's what you've been up to! I wish you started a new thread, so I could join in. This one is already all over the place with chess.

I look forward to checking it out, thanks.
Title: Re: A 90% complete chess engine
Post by: SierraKen on February 02, 2020, 05:40:47 pm
I'll make a new thread for it.
Title: Re: A 90% complete chess engine
Post by: Richard Frost on February 26, 2020, 09:47:41 pm
Vastly improved, but still far to go.  No need to report bugs, as I'm well aware of them.

The plasma effect from B+, toned down, looks like marble to me. 

Cursor keys to move, or click piece and square to be moved to.  I really like the "special"
cursor that pops up if an illegal move is attempted.  Sound files optional, but I include
them anyway.  They're just Windows files, some renamed.  The JPG is required, as are
the PNG files from the previous post.

Code: QB64: [Select]
  1.  
  2. _TITLE "Chess"
  3. DEFINT A-Z
  4.  
  5. CONST true = -1, false = 0, Rook = 1, Knight = 2, Bishop = 3, Queen = 4, King = 5, Pawn = 6
  6. COMMON SHARED WorB, Move, Score, Index, opening, invert, i$, m$, lm$, msg$, abort, MaxRow, xq, yq, xc, yc, xm, ym, castle$, OtherK$
  7. COMMON SHARED mkr, mkc, okr, okc, k$, MasterLevel, MasterLevel1, SaveWorB, GameFile$, check, incheck, debug, DebugR, DebugC, Start1!, Start2!
  8. COMMON SHARED MaxElapse!, human, humanc, OnAuto, graphics, rflag, tlimit, boardwhite&, boardblack&, black&, red&, green&, blue&, white&, gray&
  9. COMMON SHARED Enter$, Esc$, lf$, crlf$, debug$, pinit, takebackflag, tbc, waitflag, pause, cursoron!, quitflag, smode, vflag, MakeNoise
  10. COMMON SHARED bri, hold!, dtime!, mtime!, altblack, epfc, epfr, eptc, eptr, eprc, eprr, best, best$, ep$, rick, lcount&, alpha$, ocount&
  11.  
  12. DIM SHARED l, p, b, q1, q2
  13. l = 10: p = 6: b = 8: q1 = 300: q2 = 500
  14. DIM SHARED b(b, b), t(b, b, l), o(b, b), tb(b, b, 10), castle$(l), Moves(l), Move$(l, q1), Score(l, q1)
  15. DIM SHARED TieTo(l), Index(l, q1), prot(l), prot$(l, q1), x(p, q2), y(p, q2), c(12, q2), MoveLog$(q2)
  16. DIM SHARED cp&(32), etime!(3), myr(32), myg(32), myb(32), icon&(10), emin, useidiot, main&, alfred!
  17. DIM SHARED mcount&(10), du(p, 7), dd(p, 7), dl(p, 7), dr(p, 7), value(p), alphal$(8)
  18. DIM SHARED showthink, history, showlegalf, showprotf
  19.  
  20. DIM SHARED abuff(30000)
  21. 'DIM SHARED debug$(2)
  22.  
  23. DIM SHARED s1(b, b), s2(b, b), s3(b, b), s4(b, b), s5(b, b), s9(b, b) '                  saving board state for recursion
  24. m(0) = _MEM(b(0, 0))
  25. m(1) = _MEM(s1(0, 0))
  26. m(2) = _MEM(s2(0, 0))
  27. m(3) = _MEM(s3(0, 0))
  28. m(4) = _MEM(s4(0, 0))
  29. m(5) = _MEM(s5(0, 0))
  30. m(9) = _MEM(s9(0, 0))
  31.  
  32. rick = _FILEEXISTS("rick.")
  33. IF INSTR(COMMAND$ + " ", "rick") THEN debug = true
  34.  
  35. begin:
  36. Init
  37. OPEN "chess.txt" FOR OUTPUT AS #2
  38.     _ICON icon&(1) '                                                 chess.png
  39.     SaveWorB = WorB
  40.  
  41.     mking = 5: oking = 11
  42.     IF humanc = 0 THEN SWAP mking, oking
  43.     FOR r = 1 TO 8
  44.         FOR c = 1 TO 8
  45.             IF b(c, r) = mking THEN mkr = r: mkc = c
  46.             IF b(c, r) = oking THEN okr = r: okc = c
  47.         NEXT c
  48.     NEXT r
  49.     ks$ = alphal$(mkc) + CHR$(48 + mkr)
  50.  
  51.     redo:
  52.     SaveForTakeBack
  53.     Reset_To_Zero
  54.     IF Moves(0) = 0 THEN msg$ = "Stalemate": GOTO yoyo
  55.     Start1! = TIMER: Start2! = Start1!
  56.     DebugR = 99
  57.  
  58.     IF human AND (humanc = WorB) OR (human = 2) THEN '               2 is two humans
  59.         IF human = 2 THEN invert = -(WorB = 0)
  60.         DO
  61.             pinit = 0 '                                              nudge for the graphics, vary it a little
  62.             HumanMove '                                              get a move
  63.             IF LEN(msg$) THEN GOTO yoyo
  64.             IF takebackflag THEN
  65.                 TakeBack '                                           restores board & castling status
  66.                 PlotBoard
  67.                 takebackflag = 0
  68.                 GOTO redo
  69.             END IF
  70.             sm$ = m$
  71.             _MEMCOPY m(0), m(0).OFFSET, m(0).SIZE TO m(9), m(9).OFFSET '         save board
  72.             MoveIt m$, false
  73.             WorB = WorB XOR 1
  74.             CheckBoard 1
  75.             WorB = WorB XOR 1
  76.             m$ = sm$
  77.             _MEMCOPY m(9), m(9).OFFSET, m(9).SIZE TO m(0), m(0).OFFSET '     restore board
  78.             IF Score <> 777 THEN
  79.                 FOR i = 1 TO Moves(0) '                              check against legal list
  80.                     IF m$ = Move$(0, i) THEN EXIT DO '               move found, skip more checking
  81.                 NEXT i
  82.             END IF
  83.             alfred! = TIMER + 5
  84.             IF MakeNoise THEN PlaySound "bad"
  85.         LOOP
  86.     ELSE
  87.         abort = false
  88.         DebugR = 99
  89.         rflag = true '                                               flag in recursion to stop displaying board
  90.         best = -99999
  91.         Center 0, "", true
  92.         MasterLevel = 2 '                                            fast check in case slow aborted
  93.         Recurse 1 '                                                  try all moves & responses
  94.         TakeBest 0, true '
  95.         ShowBest
  96.         IF (Score < -700) OR (Score > 500) THEN
  97.             rflag = 0
  98.             IF Moves(0) THEN msg$ = "Checkmate!" ELSE msg$ = "Stalemate!"
  99.             msg$ = msg$ + STR$(Score)
  100.             GOTO yoyo
  101.         END IF
  102.         MasterLevel = MasterLevel1 '                                 slow check
  103.         FOR i = 1 TO MasterLevel: Moves(i) = 0: NEXT
  104.         Recurse 1 '                                                  try all moves & responses
  105.         IF MakeNoise THEN PlaySound "ding"
  106.         TakeBest 0, true '
  107.         ShowBest
  108.         rflag = false
  109.         Center 0, "", true
  110.         IF abort THEN _MEMCOPY m(1), m(1).OFFSET, m(1).SIZE TO m(0), m(0).OFFSET '         restore board
  111.         IF msg$ = "abort" THEN msg$ = ""
  112.         IF LEN(msg$) THEN WorBs = WorB + 1: GOTO yoyo
  113.     END IF
  114.  
  115.     IF LEN(msg$) THEN GOTO yoyo
  116.  
  117.     WorB = SaveWorB
  118.  
  119.     sm$ = m$: m2$ = m$ '                                             save move for display in case modified for castling
  120.     IF m$ = "O-O" THEN '                                             castle kingside
  121.         IF WorB THEN
  122.             m$ = "e1g1": m2$ = "h1f1"
  123.         ELSE
  124.             m$ = "e8g8": m2$ = "h8f8"
  125.         END IF
  126.     END IF
  127.     IF m$ = "O-O-O" THEN '                                           castle queenside
  128.         IF WorB THEN
  129.             m$ = "e1c1": m2$ = "a1c1"
  130.         ELSE
  131.             m$ = "e8c8": m2$ = "a8d8"
  132.         END IF
  133.     END IF
  134.  
  135.     IF human <> 1 THEN GOTO doit '                                   people playing, or computer playing itself
  136.  
  137.     waitflag = 1
  138.     _ICON icon&(2) '                                                 clockx or clockx2
  139.  
  140.     fr = VAL(MID$(m$, 2, 1)) '                                       from row (or rank)
  141.     IF invert THEN fr = 9 - fr '                                     invert means black at bottom
  142.     fc = INSTR(alpha$, LEFT$(m$, 1)) '                               from column
  143.  
  144.     IF invert THEN fc = 9 - fc
  145.  
  146.     tr = VAL(MID$(m$, 4, 1)) '                                       row or rank
  147.     IF invert THEN tr = 9 - tr '                                     black at bottom
  148.     tc = INSTR(alpha$, MID$(m$, 3, 1)) '                             column
  149.     IF invert THEN tc = 9 - tc
  150.  
  151.     DO: _LIMIT 100
  152.         'IF (itime! = 0) OR (TIMER > itime!) THEN
  153.         '    iname = iname XOR 1
  154.         '    _ICON icon&(iname + 2) '                                clockx or clockx2
  155.         '    itime! = TIMER + .5
  156.         'END IF
  157.         KeyScan 1, 1 '                                               plotscreen, _display
  158.         Cursor fr, fc, 0
  159.         Cursor tr, tc, 0
  160.         IF WorB = humanc THEN EXIT DO
  161.     LOOP UNTIL (i$ = Enter$) OR (human = 0) OR LEN(msg$)
  162.  
  163.     waitflag = 0
  164.  
  165.     doit:
  166.     m$ = sm$
  167.     lm$ = m$
  168.     MoveIt m$, true
  169.     AddMove
  170.     PlotScreen true
  171.     _DISPLAY
  172.  
  173.     check = false
  174.     CheckBoard 0
  175.     IF Score = 777 THEN check = true: TempMess "Check!", 2
  176.  
  177.     'check = 0: incheck = 0
  178.  
  179.     'check = false: z = Level XOR 1
  180.     'k1$ = MID$(alpha$, mkc, 1) + CHR$(48 + mkr) '                   location of King
  181.     'k2$ = MID$(alpha$, okc, 1) + CHR$(48 + okr) '                   location of King
  182.     'ic = 0
  183.     'FOR i = 1 TO Moves(0) '                                         can any opponent piece move there?
  184.     '    s$ = RIGHT$(Move$(z, 0), 2)
  185.     '    IF k1$ = s$ THEN ic = 1 '                                   in check
  186.     '    IF k2$ = s$ THEN ic = 2 '                                   in check
  187.     'NEXT i
  188.     'IF ic THEN
  189.     '    check = true
  190.     '    ic$ = CHR$(48 + ic) + " Check!"
  191.     '    TempMess ic$
  192.     'END IF
  193.  
  194.     WorB = SaveWorB XOR 1 '                                          toggle white/black
  195. LOOP UNTIL Move = 500
  196.  
  197. IF Move = 500 THEN msg$ = "Over 500 moves...."
  198. PRINT #1, ""
  199. PRINT #1, msg$
  200.  
  201. yoyo:
  202. Playagain msg$
  203. msg$ = ""
  204. IF i$ = "n" THEN GOTO begin '                                        n for new game
  205. IF WorBs THEN
  206.     WorB = WorBs - 1: WorBs = 0
  207.     WorB = WorB XOR 1
  208. PlotScreen true
  209. GOTO redo
  210.  
  211. o1:
  212. DATA e2e4,e7e5,g1f3,b8c6,f1b5,a7a6,b5a4,b7b5,a4b3,g8f6,b1c3,f8e7,f3g5,h7h6
  213. 'DATA g5f7,O-O
  214. 'DATA f7d8,g8h7
  215.  
  216. Setup:
  217. DATA 1,2,3,4,5,3,2,1
  218. DATA 6,6,6,6,6,6,6,6
  219. DATA 0,0,0,0,0,0,0,0
  220. DATA 0,0,0,0,0,0,0,0
  221. DATA 0,0,0,0,0,0,0,0
  222. DATA 0,0,0,0,0,0,0,0
  223. DATA 12,12,12,12,12,12,12,12
  224. DATA 7,8,9,10,11,9,8,7
  225.  
  226. test:
  227. DATA 0,0,0,0,0,0,0,0
  228. DATA 0,0,0,0,0,0,0,0
  229. DATA 0,0,0,0,0,0,0,0
  230. DATA 0,11,0,0,0,0,0,0
  231. DATA 0,7,0,12,0,0,0,0
  232. DATA 0,0,0,0,0,0,0,0
  233. DATA 9,0,0,0,6,0,0,0
  234. DATA 5,9,0,0,0,0,0,0
  235.  
  236. Legal:
  237. '      udlr,udlr,udlr,udlr,udlr,udlr,udlr,udlr
  238. DATA R,7000,0700,0070,0007,0000,0000,0000,0000
  239. DATA N,2010,2001,0210,0201,1020,1002,0120,0102
  240. DATA B,7070,7007,0770,0707,0000,0000,0000,0000
  241. DATA Q,7000,0700,0070,0007,7070,7007,0770,0707
  242. DATA K,1000,0100,0010,0001,1010,1001,0110,0101
  243. DATA P,1000,1001,1010,0000,0000,0000,0000,0000
  244.  
  245. hg:
  246. '                   1         2         3         4         5
  247. '          12345678901234567890123456789012345678901234567890
  248. DATA "01","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  249. DATA "02","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  250. DATA "03","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  251. DATA "04","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  252. DATA "05","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  253. DATA "06","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  254. DATA "07","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  255. DATA "08","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  256. DATA "09","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  257. DATA "10","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  258. DATA "11","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  259. DATA "12","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  260. DATA "13","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  261. DATA "14","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  262. DATA "15","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  263. DATA "16","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  264. DATA "17","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  265. DATA "18","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  266. DATA "19","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  267. DATA "20","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  268. DATA "21","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  269. DATA "22","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  270. DATA "23","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  271. DATA "24","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  272. DATA "25","               XXXXXXXXXXXXXXXXXXXX               "
  273. DATA "26","                XXXXXXXXXXXXXXXXXX                "
  274. DATA "27","                 XXXXXXXXXXXXXXXX                 "
  275. DATA "28","                  XXXXXXXXXXXXXX                  "
  276. DATA "29","                   XXXXXXXXXXXX                   "
  277. DATA "30","                    XXXXXXXXXX                    "
  278. DATA "31","                     XXXXXXXX                     "
  279. DATA "32","                      XXXXXX                      "
  280.  
  281. DATA "33","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  282. DATA "34","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  283. DATA "35","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  284. DATA "36","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  285. DATA "37","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  286. DATA "38","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  287. DATA "39","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  288. DATA "40","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  289. DATA "41","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  290. DATA "42","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  291. DATA "43","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  292. DATA "44","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  293. DATA "45","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  294. DATA "46","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  295. DATA "47","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  296. DATA "48","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  297. DATA "49","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  298. DATA "50","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  299. DATA "51","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  300. DATA "52","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  301. DATA "53","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  302. DATA "54","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  303. DATA "55","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  304. DATA "56","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  305. DATA "57","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  306. DATA "58","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  307. DATA "59","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  308. DATA "51","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  309. DATA "60","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  310. DATA "61","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  311. DATA "62","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  312. DATA "63","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  313. DATA "64","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  314.  
  315. PiecePatterns:
  316. DATA ........................
  317. DATA ........................
  318. DATA ........................
  319. DATA ........................
  320. DATA ....X..XX..XX..XX..X....
  321. DATA ....X..XX..XX..XX..X....
  322. DATA ....X..XX..XX..XX..X....
  323. DATA ....X..XX..XX..XX..X....
  324. DATA ....X..XX..XX..XX..X....
  325. DATA .....X.XX..XX..XX.X.....
  326. DATA ......XXXXXXXXXXXX......
  327. DATA .....XX..........XX.....
  328. DATA ......X.XXXXXXXX.X......
  329. DATA ......X.XXXXXXXX.X......
  330. DATA ......X.XXXXXXXX.X......
  331. DATA ......X.XXXXXXXX.X......
  332. DATA .....X............X.....
  333. DATA .....X..XXXXXXXX..X.....
  334. DATA ....X..............X....
  335. DATA ...X..XXXXXXXXXXXX..X...
  336. DATA ...X................X...
  337. DATA ...XXXXXXXXXXXXXXXXXX...
  338.  
  339. DATA ........................
  340. DATA ........................
  341. DATA ........................
  342. DATA ........................
  343. DATA ............XXX.........
  344. DATA ..........XX.X.X........
  345. DATA .........X..X.X.XX......
  346. DATA ........X.X.XX.X..X.....
  347. DATA .......X.XXXX.X.X..X....
  348. DATA .......X.X...XXX.X..X...
  349. DATA .....X..XX..X.XXX.X.X...
  350. DATA ....X.XXXXXXX.XXX.X..X..
  351. DATA ...X.XXXXXX.X..XX.X..X..
  352. DATA ...X.XX..XXX.X.XX.X..X..
  353. DATA ....X..XXXX..X.XX.X..X..
  354. DATA .....XX..X..X.XXX.X..X..
  355. DATA ........X..XX.XX.XX.X...
  356. DATA .......X..XX.XX.XX.X....
  357. DATA ......XXXXXXXXXXXXXX....
  358. DATA .....X..............X...
  359. DATA ....X................X..
  360. DATA .....XXXXXXXXXXXXXXXX...
  361.  
  362. DATA ........................
  363. DATA ........................
  364. DATA ........................
  365. DATA ............X...........
  366. DATA ...........X.X..........
  367. DATA ..........X.X.X.........
  368. DATA ........X...XX..X.......
  369. DATA .......X..X..XX..X......
  370. DATA .......X.XXX..XX.X......
  371. DATA .......X.XXXX..X.X......
  372. DATA ........X.......X.......
  373. DATA .......XX.X.X.X.XX......
  374. DATA ......X...........X.....
  375. DATA .......X.XXX.XX.XX......
  376. DATA ........X.XX.XX.X.......
  377. DATA .......X.XXX.XXX.X......
  378. DATA .......X.XXX.XXX.X......
  379. DATA ......X.X.......X.X.....
  380. DATA .....X.XXXXX.XXXXX.X....
  381. DATA .....X.XXXXX.XXXXX.X....
  382. DATA .....X.............X....
  383. DATA ......XXXXXXXXXXXXX.....
  384.  
  385. DATA ............X...........
  386. DATA ...........X.X..........
  387. DATA .....X....X.X.X....X....
  388. DATA ....X.X.XX.XXX..X.X.X...
  389. DATA ...X.X.X..XX.XXX.X.X.X..
  390. DATA ...X.XX.XXX.X.XXX.XX.X..
  391. DATA ...X.XXX.X.XXX.X.XXX.X..
  392. DATA ...X.XXXX.XXXXX.XXXX.X..
  393. DATA ....X.XXXXXX..XXXXX.X...
  394. DATA .....X.XXXXX..XXXX.X....
  395. DATA .....X.............X....
  396. DATA ......XXXXXXXXXXXXX.....
  397. DATA ....X...............X...
  398. DATA ......XX.XXXXXXX.XX.....
  399. DATA .......X.X.XXX.X.X......
  400. DATA ......X.XX.XXX.XX.X.....
  401. DATA ......X.XX.XXX.XX.X.....
  402. DATA .....XXXXXXXXXXXXXXX....
  403. DATA ....X...............X...
  404. DATA ...X..XX.XX.XX.XX.X..X..
  405. DATA ...X.................X..
  406. DATA ....XXXXXXXXXXXXXXXXX...
  407.  
  408. DATA ...........XX...........
  409. DATA .........XX..XX.........
  410. DATA .......XX.X..X.XX.......
  411. DATA .....XX.X......X.XX.....
  412. DATA ....X..XX.X..X.XX..X....
  413. DATA ...X...XXXX..XXXX...X...
  414. DATA ..X...XX........XX...X..
  415. DATA .X..XXX.XXX..XXX.XXX..X.
  416. DATA X..XXX..XXX..XXX..XXX..X
  417. DATA X.XXXX..XXX..XXXX.XXXX.X
  418. DATA X.XXXX.XXXX..XXXX.XXXX.X
  419. DATA X.XXXX..XXXXXXXX..XXXX.X
  420. DATA .X.XXXX..XXXXXX..XXXX.X.
  421. DATA .X..XXXX..XXXX..XXXX..X.
  422. DATA ..X..XXXX......XXXX..X..
  423. DATA ...X....X......X....X...
  424. DATA ...XXXXXXXXXXXXXXXXXX...
  425. DATA ..X..................X..
  426. DATA .X..XXXXXXXXXXXXXXXX..X.
  427. DATA .X..XXXXXXXXXXXXXXXX..X.
  428. DATA ..X..................X..
  429. DATA ...XXXXXXXXXXXXXXXXXX...
  430.  
  431. DATA ........................
  432. DATA ........................
  433. DATA ........................
  434. DATA ..........XXXX..........
  435. DATA .........X....X.........
  436. DATA ........X.XXXX.X........
  437. DATA ........X.XXXX.X........
  438. DATA .........X....X.........
  439. DATA ........XXXXXXXX........
  440. DATA .......X........X.......
  441. DATA ........XXXXXXXX........
  442. DATA .........X.XX.X.........
  443. DATA .........X.XX.X.........
  444. DATA .........X.XX.X.........
  445. DATA ........X..XX..X........
  446. DATA .......X..XXXX..X.......
  447. DATA ......X.XXXXXXXX.X......
  448. DATA ......X.XXXXXXXX.X......
  449. DATA .....X............X.....
  450. DATA ......XXXXXXXXXXXX......
  451. DATA ........................
  452. DATA ........................
  453.  
  454. rgb:
  455. DATA 0,0,0,0,""
  456. 'DATA 1,20,50,0,"board white"
  457. DATA 1,30,60,20,"board white"
  458. DATA 2,1,1,1,"board black"
  459. DATA 3,50,50,50,"white bright"
  460. DATA 4,12,12,30,"white hightlight"
  461. DATA 5,0,0,0,"black bright"
  462. 'DATA 6,32,32,32,"black highlight"
  463. DATA 6,50,12,12,"black highlight"
  464. DATA 7,63,0,0,"red"
  465. DATA 8,0,63,0,"green"
  466. DATA 9,0,0,63,"blue"
  467. DATA 10,50,50,50,"white"
  468. DATA 11,20,20,20,""
  469. DATA 12,20,20,20,""
  470. DATA 13,40,10,30,""
  471. DATA 14,25,25,25,"gray"
  472. DATA 15,30,30,30,"printing"
  473.  
  474. cmenu:
  475. DATA "1 Board white"
  476. DATA "2 Board black"
  477. DATA "3 W piece main"
  478. DATA "4 W piece trim"
  479. DATA "5 B piece main"
  480. DATA "6 B piece trim"
  481.  
  482. Oops:
  483. gronk = gronk + 1
  484. IF gronk < 100 THEN
  485.     RESUME
  486.     PRINT "Error "; DATE$; "  "; TIME$;
  487.     END
  488.  
  489. SUB AddIt (Level, tm$, Score)
  490.     IF rflag THEN mcount&(Level) = mcount&(Level) + 1
  491.     Moves(Level) = Moves(Level) + 1 '                                count ok
  492.     Move$(Level, Moves(Level)) = tm$ '                               save move
  493.     Score(Level, Moves(Level)) = Score
  494.     Index(Level, Moves(Level)) = TieTo(Level)
  495.  
  496. SUB AddMove
  497.  
  498.     IF WorB THEN '                                                   white=1, black=0
  499.         Move = Move + 1 '                                            number the moves
  500.         PRINT #1, RIGHT$("  " + STR$(Move), 3);
  501.         PRINT #1, RIGHT$(SPACE$(10) + m$, 7);
  502.         MoveLog$(Move) = SPACE$(15)
  503.         MID$(MoveLog$(Move), 1, 3) = Rjust$(Move, 3)
  504.         MID$(MoveLog$(Move), 5, LEN(m$)) = m$
  505.     ELSE
  506.         MID$(MoveLog$(Move), 11, LEN(m$)) = m$
  507.         PRINT #1, " "; m$
  508.         IF (Move MOD 5) = 0 THEN PRINT #1, ""
  509.     END IF
  510.  
  511.  
  512. SUB Center (tr, t$, highlight)
  513.     IF t$ = "" THEN
  514.         IF rflag THEN
  515.             t$ = "           Quit   spacebar:move now   Noise           "
  516.         ELSE
  517.             t$ = "Quit Resign Back Color Invert Setup Mode Noise Graphic"
  518.         END IF
  519.     END IF
  520.     z = _WIDTH \ 2 - LEN(t$) * 4 + 8
  521.     SELECT CASE tr
  522.         CASE IS = -1
  523.             y = ym - 40
  524.         CASE IS = 0
  525.             y = ym - 18
  526.         CASE ELSE
  527.             y = tr / (ym / 16) * ym
  528.     END SELECT
  529.     LINE (0, ym)-(xm - 1, ym - 18), black&, BF
  530.     COLOR white&
  531.     _PRINTSTRING (z, y), t$
  532.     IF highlight THEN
  533.         COLOR cp&(1)
  534.         FOR i = 1 TO LEN(t$)
  535.             c$ = MID$(t$, i, 1)
  536.             IF (c$ = UCASE$(c$)) AND (c$ <> ":") THEN
  537.                 _PRINTSTRING (z + (i - 1) * 8, y), c$
  538.             END IF
  539.         NEXT
  540.     END IF
  541.     COLOR white&
  542.  
  543. SUB ChangeColors
  544.     LINE (0, 500)-(xm, ym), black&, BF '                             clear lower area
  545.     k = 1
  546.     DO
  547.         RESTORE cmenu
  548.         FOR i = 1 TO 6
  549.             READ t$
  550.             tx = 40 + INT((i - 1) / 2) * 150
  551.             ty = 540 + ((i - 1) MOD 2) * 16
  552.             IF i = k THEN COLOR white& ELSE COLOR gray& '            highlight palette for change
  553.             _PRINTSTRING (tx, ty), t$
  554.         NEXT i
  555.         COLOR white&
  556.         t$ = "rgb:down   RGB:up  Esc:exit"
  557.         tx = _WIDTH \ 2 - LEN(t$) * 4 + 8
  558.         _PRINTSTRING (tx, _HEIGHT - 20), t$
  559.  
  560.         FOR i = 1 TO 3 '                                             show 3 colors lines
  561.             x1 = xc - xq * 4: x2 = xc + xq * 4
  562.             y1 = yc + yq * 4 + 20 + i * 8: y2 = y1 + 4
  563.             LINE (x1, y1)-(x2, y2), black&, BF
  564.             LINE (x1, y1)-(x2, y2), gray&, B
  565.             IF i = 1 THEN j = myr(k): tc& = red&
  566.             IF i = 2 THEN j = myg(k): tc& = green&
  567.             IF i = 3 THEN j = myb(k): tc& = blue&
  568.             j = j / 255 * xq * 8
  569.             LINE (x1, y1)-(x1 + j, y2), tc&, BF
  570.         NEXT i
  571.  
  572.         _DISPLAY
  573.  
  574.         DO: _LIMIT 10: i$ = INKEY$: LOOP UNTIL LEN(i$) '             wait for key
  575.         IF i$ = Esc$ THEN EXIT DO '                                  done
  576.         IF i$ = "" THEN i$ = " " '                                   so instr doesn't bomb
  577.         p = INSTR("123456", i$): IF p THEN k = p '                   select palette
  578.  
  579.         z = 10
  580.         SELECT CASE i$
  581.             CASE IS = "r" '                                          red down
  582.                 myr(k) = myr(k) - z
  583.                 IF myr(k) < 0 THEN myr(k) = 0
  584.             CASE IS = "g" '                                          green down
  585.                 myg(k) = myg(k) - z
  586.                 IF myg(k) < 0 THEN myg(k) = 0
  587.             CASE IS = "b" '                                          blue down
  588.                 myb(k) = myb(k) - z
  589.                 IF myb(k) < 0 THEN myb(k) = 0
  590.             CASE IS = "R" '                                          red up
  591.                 myr(k) = myr(k) + z
  592.                 IF myr(k) > 255 THEN myr(k) = 255
  593.             CASE IS = "G" '                                          green up
  594.                 myg(k) = myg(k) + z
  595.                 IF myg(k) > 255 THEN myg(k) = 255
  596.             CASE IS = "B" '                                          blue up
  597.                 myb(k) = myb(k) + z
  598.                 IF myb(k) > 255 THEN myb(k) = 255
  599.         END SELECT
  600.  
  601.         ColorWrite
  602.         Colorassign
  603.         PlotScreen false
  604.     LOOP
  605.  
  606.     LINE (0, 500)-(xm, ym), black&, BF
  607.  
  608.  
  609. SUB CheckBoard (Level)
  610.     Moves(Level) = 0
  611.     prot(Level) = 0
  612.  
  613.     FOR r = 1 TO 8
  614.         FOR c = 1 TO 8
  615.             mp = b(c, r)
  616.             mc = -(mp > 6) - (mp = 0) * 2 '                          evaluates to 0 black 1 white 2 empty
  617.             mp = mp + (mp > 6) * 6
  618.             IF mc = WorB THEN
  619.                 TryMove Level, c, r, mp, mc
  620.             END IF
  621.         NEXT
  622.     NEXT
  623.  
  624.     IF Level > 1 THEN GOTO nocastle '                                only do for current move (speed)
  625.  
  626.     cq = true: ck = true '                                           castling
  627.  
  628.     IF WorB THEN rn$ = "1" ELSE rn$ = "8"
  629.     rn = VAL(rn$)
  630.     tp = b(5, rn): tp = tp + (tp > 6) * 6 '                          e1 (white) or e8 (black)
  631.     IF tp <> King THEN cq = 0: ck = 0: GOTO nocastle '               no King here
  632.  
  633.     t$ = "e" + rn$ '                                                 King home spot algebraic
  634.     FOR lm = 1 TO Moves(1) '                                         can any opponent piece move there?
  635.         IF t$ = RIGHT$(Move$(1, lm), 2) THEN cq = 0: ck = 0: GOTO nocastle ' must be in check
  636.     NEXT lm
  637.  
  638.     ' WHITE                      BLACK
  639.     ' 8 R N B Q K B N R          1 R N B K Q B N R
  640.     ' 7 P P P P P P P P          2 P P P P P P P P
  641.     ' 6                          3
  642.     ' 5                          4
  643.     ' 4                          5
  644.     ' 3                          6
  645.     ' 2 P P P P P P P P          7 P P P P P P P P
  646.     ' 1 R N B Q K B N R          8 R N B K Q B N R
  647.     '   a b c d e f g h            h g f e d c b a
  648.  
  649.     FOR castle = 1 TO 2 '                                            queenside, then kingside
  650.  
  651.         'debug$(castle) = ""
  652.         nr = 0 '   no rook
  653.         pr = 0 '   prior condition
  654.         ne = 0 '   not empty
  655.         co = 0 '   controlled space
  656.  
  657.         '                 bbww
  658.         ' castle$ format "QKQK" blank if ok, X if nulled by King or Rook move
  659.         IF MID$(castle$, WorB * 2 + castle, 1) <> " " THEN pr = castle: GOTO nocando '  prior condition
  660.  
  661.         IF castle = 1 THEN cn = 1 ELSE cn = 8 '                      column number
  662.         p = b(cn, rn): p = p + (p > 6) * 6
  663.         IF p <> Rook THEN nr = 1: GOTO nocando
  664.  
  665.         '                         bcd              fg
  666.         IF castle = 1 THEN ca$ = "234" ELSE ca$ = "67" '             column number
  667.         FOR cs = 1 TO LEN(ca$) '                                     look at spaces between king and rook
  668.             cn = VAL(MID$(ca$, cs, 1))
  669.             IF b(cn, rn) > 0 THEN ne = castle: GOTO nocando '        not empty
  670.  
  671.             IF NOT ((cs = 1) AND (castle = 1)) THEN '                queenside knight
  672.                 t$ = MID$(alpha$, cn, 1) + rn$ '                     controlled square?
  673.                 IF Level THEN lm = 0 ELSE lm = 1
  674.                 FOR i = 1 TO Moves(lm) '                             see what can move here
  675.                     IF t$ = RIGHT$(Move$(lm, i), 2) THEN
  676.                         'debug$(castle) = Move$(lm, i)
  677.                         co = castle: EXIT FOR ' yes
  678.                     END IF
  679.                 NEXT i
  680.             END IF
  681.         NEXT cs
  682.         nocando:
  683.         'debug$(castle) = debug$(castle) + STR$(nr) + STR$(pr) + STR$(ne) + STR$(co)
  684.         IF (nr + pr + ne + co) THEN '                                non-zero means some test failed
  685.             IF castle = 1 THEN cq = false ELSE ck = false
  686.         END IF
  687.     NEXT castle
  688.  
  689.     IF ck THEN AddIt Level, "O-O", 12
  690.     IF cq THEN AddIt Level, "O-O-O", 13
  691.  
  692.     'LOCATE 34 + WorB, 45: PRINT "*"; castle$; "* ";
  693.     'PRINT MID$("K ", ck + 2, 1);
  694.     'PRINT MID$("Q ", cq + 2, 1); cq; ck;
  695.  
  696.     nocastle:
  697.     TakeBest Level, false
  698.  
  699. SUB Colorassign
  700.     tf$ = "ccolor.dat"
  701.     tf = FREEFILE
  702.     IF _FILEEXISTS(tf$) THEN
  703.         OPEN tf$ FOR INPUT AS #tf
  704.         INPUT #tf, bri
  705.         IF bri = 0 THEN bri = obri
  706.         IF bri < 2 THEN bri = 2
  707.         FOR i = 0 TO 31
  708.             INPUT #tf, myr(i), myg(i), myb(i)
  709.             cp&(i) = _RGB32(myr(i) * bri, myg(i) * bri, myb(i) * bri)
  710.         NEXT
  711.         CLOSE #tf
  712.     ELSE
  713.         bri = 4
  714.         RESTORE rgb
  715.         FOR i = 0 TO 31
  716.             IF i < 16 THEN
  717.                 READ PalNum, myr(i), myg(i), myb(i), Desc$
  718.             ELSE
  719.                 myr(i) = 32: myg(i) = 32: myb(i) = 32
  720.             END IF
  721.             cp&(i) = _RGB32(myr(i) * bri, myg(i) * bri, myb(i) * bri)
  722.         NEXT
  723.         ColorWrite
  724.     END IF
  725.     CLOSE #tf
  726.     black& = cp&(0)
  727.     boardwhite& = cp&(1)
  728.     boardblack& = cp&(2)
  729.     red& = cp&(7)
  730.     green& = cp&(8)
  731.     blue& = cp&(9)
  732.     white& = _RGB32(155, 155, 155)
  733.     gray& = _RGB32(40, 40, 40)
  734.     COLOR gray&
  735.     IF altblack THEN cp&(6) = _RGB32(32 * bri, 32 * bri, 32 * bri)
  736.  
  737. SUB ColorWrite
  738.     tf$ = "ccolor.dat"
  739.     tf = FREEFILE
  740.     OPEN tf$ FOR OUTPUT AS #tf
  741.     PRINT #tf, bri
  742.     FOR i = 0 TO 31
  743.         PRINT #tf, myr(i); ","; myg(i); ","; myb(i)
  744.     NEXT
  745.     CLOSE #tf
  746.  
  747. SUB Cursor (br, bc, fl) STATIC
  748.     DIM garr(8000)
  749.     IF (bc < 1) OR (br < 1) OR (bc > 8) OR (br > 8) THEN EXIT SUB
  750.     x1 = xc + (bc - 5) * xq: x2 = x1 + xq
  751.     y1 = yc + (4 - br) * yq: y2 = y1 + yq
  752.     GET (x1, y1)-(x2, y2), garr()
  753.     IF (ctime! = 0) OR (TIMER > ctime!) THEN xx = xx XOR 1: ctime! = TIMER + .25
  754.     IF xx THEN
  755.         IF useidiot OR (TIMER < alfred!) THEN PUT (x1 + 2, y1 + 2), abuff(), PSET ELSE PUT (x1, y1), garr(), PRESET
  756.     END IF
  757.     IF fl THEN _PRINTSTRING (x1 + 16, y1 + 36), "To?"
  758.     _DISPLAY
  759.  
  760. SUB DispStats
  761.  
  762.     IF waitflag = 0 THEN
  763.         IF rflag = 0 THEN tc = humanc ELSE tc = 1 - humanc
  764.         etime!(tc) = etime!(tc) + TIMER - Start2!
  765.         etime!(2) = TIMER - Start1! + hold! '                        current move
  766.         hold! = 0
  767.         IF etime!(2) > etime!(tc) THEN etime!(2) = etime!(tc)
  768.         etime!(3) = etime!(0) + etime!(1) '                          game total
  769.         emin = etime!(2) \ 60
  770.     END IF
  771.     Start2! = TIMER
  772.  
  773.     IF (dtime! = 0) OR (TIMER > dtime!) THEN
  774.  
  775.         'IF rick AND (vflag = 0) THEN
  776.         '    LOCATE 1, 4
  777.         '    PRINT Moves(0);
  778.         '    FOR i = 1 TO 3
  779.         '        PRINT mcount&(i);
  780.         '    NEXT i
  781.         '    LOCATE 2, 4
  782.         '    FOR i = 0 TO 3
  783.         '        PRINT Moves(i);
  784.         '    NEXT i
  785.         'END IF
  786.  
  787.         'IF tlimit > 0 THEN t$ = LTRIM$(STR$(tlimit)) + "m" ELSE t$ = "unlimited"
  788.         't$ = "Time: " + t$
  789.         'LOCATE 2, 4: PRINT t$;
  790.  
  791.         tcount& = Moves(0) + mcount&(1) + mcount&(2) + mcount&(3)
  792.         mps& = tcount& - ocount&
  793.         IF mps& <= 100 THEN mps& = omps& ELSE opms& = mps&
  794.         t$ = "   " + STR$(mps&)
  795.         tx = _WIDTH - LEN(t$) * 8 - 10
  796.         IF mps& THEN _PRINTSTRING (tx, 2), t$
  797.  
  798.         t$ = STR$(tcount&)
  799.         tx = _WIDTH - LEN(t$) * 8 - 10
  800.         _PRINTSTRING (tx, 16), t$
  801.  
  802.         ShowTime 32, etime!(0), "Black"
  803.         ShowTime 33, etime!(1), "White"
  804.         ShowTime 34, etime!(3), "Game"
  805.         ShowTime 35, etime!(2), "Move"
  806.  
  807.         ocount& = tcount&
  808.         dtime! = TIMER + 1
  809.     END IF
  810.  
  811.     IF (showthink = 0) OR (smode < 2) THEN _DISPLAY
  812.  
  813.  
  814. DEFSNG A-Z
  815. FUNCTION f_pl (n1, n2, n3) '                                         plasma function
  816.     f_pl = _RGB32(n1 * 255, n2 * 255, n3 * 255)
  817.  
  818. DEFINT A-Z
  819. SUB Init
  820.     xm = 600: ym = 200
  821.     main& = _NEWIMAGE(xm, ym, 32)
  822.     SCREEN main&
  823.     _DELAY .2
  824.     _DELAY .2
  825.  
  826.     RANDOMIZE TIMER '                                                seed generator
  827.     Colorassign '                                                    red&, green&, etc, easier to use than palette numbers
  828.  
  829.     alpha$ = "abcdefgh"
  830.     castle$ = SPACE$(4) '                                            flags QKQK (B then W)
  831.     crlf$ = Enter$ + lf$
  832.     Enter$ = CHR$(13)
  833.     Esc$ = CHR$(27) '                                                to quit program
  834.     graphics = 3 '                                                   graphics for white squares (0-3)
  835.     lcount& = 0 '                                                    line counter for debug output
  836.     lf$ = CHR$(10) '                                                 line feed
  837.     Move = 0
  838.     MakeNoise = 1
  839.     showthink = 1
  840.     WorB = 1 '                                                       white=1, black=0
  841.     xq = 56: yq = 56
  842.     xc = 248: yc = 256 '                                             center of board
  843.  
  844.     FOR i = 1 TO 8
  845.         alphal$(i) = MID$(alpha$, i, 1)
  846.     NEXT i
  847.  
  848.     FOR i = 0 TO 3: etime!(i) = 0: NEXT '                            sides, total, current
  849.  
  850.     RESTORE PiecePatterns '                                          bit images
  851.     FOR p = 1 TO 6 '                                                 RNBQKP
  852.         n = 0
  853.         FOR y = 0 TO 21 ' 22 rows
  854.             READ d$
  855.             p1 = INSTR(d$ + "X", "X") '                              find first "on" bit
  856.             FOR t = LEN(d$) TO 1 STEP -1 '                           find last "on" bit
  857.                 IF MID$(d$, t, 1) = "X" THEN
  858.                     p2 = t
  859.                     EXIT FOR
  860.                 END IF
  861.             NEXT t
  862.             FOR x = p1 TO p2
  863.                 pixel = INSTR(".X", MID$(d$, x, 1))
  864.                 n = n + 1
  865.                 IF pixel = 2 THEN c = 3 ELSE c = 4
  866.                 x(p, n) = x + 1
  867.                 y(p, n) = y + 2
  868.                 c(p, n) = c
  869.                 IF pixel = 2 THEN c = 5 ELSE c = 6
  870.                 c(p + 6, n) = c
  871.             NEXT x
  872.         NEXT y
  873.         c(p, 0) = n
  874.         FOR scram = 1 TO 256 '                                       scramble (moves nicer)
  875.             c1 = RND * (c(p, 0) - 1) + 1 '                           any bit
  876.             c2 = RND * (c(p, 0) - 1) + 1 '                           any other bit
  877.             SWAP x(p, c1), x(p, c2)
  878.             SWAP y(p, c1), y(p, c2)
  879.             SWAP c(p, c1), c(p, c2) '                                black
  880.             SWAP c(p + 6, c1), c(p + 6, c2) '                        white
  881.         NEXT scram
  882.     NEXT p
  883.  
  884.     RESTORE Legal '                                                  define how piece moves
  885.     FOR p = 1 TO 6 '                                                 RNBQKP
  886.         READ p$ '                                                    piece, not saved
  887.         FOR t = 0 TO 7 '                                             8 each
  888.             READ udlr$
  889.             du(p, t) = VAL(MID$(udlr$, 1, 1)) '                      direction up
  890.             dd(p, t) = VAL(MID$(udlr$, 2, 1)) '                      direction down
  891.             dl(p, t) = VAL(MID$(udlr$, 3, 1)) '                      direction left
  892.             dr(p, t) = VAL(MID$(udlr$, 4, 1)) '                      direction right
  893.         NEXT t
  894.     NEXT p
  895.  
  896.     FOR i = 1 TO 6
  897.         '                    RNBQKP
  898.         value(i) = VAL(MID$("533901", i, 1)) '                       point value for capture
  899.     NEXT i
  900.  
  901.     RESTORE Setup '                                                  initial board position
  902.     FOR r = 8 TO 1 STEP -1 '                                         row
  903.         FOR c = 1 TO 8 '                                             column
  904.             READ b(c, r) '                                           board
  905.             o(c, r) = b(c, r) '                                      initial setup
  906.         NEXT c
  907.     NEXT r
  908.  
  909.     gm = 0: n = 0
  910.     IF LEN(GameFile$) > 0 THEN ReadGame
  911.     gm = 0
  912.  
  913.     CLOSE
  914.     newf:
  915.     f = f + 1
  916.     f$ = "ch" + RIGHT$("0000000" + LTRIM$(STR$(f)), 6) + ".alg" '    save game for analysis
  917.     IF _FILEEXISTS(f$) THEN GOTO newf
  918.  
  919.     OPEN f$ FOR OUTPUT AS #1 '                                       algrebraic moves
  920.     MasterLevel1 = VAL(COMMAND$) '                                   only 4 really tested....2 is plenty stupid, odds not tested!
  921.     IF MasterLevel1 = 0 THEN MasterLevel1 = 4
  922.  
  923.     FOR i = 0 TO 3
  924.         SELECT CASE i
  925.             CASE IS = 0
  926.                 f$ = "alfred.jpg" '                                  Alfred E. Neuman
  927.             CASE IS = 1
  928.                 f$ = "chess.png"
  929.             CASE IS = 2
  930.                 f$ = "clockx.png"
  931.             CASE IS = 3
  932.                 f$ = "clockx2.png"
  933.         END SELECT
  934.         IF _FILEEXISTS(f$) = 0 THEN '                                accomodate Linux, which cares about case
  935.             f$ = UCASE$(f$) '                                        now try uppercase
  936.             IF _FILEEXISTS(f$) = 0 THEN SYSTEM '                     so it really isn't there
  937.         END IF
  938.         li1:
  939.         icon&(i) = _LOADIMAGE(f$)
  940.         IF icon&(i) >= -1 THEN _DELAY .2: GOTO li1
  941.     NEXT i
  942.     _ICON icon&(1)
  943.     _DELAY .2
  944.  
  945.     _SOURCE icon&(0) '                                               Alfred E. Neuman
  946.     _DISPLAY '                                                       hide idiot
  947.     _PUTIMAGE
  948.     GET (0, 0)-(52, 53), abuff(0)
  949.  
  950.     CLS
  951.     _DELAY .2
  952.     Menubox
  953.     Center 6, "White  Black  Humans  Computer", 1
  954.     Center 0, "Quit or Esc to exit", 1
  955.     _DISPLAY
  956.     DO: _LIMIT 10
  957.         i$ = INKEY$
  958.         IF i$ = "" THEN i$ = " "
  959.         IF (LCASE$(i$) = "q") OR (i$ = Esc$) THEN SYSTEM
  960.         p = INSTR("bwhc", i$)
  961.     LOOP UNTIL p
  962.     SELECT CASE p
  963.         CASE IS = 1 '                                                player is black
  964.             human = 1: humanc = 0: invert = 1
  965.         CASE IS = 2 '                                                player is white
  966.             human = 1: humanc = 1
  967.         CASE IS = 3 '                                                human vs. human
  968.             human = 2
  969.         CASE IS = 4 '                                                computer vs. computer, just watch
  970.             human = 0: OnAuto = 1
  971.     END SELECT
  972.  
  973.     'IF human <> 2 THEN
  974.     '    tlimit = 0
  975.     '    DO
  976.     '        CLS
  977.     '        Menubox
  978.     '        Center 6, "Time limit in minutes?  (0 unlimited)", 0
  979.     '        Center 8, STR$(tlimit), 0
  980.     '        Center 0, "Quit or Esc to exit", 1
  981.     '        _DISPLAY
  982.     '        DO: _LIMIT 10
  983.     '            i$ = INKEY$
  984.     '        LOOP UNTIL LEN(i$)
  985.     '        IF (LCASE$(i$) = "q") OR (i$ = Esc$) THEN SYSTEM
  986.     '        IF i$ = CHR$(8) THEN tlimit = tlimit / 10
  987.     '        p = INSTR("0123456789", i$): IF p THEN tlimit = tlimit * 10 + p - 1
  988.     '    LOOP UNTIL i$ = Enter$
  989.     'END IF
  990.  
  991.     'IF rick THEN smode = 2
  992.     ScreenInit
  993.     PlotBoard
  994.  
  995. SUB HumanMove STATIC
  996.     cursoron! = TIMER + 3
  997.     IF cc = 0 THEN
  998.         rr = 7
  999.         cc = 5 + (WorB = 0)
  1000.     END IF
  1001.     FOR i = 0 TO 1
  1002.         DO: _LIMIT 30
  1003.             IF vflag THEN ShowValid cc, rr
  1004.             KeyScan 1, 0 '                                           plotscreen, no _display
  1005.             IF rr < 1 THEN rr = 1
  1006.             IF rr > 8 THEN rr = 8
  1007.             IF cc < 1 THEN cc = 1
  1008.             IF cc > 8 THEN cc = 8
  1009.             IF cursoron! > TIMER THEN Cursor 9 - rr, cc, i
  1010.             IF takebackflag OR LEN(msg$) THEN EXIT SUB
  1011.             WHILE _MOUSEINPUT
  1012.                 mx = _MOUSEX
  1013.                 my = _MOUSEY
  1014.                 xx = (mx - xc - (4 * xq) + xq \ 2) / xq + 8
  1015.                 yy = (my - yc - (4 * yq) + yq \ 2) / yq + 8
  1016.                 IF (xx > 0) AND (xx < 9) AND (yy > 0) AND (yy < 9) THEN rr = yy: cc = xx
  1017.                 IF _MOUSEBUTTON(1) OR _MOUSEBUTTON(2) THEN i$ = Enter$
  1018.             WEND
  1019.             IF LEN(i$) = 2 THEN
  1020.                 kk = ASC(RIGHT$(i$, 1))
  1021.                 cc = cc + (kk = 75) - (kk = 77) '                    left right
  1022.                 rr = rr + (kk = 72) - (kk = 80) '                    up down
  1023.             END IF
  1024.         LOOP UNTIL i$ = Enter$
  1025.         IF i = 0 THEN
  1026.             fr = rr: fc = cc
  1027.             IF invert THEN fr = 9 - fr: fc = 9 - fc
  1028.         ELSE
  1029.             tr = rr: tc = cc
  1030.             IF invert THEN tr = 9 - tr: tc = 9 - tc
  1031.         END IF
  1032.     NEXT i
  1033.  
  1034.     fs$ = alphal$(fc) + LTRIM$(STR$(9 - fr))
  1035.     ts$ = alphal$(tc) + LTRIM$(STR$(9 - tr))
  1036.     m$ = fs$ + ts$
  1037.     IF m$ = "e1g1" THEN m$ = "O-O"
  1038.     IF m$ = "e1c1" THEN m$ = "O-O-O"
  1039.     IF m$ = "e8g8" THEN m$ = "O-O"
  1040.     IF m$ = "e8c8" THEN m$ = "O-O-O"
  1041.  
  1042. SUB KeyScan (kf1, kf2) STATIC '                                      plotscreen, _display
  1043.     TempMess "", 0
  1044.     DispStats
  1045.     dot = 0
  1046.     i$ = INKEY$
  1047.     IF LEN(i$) THEN
  1048.         cursoron! = TIMER + 2
  1049.     END IF
  1050.     IF LEN(i$) = 1 THEN
  1051.         IF (LCASE$(i$) = "q") OR (i$ = Esc$) THEN abort = 9: msg$ = "Quit!"
  1052.         IF i$ = Enter$ THEN EXIT SUB
  1053.         IF i$ = " " THEN msg$ = "abort": abort = 1: EXIT SUB '       move now
  1054.         c = INSTR("123456789ABCDEF0", i$) '                          experiment with colors
  1055.         IF c > 0 THEN
  1056.             IF c = 16 THEN
  1057.                 c = 2
  1058.                 myr(c) = 0: myg(c) = 0: myb(c) = 0
  1059.             ELSE
  1060.                 myr(c) = RND * 64: myg(c) = RND * 64: myb(c) = RND * 64
  1061.             END IF
  1062.             cp&(c) = _RGB32(myr(c) * bri, myg(c) * bri, myb(c) * bri)
  1063.             ColorWrite
  1064.             Colorassign
  1065.             PlotBoard
  1066.         END IF
  1067.         IF i$ = "a" THEN OnAuto = NOT (OnAuto) '                     not currently in use
  1068.         IF i$ = "b" THEN takebackflag = 1
  1069.         IF i$ = "c" THEN ChangeColors
  1070.         IF i$ = "g" THEN '                                           change white square graphics scheme
  1071.             graphics = (graphics + 1) MOD 4
  1072.             IF graphics = 0 THEN PlotBoard
  1073.             t$ = "Mode" + STR$(graphics + 1) + " of 4"
  1074.             TempMess t$, 2
  1075.         END IF
  1076.         IF i$ = "G" THEN pinit = pinit XOR 1 '                       adjust current white square graphics
  1077.         IF i$ = "h" THEN dot = 1: history = history XOR 1
  1078.         IF i$ = "i" THEN invert = invert XOR 1: PlotBoard '          flip board around
  1079.         IF i$ = "I" THEN
  1080.             useidiot = useidiot XOR 1
  1081.             t$ = "Idiot " + OnOff$(useidiot)
  1082.             TempMess t$, 2
  1083.         END IF
  1084.         IF i$ = "l" THEN dot = 1: showlegalf = showlegalf XOR 1
  1085.         IF i$ = "L" THEN '                                           look at log file
  1086.             CLOSE #2
  1087.             SHELL _DONTWAIT "notepad chess.txt"
  1088.             OPEN "chess.txt" FOR APPEND AS #2
  1089.         END IF
  1090.         IF i$ = "m" THEN '                                           screen mode
  1091.             smode = (smode + 1) MOD 3
  1092.             ScreenInit
  1093.         END IF
  1094.         IF i$ = "n" THEN '                                           sound effects
  1095.             MakeNoise = MakeNoise XOR 1
  1096.             t$ = "Sound " + OnOff$(MakeNoise)
  1097.             TempMess t$, 2
  1098.         END IF
  1099.         IF i$ = "p" THEN dot = 1: showprotf = showprotf XOR 1
  1100.         IF i$ = "P" THEN
  1101.             pause = pause XOR 1
  1102.             IF pause THEN
  1103.                 LOCATE 2, 29: PRINT "PAUSED";
  1104.                 _DISPLAY
  1105.                 hold! = TIMER - etime!(2)
  1106.                 SLEEP
  1107.                 Start1! = TIMER
  1108.                 LOCATE 2, 29: PRINT SPACE$(10);
  1109.                 _DISPLAY '
  1110.             END IF
  1111.         END IF
  1112.         IF (rflag = 0) AND (i$ = "r") THEN abort = 2: msg$ = "Resign!"
  1113.         IF i$ = "s" THEN Setup '                                     setup
  1114.         IF i$ = "t" THEN dot = 1: showthink = showthink XOR 1
  1115.         IF i$ = "v" THEN '                                           show valid moves at top left
  1116.             vflag = vflag XOR 1
  1117.             LOCATE 2, 4: PRINT SPACE$(40);
  1118.             _DISPLAY
  1119.         END IF
  1120.         IF i$ = "x" AND MakeNoise THEN PlaySound "ding" '            sound test
  1121.         IF i$ = "X" THEN
  1122.             SHELL _HIDE "del ccolor.dat" '                           kill color file
  1123.             ColorWrite
  1124.             Colorassign
  1125.             PlotBoard
  1126.         END IF
  1127.         'IF i$ = "y" THEN itest '                                    see how bad icon problem is
  1128.         IF i$ = "z" THEN
  1129.             altblack = altblack XOR 1
  1130.             Colorassign
  1131.             CLS
  1132.             PlotBoard
  1133.             TempMess "Alternate black " + OnOff(altblack), 2
  1134.         END IF
  1135.         i$ = ""
  1136.     END IF
  1137.     IF LEN(i$) = 2 THEN
  1138.         k = ASC(RIGHT$(i$, 1))
  1139.         wbri = bri
  1140.         bri = bri - (k = 73) + (k = 81) '                            brightness PgUp/PgDn
  1141.         IF bri < 2 THEN bri = 2
  1142.         IF bri > 4 THEN bri = 4
  1143.         IF bri <> wbri THEN '                                        was changed
  1144.             ColorWrite
  1145.             Colorassign
  1146.             TempMess "Brightness" + STR$(bri), 1
  1147.         END IF
  1148.     END IF
  1149.  
  1150.     IF kf1 THEN PlotScreen true
  1151.     IF dot THEN DebugR = 99: TextInfo ""
  1152.     IF kf2 THEN _DISPLAY
  1153.  
  1154. FUNCTION Make4$ (t$)
  1155.     Make4$ = LEFT$(t$ + SPACE$(4), 4)
  1156.  
  1157. SUB LogThinking () STATIC
  1158.     ts = 0: z1$ = "": z2$ = ""
  1159.     FOR t = 1 TO 3
  1160.         ti = TieTo(t)
  1161.         z1$ = z1$ + Make4$(Move$(t - 1, ti)) + " "
  1162.         z2$ = z2$ + Rjust$(Score(t - 1, ti), 3) + " "
  1163.         ts = ts + Score(t - 1, ti)
  1164.     NEXT t
  1165.     ts = ts - Score
  1166.     zz$ = z1$ + Make4$(m$) + z2$ + Rjust$(Score, 3) + " " + Rjust$(ts, 4)
  1167.     PRINT #2, zz$
  1168.     TextInfo zz$
  1169.  
  1170. SUB Menubox
  1171.     tx = _WIDTH \ 2: ty = _HEIGHT \ 2
  1172.     xs = 200: ys = 70
  1173.     x1 = tx - xs: y1 = ty - ys
  1174.     x2 = tx + xs: y2 = ty + ys
  1175.  
  1176.     LINE (x1, y1 + 20)-(x2, y2 - 20), _RGBA(1, 1, 1, 220), BF
  1177.     FOR q = 2 TO 20 STEP 4
  1178.         LINE (x1 - q + 0, y1 + q + 0)-(x2 + q + 0, y2 - q + 0), cp&(1), B
  1179.         LINE (x1 - q + 1, y1 + q + 1)-(x2 + q + 1, y2 - q + 1), cp&(1), B
  1180.     NEXT q
  1181.  
  1182. SUB MoveIt (m$, real)
  1183.     IF m$ = ep$ THEN '                                               epfc, epfr, eptc, eptr, eprc, eprr
  1184.         Plotpiece fc, fr, tc, tr
  1185.         b(epfc, epfr) = 0
  1186.         b(eprc, eprr) = 0
  1187.         b(eptc, eptr) = 6 + WorB * 6
  1188.         EXIT SUB
  1189.     END IF
  1190.  
  1191.     IF m$ = "res" THEN EXIT SUB '                                    resign?
  1192.     fs$ = LEFT$(m$, 2) '                                             from square
  1193.     ts$ = RIGHT$(m$, 2) '                                            to square
  1194.     tzz = 1 - (LEFT$(m$, 1) = "O") - (L1$ = "e") '                   two moves for a castle
  1195.  
  1196.     FOR pass = 1 TO tzz
  1197.  
  1198.         IF m$ = "O-O" THEN '                                         castle Kingside
  1199.             IF WorB = 1 THEN '                                       white
  1200.                 IF pass = 1 THEN '                                   first move of KS castle
  1201.                     fs$ = "e1": ts$ = "g1"
  1202.                 ELSE '                                               else 2nd
  1203.                     fs$ = "h1": ts$ = "f1"
  1204.                 END IF
  1205.             ELSE '                                                   black castle
  1206.                 IF pass = 1 THEN
  1207.                     fs$ = "e8": ts$ = "g8"
  1208.                 ELSE
  1209.                     fs$ = "h8": ts$ = "f8"
  1210.                 END IF
  1211.             END IF
  1212.         END IF
  1213.         IF m$ = "O-O-O" THEN '                                       castle Queenside
  1214.             IF WorB THEN '                                           white
  1215.                 IF pass = 1 THEN
  1216.                     fs$ = "e1": ts$ = "c1"
  1217.                 ELSE
  1218.                     fs$ = "a1": ts$ = "d1"
  1219.                 END IF
  1220.             ELSE
  1221.                 IF pass = 1 THEN
  1222.                     fs$ = "e8": ts$ = "c8"
  1223.                 ELSE
  1224.                     fs$ = "a8": ts$ = "d8"
  1225.                 END IF
  1226.             END IF
  1227.         END IF
  1228.         fc = INSTR(alpha$, LEFT$(fs$, 1)) '                          from column
  1229.         fr = VAL(RIGHT$(fs$, 1)) '                                   from row
  1230.         pm = b(fc, fr) '                                             piece to move
  1231.         p = pm + (pm > 6) * 6
  1232.         tc = INSTR(alpha$, LEFT$(ts$, 1)) '                          to column
  1233.         tr = VAL(RIGHT$(ts$, 1)) '                                   to row
  1234.         b(tc, tr) = pm '                                             move piece in array
  1235.         b(fc, fr) = 0 '                                              blank old array spot
  1236.         IF real THEN
  1237.             IF b(c, r) = o(c, r) THEN o(c, r) = -1
  1238.             Plotpiece fc, fr, tc, tr
  1239.             IF p = King THEN MID$(castle$, WorB * 2 + 1, 2) = "XX"
  1240.             IF p = Rook THEN
  1241.                 IF WorB THEN
  1242.                     IF (fc = 1) AND (fr = 1) THEN MID$(castle$, 3, 1) = "X"
  1243.                     IF (fc = 1) AND (fr = 8) THEN MID$(castle$, 4, 1) = "X"
  1244.                 ELSE
  1245.                     IF (fc = 8) AND (fr = 1) THEN MID$(castle$, 1, 1) = "X"
  1246.                     IF (fc = 8) AND (fr = 8) THEN MID$(castle$, 2, 1) = "X"
  1247.                 END IF
  1248.             END IF
  1249.         END IF
  1250.         IF (p = Pawn) AND ((tr = 1) OR (tr = 8)) THEN
  1251.             b(tc, tr) = Queen - (pm > 6) * 6 '                       promote to queen
  1252.             IF real THEN Plotpiece tc, tr, tc, tr '                  show queen
  1253.         END IF
  1254.     NEXT pass
  1255.  
  1256. DEFINT A-Z
  1257. FUNCTION OnOff$ (v)
  1258.     OnOff$ = MID$("OFFON ", v * 3 + 1, 3)
  1259.  
  1260. DEFSNG A-Z
  1261. SUB Plasma STATIC
  1262.     TYPE xy
  1263.         x AS SINGLE
  1264.         y AS SINGLE
  1265.         dx AS SINGLE
  1266.         dy AS SINGLE
  1267.     END TYPE
  1268.  
  1269.     IF pinit% = 0 THEN
  1270.         DIM c(360) AS _UNSIGNED LONG, p(10) AS xy, f(10)
  1271.         r = RND: g = RND: b = RND: i% = 0: q = .5
  1272.         FOR n% = 1 TO 5
  1273.             r1 = r: g1 = g: b1 = b
  1274.             DO: r = RND: LOOP UNTIL ABS(r - r1) > q
  1275.             DO: g = RND: LOOP UNTIL ABS(g - g1) > q
  1276.             DO: b = RND: LOOP UNTIL ABS(g - g1) > q
  1277.             FOR m% = 0 TO 17: m1% = 17 - m%
  1278.                 f1 = (m% * r) / 18: f2 = (m% * g) / 18: f3 = (m% * b) / 18: c(i%) = f_pl(f1, f2, f3): i% = i% + 1
  1279.             NEXT
  1280.             FOR m% = 0 TO 17: m1% = 17 - m%
  1281.                 f1 = (m% + m1% * r) / 18: f2 = (m% + m1% * g) / 18: f3 = (m% + m1% * b) / 18: c(i%) = f_pl(f1, f2, f3): i% = i% + 1
  1282.             NEXT
  1283.             FOR m% = 0 TO 17: m1% = 17 - m%
  1284.                 f1 = (m1% + m% * r) / 18: f2 = (m1% + m% * g) / 18: f3 = (m1% + m% * b) / 18: c(i%) = f_pl(f1, f2, f3): i% = i% + 1
  1285.             NEXT
  1286.             FOR m% = 0 TO 17: m1% = 17 - m%
  1287.                 f1 = (m1% * r) / 18: f2 = (m1% * g) / 18: f3 = (m1% * b) / 18: c(i%) = f_pl(f1, f2, f3): i% = i% + 1
  1288.             NEXT
  1289.         NEXT
  1290.  
  1291.         FOR n% = 0 TO 5
  1292.             p(n%).x = RND * xm%: p(n%).y = RND * ym%: p(n%).dx = RND * 2 - 1: p(n%).dy = RND * 2 - 1
  1293.             f(n%) = RND * .1
  1294.         NEXT
  1295.  
  1296.         xm2% = 8 * xq%: ym2% = xm2%: x1% = xc% - 4 * xq%: y1% = yc% - 4 * yq%: x2% = xc% + 4 * xq%: y2% = yc% + 4 * yq%:
  1297.         pinit% = 1
  1298.     END IF
  1299.  
  1300.     FOR n% = 0 TO 5
  1301.         p(n%).x = p(n%).x + p(n%).dx
  1302.         IF p(n%).x > xm2% OR p(n%).x < 0 THEN p(n%).dx = -p(n%).dx
  1303.         p(n%).y = p(n%).y + p(n%).dy
  1304.         IF p(n%).y > ym2% OR p(n%).y < 0 THEN p(n%).dy = -p(n%).dy
  1305.     NEXT
  1306.  
  1307.     IF graphics% = 2 THEN z% = 1 ELSE z% = 2
  1308.  
  1309.     FOR y% = y1% TO y2% STEP z%
  1310.         FOR x% = x1% TO x2% STEP z%
  1311.             p& = POINT(x%, y%)
  1312.             'IF (p& = boardwhite&) OR (p& = boardblack&) THEN
  1313.             IF (p& = boardwhite&) THEN
  1314.                 d = 0
  1315.                 FOR n% = 0 TO 5
  1316.                     dx = x% - p(n%).x: dy = y% - p(n%).y
  1317.                     k = SQR(dx * dx + dy * dy)
  1318.                     d = d + (SIN(k * f(n%)) + 1) / 2
  1319.                 NEXT
  1320.                 PSET (x%, y%), c(d * 60)
  1321.             END IF
  1322.         NEXT
  1323.         '_DELAY .001
  1324.     NEXT
  1325.  
  1326. DEFINT A-Z
  1327. SUB Playagain (t$)
  1328.     Menubox
  1329.     COLOR _RGBA32(222, 222, 222, 255), _RGBA32(1, 1, 1, 0)
  1330.     Center 18, t$, 0
  1331.     IF INSTR("QR", LEFT$(t$, 1)) THEN '                              Quit or Resign
  1332.         Center 20, "Resume    New game     Quit", 1
  1333.         ks$ = "rn"
  1334.     ELSE
  1335.         Center 20, "New game     Quit", 1
  1336.         ks$ = "rn" '                                                 take out r when working properly (false checkmates)
  1337.     END IF
  1338.     _DISPLAY
  1339.     COLOR _RGBA(155, 155, 155, 255), _RGBA32(0, 0, 0, 255)
  1340.  
  1341.     DO: _LIMIT 10
  1342.         i$ = INKEY$
  1343.         IF i$ = "" THEN i$ = " "
  1344.         IF (i$ = Esc$) OR (LCASE$(i$) = "q") THEN SYSTEM
  1345.         IF human = 0 THEN i$ = "n"
  1346.     LOOP UNTIL INSTR(ks$, i$)
  1347.  
  1348. DEFSNG A-Z
  1349. SUB PlaySound (f$) STATIC '         ding,tada,notify,windows xp hardware fail, etc\
  1350.     CONST CACHE = 441 '             minimal detected frequency for analyzer is 100 Hz, so this is enought value (with 44100 biterate)
  1351.     TYPE head
  1352.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  1353.         size AS LONG '              4 bytes  (?E??)
  1354.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  1355.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  1356.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  1357.         format AS STRING * 2 '      2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  1358.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  1359.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  1360.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  1361.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  1362.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  1363.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  1364.     END TYPE '                     40 bytes  total
  1365.     TYPE Wav16S
  1366.         Left AS INTEGER
  1367.         Right AS INTEGER
  1368.     END TYPE
  1369.     REDIM scache(CACHE) AS Wav16S
  1370.     DIM H AS head
  1371.     ch = FREEFILE
  1372.     f$ = f$ + ".wav"
  1373.     IF _FILEEXISTS(f$) = 0 THEN EXIT SUB
  1374.     OPEN f$ FOR BINARY AS #ch
  1375.     GET #ch, , H
  1376.     block = H.Block
  1377.     RATE = H.rate
  1378.     chan = H.channels
  1379.     bits = H.Bits
  1380.     L = _SNDOPENRAW
  1381.     R = _SNDOPENRAW
  1382.     REDIM scache(CACHE) AS Wav16S
  1383.     DO WHILE NOT EOF(ch)
  1384.         GET #ch, , scache()
  1385.         FOR P = 0 TO CACHE
  1386.             lef = scache(P).Left
  1387.             IF chan = 1 THEN righ = lef ELSE righ = scache(P).Right
  1388.             lef = lef / RATE
  1389.             righ = righ / RATE
  1390.             IF RATE > 44100 THEN frekvence = RATE ELSE frekvence = 44100
  1391.             FOR plll = 1 TO frekvence / RATE
  1392.                 _SNDRAW lef, L
  1393.                 _SNDRAW righ, R
  1394.             NEXT plll
  1395.         NEXT
  1396.     LOOP
  1397.     CLOSE ch
  1398.  
  1399. DEFINT A-Z
  1400. SUB PlotBoard
  1401.     FOR zr = 1 TO 8
  1402.         FOR zc = 1 TO 8
  1403.             IF rflag = 0 THEN Plotpiece zc, zr, zc, zr
  1404.         NEXT zc
  1405.     NEXT zr
  1406.  
  1407. SUB Plotpiece (fc, fr, tc, tr)
  1408.     x1 = xc + (fc - 5) * xq
  1409.     x2 = xc + (tc - 5) * xq
  1410.     y1 = yc + (4 - fr) * yq
  1411.     y2 = yc + (4 - tr) * yq
  1412.     p = b(tc, tr)
  1413.     IF invert THEN p = b(9 - tc, 9 - tr)
  1414.     IF p > 6 THEN wb = 1: p = p - 6
  1415.     i = p - (wb = 0) * 6
  1416.  
  1417.     FOR ps = 0 TO 1
  1418.         IF ps = 0 THEN
  1419.             c = fr + fc: tx = x1: ty = y1
  1420.         ELSE
  1421.             c = tr + tc: tx = x2: ty = y2
  1422.         END IF
  1423.         IF c MOD 2 THEN
  1424.             LINE (tx, ty)-(tx + xq, ty + yq), boardwhite&, BF
  1425.         ELSE
  1426.             LINE (tx, ty)-(tx + xq, ty + yq), boardblack&, BF '      black square
  1427.             LINE (tx, ty)-(tx + xq, ty + yq), boardwhite&, B '       border
  1428.         END IF
  1429.     NEXT ps
  1430.  
  1431.     FOR t = 1 TO c(p, 0)
  1432.         tx = x1 + x(p, t) * 2
  1433.         ty = y1 + y(p, t) * 2
  1434.         LINE (tx, ty)-STEP(1, 1), cp&(c(i, t)), B
  1435.     NEXT t
  1436.  
  1437. SUB PlotScreen (lflag) STATIC
  1438.     PlotBoard
  1439.     TextInfo ""
  1440.     r = _RED32(boardwhite&) \ 2 '                                    legend, dim a-h, 1-8 along sides
  1441.     g = _GREEN32(boardwhite&) \ 2
  1442.     b = _BLUE32(boardwhite&) \ 2
  1443.     COLOR _RGB32(r, g, b)
  1444.     FOR i = 1 TO 8
  1445.         IF invert THEN z = i ELSE z = 9 - i
  1446.         n$ = LTRIM$(STR$(z))
  1447.         IF invert THEN z = 9 - i ELSE z = i
  1448.         a$ = alphal$(z)
  1449.         nx = xc - 4 * xq - 12
  1450.         ny = yc + (i - 4) * yq - 34
  1451.         ax = xc + (i - 5) * xq + 22
  1452.         ay = yc + 4 * yq + 3
  1453.         _PRINTSTRING (nx, ny), n$
  1454.         _PRINTSTRING (ax, ay), a$
  1455.     NEXT i
  1456.     COLOR white&
  1457.  
  1458.     IF lflag THEN Center 0, "", 1
  1459.  
  1460.     IF graphics = 0 THEN EXIT SUB
  1461.     IF graphics > 1 THEN
  1462.         Plasma
  1463.         EXIT SUB
  1464.     END IF
  1465.  
  1466.     br = 255
  1467.     zz = (zz + 1) MOD 50: IF zz = 1 THEN r! = RND: g! = RND: b! = RND
  1468.     x1 = xc - 4 * xq
  1469.     y1 = yc - 4 * yq
  1470.     x2 = x1 + 8 * xq
  1471.     y2 = y1 + 8 * yq
  1472.     FOR sy = y1 TO y2
  1473.         FOR sx = x1 TO x2
  1474.             p& = POINT(sx, sy)
  1475.             IF p& = boardwhite& THEN
  1476.                 z = ABS((sx - xc - xq \ 2) * (sy - yc - yq \ 2))
  1477.                 PSET (sx, sy), _RGB32(br * SIN(.1 * r! * z + zz), br * SIN(.155 * g! * z + zz), br * SIN(2 * b! * z + zz))
  1478.             END IF
  1479.     NEXT sx: NEXT sy
  1480.  
  1481. SUB ReadGame
  1482.     DIM g$(500)
  1483.     CLS
  1484.     OPEN GameFile$ FOR INPUT AS #8
  1485.     WHILE NOT (EOF(8))
  1486.         INPUT #8, mn, m1$, m2$
  1487.         gm = gm + 1: g$(gm) = LTRIM$(m1$)
  1488.         gm = gm + 1: g$(gm) = LTRIM$(m2$)
  1489.         PRINT m1$; "*"; m2$
  1490.     WEND
  1491.     CLOSE #8
  1492.     _DISPLAY
  1493.     SLEEP
  1494.     CLS
  1495.     _DISPLAY
  1496.  
  1497. SUB Recurse (Level)
  1498.     IF abort OR (Level = MasterLevel) THEN EXIT SUB
  1499.     FOR t = 1 TO Moves(Level - 1)
  1500.  
  1501.         IF Level = 1 THEN '                                                              progress bar
  1502.             x1 = xc - 4 * xq: x2 = xc + 4 * xq
  1503.             y1 = yc + 4 * yq + 20
  1504.             z1 = Moves(Level - 1): z2 = z1 - (z1 = 0)
  1505.             xx = (z1 - t + 1) / z2 * (x2 - x1)
  1506.             IF xx < x1 THEN xx = x1
  1507.             IF xx > x2 THEN xx = x2
  1508.             LINE (x1, y1)-(x2, y1), black&
  1509.             IF (xx - x1) > 2 THEN LINE (x1, y1)-(xx, y1), cp&(1)
  1510.  
  1511.             'x1 = 290: x2 = x1 + 50
  1512.             'y1 = 508: y2 = y1 + 64
  1513.             'LINE (x1, y1)-(x2, y2), _RGB32(222, 0, 0), B
  1514.  
  1515.         END IF
  1516.  
  1517.         WorB = SaveWorB
  1518.         IF (Level MOD 2) = 1 THEN WorB = WorB XOR 1
  1519.         TieTo(Level) = t
  1520.         IF ABS(Score(0, t)) <> 777 THEN
  1521.             _MEMCOPY m(0), m(0).OFFSET, m(0).SIZE TO m(Level), m(Level).OFFSET '         save board
  1522.             m$ = Move$(Level - 1, t)
  1523.             MoveIt m$, false
  1524.             lm1 = Level - 1
  1525.             CheckBoard Level
  1526.             Recurse Level + 1
  1527.             TakeBest Level, false
  1528.             i = Index
  1529.             Score = Score(Level, 1)
  1530.             levm1 = Level - 1
  1531.             IF Score(levm1, 1) <> 777 THEN Score(levm1, i) = Score(levm1, i) - Score
  1532.             IF Level = (MasterLevel - 1) THEN
  1533.                 KeyScan 0, 0 '                                                           no plotscreen or _display
  1534.                 'IF (tlimit > 0) AND (emin >= tlimit) THEN abort = true
  1535.                 IF abort THEN EXIT SUB
  1536.                 IF smode = 2 THEN LogThinking
  1537.             END IF
  1538.             _MEMCOPY m(Level), m(Level).OFFSET, m(Level).SIZE TO m(0), m(0).OFFSET '     restore board
  1539.         END IF
  1540.     NEXT t
  1541.  
  1542. SUB Reset_To_Zero
  1543.     WorB = WorB XOR 1 '      reverse who's moving
  1544.     CheckBoard 1 '           need to know what opponent can do to ensre legal castling
  1545.     WorB = WorB XOR 1 '      restore playing color
  1546.     CheckBoard 0 '           determine legal moves
  1547.  
  1548. FUNCTION Rjust$ (t, n)
  1549.     Rjust$ = RIGHT$("   " + STR$(t), n)
  1550.  
  1551. SUB SaveForTakeBack STATIC '                                         use MEM later to move arrays
  1552.     FOR i = 10 TO 1 STEP -1
  1553.         castle$(i) = castle$(i - 1)
  1554.         FOR r = 1 TO 8
  1555.             FOR c = 1 TO 8
  1556.                 tb(c, r, i) = tb(c, r, i - 1)
  1557.             NEXT c
  1558.         NEXT r
  1559.     NEXT i
  1560.     castle$(0) = castle$
  1561.     FOR r = 1 TO 8
  1562.         FOR c = 1 TO 8
  1563.             tb(c, r, 0) = b(c, r)
  1564.         NEXT c
  1565.     NEXT r
  1566.     tbc = tbc + 1
  1567.     IF tbc > 10 THEN tbc = 10
  1568.  
  1569.  
  1570. SUB ScreenInit
  1571.     xm = 480: ym = 600
  1572.     MaxRow = ym \ 16 - 2
  1573.     k = 99
  1574.     SELECT CASE smode
  1575.         CASE IS = 0
  1576.             SCREEN _NEWIMAGE(xm, ym), 32
  1577.             _SCREENMOVE _DESKTOPWIDTH \ 2 - xm \ 2, _DESKTOPHEIGHT \ 2 - ym \ 2
  1578.         CASE IS = 1
  1579.             _SCREENMOVE 780, 20
  1580.         CASE IS = 2
  1581.             SCREEN _NEWIMAGE(800, 600), 32
  1582.             _SCREENMOVE 472, 20
  1583.     END SELECT
  1584.  
  1585. SUB Setup
  1586.     t1$ = "rnbkqp:black      clear:one     spacebar:flip"
  1587.     t2$ = "RNBKQP:white      Clear:all          Esc:exit"
  1588.  
  1589.     LINE (0, 500)-(xm, ym), black&, BF
  1590.     cc = 1: rr = 8
  1591.     DO
  1592.         Center -1, t1$, 0
  1593.         Center 0, t2$, 0
  1594.         _DISPLAY
  1595.         DO: _LIMIT 20
  1596.             PlotBoard
  1597.             z = z XOR 1
  1598.             IF z THEN Cursor 9 - rr, cc, 0
  1599.             i$ = INKEY$: z = LEN(i$)
  1600.         LOOP UNTIL z
  1601.         SELECT CASE z
  1602.             CASE IS = 1
  1603.                 r2 = 9 - rr
  1604.                 IF i$ = Esc$ THEN EXIT DO
  1605.                 IF (i$ = CHR$(9)) OR (i$ = "c") THEN b(cc, r2) = 0 ' Del or "c" to delete piece
  1606.                 IF i$ = "C" THEN '                                   delete all pieces
  1607.                     FOR c = 1 TO 8: FOR r = 1 TO 8
  1608.                             b(c, r) = 0
  1609.                     NEXT: NEXT
  1610.                 END IF
  1611.                 p = INSTR("rnbqkpRNBQKP", i$)
  1612.                 IF p THEN b(cc, r2) = p '                            set piece by letter
  1613.                 IF INSTR(" t", i$) THEN '                            t or space toggle color
  1614.                     mp = b(cc, r2)
  1615.                     IF mp < 7 THEN mp = mp + 6 ELSE mp = mp - 6
  1616.                     b(cc, r2) = mp
  1617.                 END IF
  1618.                 IF i$ = "x" THEN
  1619.                     FOR c = 1 TO 8
  1620.                         FOR r = 1 TO 8
  1621.                             t = b(c, r)
  1622.                             IF t THEN
  1623.                                 IF t < 7 THEN t = t + 6 ELSE t = t - 6
  1624.                                 s9(c, r) = t
  1625.                             END IF
  1626.                         NEXT r
  1627.                     NEXT c
  1628.                     FOR c = 1 TO 8
  1629.                         FOR r = 1 TO 8
  1630.                             b(c, 9 - r) = s9(c, r)
  1631.                         NEXT r
  1632.                     NEXT c
  1633.                 END IF
  1634.                 IF i$ = "z" THEN
  1635.                     RESTORE test
  1636.                     FOR r = 1 TO 8
  1637.                         FOR c = 1 TO 8
  1638.                             READ b(c, r)
  1639.                     NEXT: NEXT
  1640.                 END IF
  1641.             CASE IS = 2
  1642.                 kk = ASC(RIGHT$(i$, 1))
  1643.                 cc = cc + (kk = 75) - (kk = 77) '                    left right
  1644.                 rr = rr + (kk = 72) - (kk = 80) '                    up down
  1645.                 IF rr < 1 THEN rr = 1
  1646.                 IF rr > 8 THEN rr = 8
  1647.                 IF cc < 1 THEN cc = 1
  1648.                 IF cc > 8 THEN cc = 8
  1649.         END SELECT
  1650.     LOOP
  1651.     LINE (0, 500)-(xm, ym), black&, BF
  1652.     '                        board probably changed - reinitialize legal moves
  1653.     Reset_To_Zero
  1654.  
  1655. SUB ShowBest
  1656.     yy = 505
  1657.     ty = yy
  1658.     tx = 24
  1659.     FOR t = 1 TO 15
  1660.         IF t <= Moves(0) THEN
  1661.             t$ = Make4$(Move$(0, t)) + Rjust$(Score(0, t), 5)
  1662.             FOR i = 1 TO LEN(t$) '                                   shift "g" up 2 pixels
  1663.                 c$ = MID$(t$, i, 1)
  1664.                 y2 = ty + (c$ = "g") * 2
  1665.                 _PRINTSTRING (tx + (i - 1) * 8, y2), c$
  1666.             NEXT
  1667.         END IF
  1668.         ty = ty + 14
  1669.         IF ty > 570 THEN ty = yy: tx = tx + 80
  1670.     NEXT t
  1671.  
  1672. SUB ShowMe (dr, dc, t$)
  1673.     EXIT SUB
  1674.     sr = CSRLIN '                                                    save row
  1675.     sc = POS(0) '                                                    save column
  1676.     IF (dr > 0) AND (dr < MaxRow) AND (dc > 0) AND (dc < 76) THEN
  1677.         LOCATE dr, dc '                                              display row & column
  1678.         PRINT t$;
  1679.     END IF
  1680.     LOCATE sr, sc '                                                  restore to old location
  1681.  
  1682. SUB ShowTime (trow, z!, Desc$)
  1683.     t! = z!
  1684.     SELECT CASE t!
  1685.         CASE IS > 3600
  1686.             unit$ = "h"
  1687.             t! = t! / 3600
  1688.         CASE IS > 60
  1689.             unit$ = "m"
  1690.             t! = t! / 60
  1691.         CASE ELSE
  1692.             unit$ = "s"
  1693.     END SELECT
  1694.     x1 = 414
  1695.     x2 = x1 - (LEN(Desc$) + 1) * 8
  1696.     yy = trow / (600 / 16) * 600 - 4
  1697.     t! = INT(t! * 1000) / 1000
  1698.     t$ = LTRIM$(STR$(t!))
  1699.     IF INSTR(t$, ".") = 0 THEN
  1700.         IF t! < 1 THEN t$ = "." + t$ ELSE t$ = t$ + "."
  1701.     END IF
  1702.     zz = 0
  1703.     WHILE INSTR(t$, ".") <> (LEN(t$) - 3)
  1704.         t$ = t$ + "0"
  1705.         zz = zz + 1
  1706.         IF zz > 5 THEN GOTO dammit
  1707.     WEND
  1708.     dammit:
  1709.  
  1710.     IF LEFT$(t$, 1) = "." THEN t$ = "0" + t$
  1711.     t$ = RIGHT$(SPACE$(10) + t$, 6)
  1712.     _PRINTSTRING (x1, yy), t$ + unit$
  1713.     _PRINTSTRING (x2, yy), Desc$
  1714.  
  1715. SUB ShowValid (cc, rr) '                                             show valid moves for piece at cursor
  1716.  
  1717.     IF (cc < 0) OR (rr < 0) OR (cc > 8) OR (rr > 8) THEN EXIT SUB
  1718.     tc = cc: tr = rr
  1719.     IF invert THEN tc = 9 - tc: tr = 9 - tr
  1720.     mp = b(tc, tr): mp = mp + (mp > 6) * 6
  1721.     z$ = alphal$(tc) + LTRIM$(STR$(9 - tr))
  1722.     t$ = z$ + ":"
  1723.     FOR i = 1 TO Moves(0)
  1724.         IF z$ = LEFT$(Move$(0, i), 2) THEN t$ = t$ + " " + RIGHT$(Move$(0, i), 2)
  1725.         IF (mp = King) AND (LEFT$(Move$(0, i), 1) = "O") THEN t$ = t$ + " " + Move$(0, i)
  1726.     NEXT i
  1727.     'IF (tc = epfc) AND (tr = epfc) THEN t$ = t$ + " ep"
  1728.  
  1729.     sw = _WIDTH \ 8 - 3
  1730.     LOCATE 2, 4: PRINT SPACE$(sw);
  1731.     LOCATE 2, 4: PRINT LEFT$(t$, sw);
  1732.     IF LEN(t$) > sw THEN PRINT "..";
  1733.  
  1734.  
  1735. SUB TakeBack '                                                       use MEM to move arrays? speed not an issue here
  1736.     IF tbc < 2 THEN EXIT SUB
  1737.     IF MakeNoise THEN PlaySound "tb" '                               so your mom knows you're cheating  :)
  1738.     castle$ = castle$(2)
  1739.     FOR r = 1 TO 8
  1740.         FOR c = 1 TO 8
  1741.             b(c, r) = tb(c, r, 2)
  1742.         NEXT c
  1743.     NEXT r
  1744.     FOR i = 0 TO 9
  1745.         castle$(i) = castle$(i + 1)
  1746.         FOR r = 1 TO 8
  1747.             FOR c = 1 TO 8
  1748.                 tb(c, r, i) = tb(c, r, i + 1)
  1749.             NEXT c
  1750.         NEXT r
  1751.     NEXT i
  1752.     tbc = tbc - 1
  1753.     Reset_To_Zero
  1754.  
  1755. SUB TakeBest (Level, final)
  1756.  
  1757.     IF final THEN '                                                  feeble attempt to vary response when scores equal
  1758.         upto = 10
  1759.         IF upto > Moves(Level) THEN upto = Moves(Level)
  1760.         FOR scram = 0 TO 199
  1761.             s1 = RND * updo + 1
  1762.             s2 = RND * upto + 1
  1763.             SWAP Score(Level, s1), Score(Level, s2)
  1764.             SWAP Move$(Level, s1), Move$(Level, s2)
  1765.             SWAP Index(Level, s1), Index(Level, s2)
  1766.         NEXT scram
  1767.     END IF
  1768.  
  1769.     passes = 0
  1770.     ReSort:
  1771.     Score = -999 '                                                   assume no moves
  1772.     DO
  1773.         Sorted = true
  1774.         FOR s = 2 TO Moves(Level)
  1775.             IF Score(Level, s - 1) < Score(Level, s) THEN
  1776.                 Sorted = false
  1777.                 SWAP Score(Level, s - 1), Score(Level, s)
  1778.                 SWAP Move$(Level, s - 1), Move$(Level, s)
  1779.                 SWAP Index(Level, s - 1), Index(Level, s)
  1780.             END IF
  1781.         NEXT s
  1782.     LOOP UNTIL Sorted
  1783.  
  1784.     m$ = Move$(Level, 1)
  1785.     Score = Score(Level, 1)
  1786.     Index = Index(Level, 1)
  1787.  
  1788.     IF final AND (Level < 2) THEN
  1789.         IF Score = -777 THEN '                                       in check, no escape
  1790.             abort = 3: msg$ = "Checkmate!"
  1791.         ELSEIF Score = -999 THEN '                                   no moves
  1792.             abort = 3: msg$ = "Stalemate!"
  1793.         END IF
  1794.  
  1795.         tm = Moves(1)
  1796.         FOR lb = 1 TO 9 '                                            stop repeats
  1797.             IF tm > 8 THEN
  1798.                 IF INSTR(MoveLog$(tm - lb), m$) THEN
  1799.                     'SOUND 888, 1
  1800.                     Score(1, 1) = Score(1, 1) - 10
  1801.                     passes = passes + 1
  1802.                     IF passes < 5 THEN GOTO ReSort '                 repeat may be only move
  1803.                 END IF
  1804.             END IF
  1805.         NEXT lb
  1806.     END IF
  1807.  
  1808.     IF (Level = 1) AND (Score = 777) THEN Score(0, TieTo(1)) = -777
  1809.  
  1810. SUB TextInfo (zz$)
  1811.     IF smode <> 2 THEN EXIT SUB
  1812.  
  1813.     t$ = "History Thinking Legal Protection"
  1814.     LOCATE 3, 61
  1815.     FOR i = 1 TO LEN(t$)
  1816.         c$ = MID$(t$, i, 1)
  1817.         IF c$ = UCASE$(c$) THEN COLOR cp&(1) ELSE COLOR white&
  1818.         PRINT c$;
  1819.     NEXT
  1820.     COLOR white&
  1821.  
  1822.     'LOCATE 1, 4: PRINT showthink; history; showlegalf; showprotf;
  1823.  
  1824.     z = 0
  1825.     IF showthink THEN z = 1
  1826.     IF history THEN z = 2
  1827.     IF showlegalf THEN z = 3
  1828.     IF showprotf THEN z = 4
  1829.     IF z = 0 THEN EXIT SUB
  1830.  
  1831.     IF DebugR > MaxRow THEN
  1832.         _DISPLAY
  1833.         DebugR = 3: DebugC = 61
  1834.         FOR r = DebugR TO MaxRow
  1835.             LOCATE r, DebugC
  1836.             PRINT SPACE$(100 - DebugC);
  1837.         NEXT r
  1838.     END IF
  1839.  
  1840.     SELECT CASE z
  1841.         CASE IS = 1
  1842.             DebugR = DebugR + 1
  1843.             LOCATE DebugR, DebugC
  1844.             PRINT zz$;
  1845.             IF DebugR = MaxRow THEN DebugR = 99
  1846.         CASE IS = 2
  1847.             BeginAt = Move - 28
  1848.             IF BeginAt < 1 THEN BeginAt = 1
  1849.             tr = 4
  1850.             FOR i = BeginAt TO Move
  1851.                 LOCATE tr, DebugC
  1852.                 PRINT MoveLog$(i);
  1853.                 tr = tr + 1
  1854.                 IF tr > MaxRow THEN EXIT FOR
  1855.             NEXT i
  1856.         CASE IS = 3
  1857.             FOR i = 1 TO Moves(0)
  1858.                 tr = i + 3
  1859.                 IF tr > MaxRow THEN EXIT FOR
  1860.                 LOCATE tr, 63
  1861.                 PRINT USING "## "; i;
  1862.                 PRINT Move$(0, i);
  1863.             NEXT i
  1864.             FOR i = 1 TO Moves(1)
  1865.                 tr = i + 3
  1866.                 IF tr > MaxRow THEN EXIT FOR
  1867.                 LOCATE tr, 73
  1868.                 PRINT USING "## "; i;
  1869.                 PRINT Move$(1, i);
  1870.             NEXT i
  1871.         CASE IS = 4
  1872.             FOR i = 1 TO prot(0)
  1873.                 tr = i + 3
  1874.                 IF tr > MaxRow THEN EXIT FOR
  1875.                 LOCATE tr, 63
  1876.                 PRINT USING "## "; i;
  1877.                 PRINT prot$(0, i);
  1878.             NEXT i
  1879.             FOR i = 1 TO prot(1)
  1880.                 tr = i + 3
  1881.                 IF tr > MaxRow THEN EXIT FOR
  1882.                 LOCATE tr, 73
  1883.                 PRINT USING "## "; i;
  1884.                 PRINT prot$(1, i);
  1885.             NEXT i
  1886.     END SELECT
  1887.  
  1888. SUB TryMove (Level, fc, fr, mp, mc) '                                from row, from column
  1889.     IF mc = 1 THEN s = -1 ELSE s = 1 '                               direction a pawn moves
  1890.     incheck = (mc = SaveWorB) AND check
  1891.  
  1892.     '                  rnbqkp
  1893.     nmoves = VAL(MID$("373772", mp, 1))
  1894.  
  1895.     FOR n = 0 TO nmoves '                                            possible 8 dirs
  1896.         du = du(mp, n): dd = dd(mp, n): dl = dl(mp, n): dr = dr(mp, n)
  1897.         IF mp <> Knight THEN du = SGN(du) * s: dd = SGN(dd) * s: dl = SGN(dl) * s: dr = SGN(dr) * s
  1898.         IF du(mp, 0) = 7 THEN TrySq = 7 ELSE TrySq = 1
  1899.         IF (mp = Pawn) AND (n = 0) THEN '                            pawn first move?
  1900.             IF (fr = 2) AND (WorB = 1) THEN TrySq = 2 '              gambit for white
  1901.             IF (fr = 7) AND (WorB = 0) THEN TrySq = 2 '              gambit for black
  1902.         END IF
  1903.         tc = fc: tr = fr '                                           row, column
  1904.         fs$ = alphal$(fc) + CHR$(48 + fr) '                          from square
  1905.         cap = false
  1906.         FOR sq = 1 TO TrySq '                                        up to 7 steps in current direction
  1907.             Score = 0 '                                              must init
  1908.             tc = tc - dl + dr '                                      column=column-left+right
  1909.             tr = tr - du + dd '                                      row=row-up+down
  1910.             IF (tr < 1) OR (tr > 8) OR (tc < 1) OR (tc > 8) THEN EXIT FOR
  1911.             ts$ = alphal$(tc) + CHR$(48 + tr) '                      to square
  1912.             IF fs$ = ts$ THEN SYSTEM
  1913.             cp = b(tc, tr) '                                         capture piece
  1914.             cc = -(cp > 6) - (cp = 0) * 2 '                          capture color
  1915.             cp = cp + (cp > 6) * 6
  1916.             IF mc = cc THEN '                                        own piece
  1917.                 prot(Level) = prot(Level) + 1
  1918.                 IF prot(Level) < q1 THEN prot$(Level, prot(Level)) = fs$ + ts$
  1919.                 IF (mp = Pawn) AND (n = 0) THEN EXIT FOR
  1920.                 IF mp = Knight THEN GOTO nsquare ELSE EXIT FOR
  1921.             ELSEIF (mc XOR 1) = cc THEN '                            capture
  1922.                 IF (mp = Pawn) AND (n = 0) THEN EXIT FOR '           no diag, no cap!
  1923.                 cap = true
  1924.                 Score = Score + value(cp) * 10
  1925.                 IF value(cp) = 0 THEN Score = 777 '                  king capture
  1926.             ELSE
  1927.                 IF (mp = Pawn) AND (n > 0) THEN EXIT FOR
  1928.             END IF
  1929.  
  1930.             IF mp = King THEN
  1931.                 IF Level = 0 THEN lm = 1 ELSE lm = 0 '               wonka
  1932.                 'FOR i = 1 TO Moves(lm) '                            can any opponent piece move there?
  1933.                 '    s$ = RIGHT$(Move$(lm, i), 2)
  1934.                 'IF ts$ = s$ THEN GOTO nsquare '                     would be moving into check
  1935.                 'NEXT
  1936.                 FOR i = 1 TO prot(lm) '                              opponent piece protecting?
  1937.                     s$ = RIGHT$(prot$(lm, i), 2)
  1938.                     IF ts$ = s$ THEN GOTO nsquare '                  would be moving into check
  1939.                 NEXT
  1940.                 IF incheck THEN
  1941.                     Score = Score + 20
  1942.                 ELSE
  1943.                     IF Move < 30 THEN Score = Score - 4 '            usually not good to be moving the King
  1944.                 END IF
  1945.             ELSE
  1946.                 dis1 = ABS(fr - okr) + ABS(fc - okc) '               get closer to king
  1947.                 dis2 = ABS(tr - okr) + ABS(tc - okc)
  1948.                 Score = Score + dis1 - dis2
  1949.                 IF Move < 20 THEN
  1950.                     dir = SGN((fr - tr) * s)
  1951.                     IF dir = 1 THEN Score = Score + 2 '              move ahead at begin & mid game
  1952.                 END IF
  1953.  
  1954.                 ' priority to getting a piece off the bottom rank
  1955.                 IF (fr = 1) AND (tr > 1) AND (WorB = 1) THEN Score = Score + 1
  1956.                 IF (fr = 8) AND (tf < 8) AND (WorB = 0) THEN Score = Score + 1
  1957.                 IF mp <> Rook THEN '                                 priority to getting a piece first moved
  1958.                     IF b(fc, fr) = o(fc, fr) THEN Score = Score + 1
  1959.                 END IF
  1960.             END IF
  1961.             's1 = Score
  1962.  
  1963.             'IF (Score <> 777) AND (NOT (incheck)) THEN
  1964.  
  1965.             IF mp = Pawn THEN
  1966.                 Score = Score + TrySq
  1967.                 IF (tr = 1) OR (tr = 8) THEN '                       promote pawn
  1968.                     Score = Score + 99
  1969.                 END IF
  1970.             END IF
  1971.             'END IF
  1972.             'IF s1 = 777 THEN Score = s1
  1973.  
  1974.             AddIt Level, fs$ + ts$, Score
  1975.  
  1976.             IF cap AND (mp = Pawn) AND (n = 0) THEN EXIT FOR
  1977.             IF cap AND (mp <> Knight) THEN EXIT FOR
  1978.             nsquare:
  1979.         NEXT sq
  1980.     NEXT n
  1981.  
  1982.     IF mp = Pawn THEN '                                              en passant
  1983.         IF WorB THEN othp = 6 ELSE othp = 12 '                       opponent pawn
  1984.         l1 = 7 + (WorB = 0) * 5 '                                    rank 7 for white, 2 for black
  1985.         l2 = 5 - (WorB = 0) '                                        rank 5 for white, 6 for black
  1986.     END IF
  1987.     IF (mp = Pawn) AND (fr = l2) AND (Level < 2) THEN
  1988.         FOR z = -1 TO 1 STEP 2 '                                     look each side
  1989.             lc = fc + z '                                            look column
  1990.             IF (lc > 0) AND (lc < 9) THEN '                          in bounds of board
  1991.                 IF b(lc, fr) = othp THEN '                           it is a pawn
  1992.                     tc$ = alphal$(lc)
  1993.                     tm$ = tc$ + CHR$(48 + l1) + tc$ + CHR$(48 + l2) '  form coordinate
  1994.                     IF tm$ = lm$ THEN '                              yes, add e.p. to list of legal moves
  1995.                         epfc = fc: epfr = fr '                       en passant from row, column
  1996.                         eptc = lc: eptr = fr - s '                   en passant to row, column
  1997.                         eprc = lc: eprr = fr '                       en passant remove piece
  1998.                         ep$ = alphal$(epfc) + CHR$(48 + epfr) + alphal$(eptc) + CHR$(48 + eptr)
  1999.                         AddIt Level, ep$, 1 '                        add with score of 1
  2000.                     END IF
  2001.                 END IF
  2002.             END IF
  2003.         NEXT z
  2004.     END IF
  2005.  
  2006.  
  2007. SUB TempMess (t$, secs) STATIC
  2008.     'EXIT SUB
  2009.     zz = 100: x1 = xc - zz: x2 = xc + zz
  2010.     IF (LEN(t$) > 0) AND (t$ <> current$) THEN
  2011.         x = xc - LEN(t$) * 4
  2012.         y = 12
  2013.         LINE (x1, 0)-(x2, 28), black&, BF
  2014.         _PRINTSTRING (x, y), t$
  2015.         _DISPLAY
  2016.         current$ = t$
  2017.         mtime! = TIMER + secs
  2018.     END IF
  2019.     IF (mtime! > 0) AND (TIMER > mtime!) THEN
  2020.         LINE (x1, 0)-(x2, 28), black&, BF
  2021.         _DISPLAY
  2022.         mtime! = 0
  2023.     END IF
  2024.  
  2025.  
Title: Re: A 90% complete chess engine
Post by: TempodiBasic on March 01, 2020, 10:17:34 am
Sorry Richard I have been not able to try and see your new release of your chess.bas because it doesn't run well, it starts with a console window that close itself quickly lasting a void file named Ch00000X.alg where X is a progressive number in each call to the exe.
Title: Re: A 90% complete chess engine
Post by: TempodiBasic on March 01, 2020, 10:43:40 am
Ah! I look into your code and I can see that after the Ch0000X.alg file you load the images for the program!
So I download again also the old images posted before in this thread.
nothing ..... I get the same... let's see better...

Yes I can see that now you load chess.pgn and not chess3.pgn as previous filename of chess.
Ok now it runs!
See later !
Title: Re: A 90% complete chess engine
Post by: Richard Frost on March 01, 2020, 11:11:44 am
Sorry for the filename change.  Rather silly of me.  I should stop uploading
stuff at the end of the day when my brain is fried.   

Also, the external files aren't really necessary and I should enable the program
to run without them.  Changing the icon is how I alert the user it's their move
(even with sound turned off).  Alfred is a bit 'o fun - shows up as the cursor when
an illegal move is attempted.
Title: Re: A 90% complete chess engine
Post by: Richard Frost on March 01, 2020, 11:51:03 am
O-tay, this is the current version, and the external files are ALL optional now,
and checked to see if they exist in upper or lower case.

Code: QB64: [Select]
  1. _TITLE "Chess"
  2. DEFINT A-Z
  3. CONST true = -1, false = 0, Rook = 1, Knight = 2, Bishop = 3, Queen = 4, King = 5, Pawn = 6
  4. ' sort these alphabetically and document them, dummy
  5. COMMON SHARED WorB, Move, Score, Index, opening, invert, i$, m$, lm$, msg$, abort, MaxRow, xq, yq, xc, yc, xm, ym, castle$, OtherK$
  6. COMMON SHARED mkr, mkc, okr, okc, k$, MasterLevel, MasterLevel1, SaveWorB, GameFile$, check, incheck, debug, DebugR, DebugC, Start1!, Start2!
  7. COMMON SHARED MaxElapse!, human, humanc, OnAuto, graphics, rflag, tlimit, boardwhite&, boardblack&, black&, red&, green&, blue&, white&, gray&
  8. COMMON SHARED Enter$, Esc$, lf$, crlf$, debug$, pinit, takebackflag, tbc, waitflag, pause, cursoron!, quitflag, smode, vflag, MakeNoise
  9. COMMON SHARED bri, hold!, dtime!, mtime!, altblack, epfc, epfr, eptc, eptr, eprc, eprr, best, best$, ep$, rick, lcount&, alpha$, ocount&
  10. COMMON SHARED iflag, showthink, history, showlegalf, showprotf, bscore, maxtime&, l, p, b, q1, q2, emin, useidiot, main&, alfred!
  11. COMMON SHARED fg0&, bg0&, bg1&, bg2&
  12. l = 10: p = 6: b = 8: q1 = 300: q2 = 500
  13. DIM SHARED b(b, b), t(b, b, l), o(b, b), tb(b, b, 10), castle$(l), Moves(l), Move$(l, q1), Score(l, q1), TieTo(l), Index(l, q1), prot(l), prot$(l, q1)
  14. DIM SHARED x(p, q2), y(p, q2), c(12, q2), MoveLog$(q2), cp&(32), etime!(3), myr(32), myg(32), myb(32), icon&(10), mcount&(10), du(p, 7), dd(p, 7)
  15. DIM SHARED dl(p, 7), dr(p, 7), value(p), alphal$(8), abuff(30000), s1(b, b), s2(b, b), s3(b, b), s4(b, b), s5(b, b), s9(b, b)
  16. m(0) = _MEM(b(0, 0))
  17. m(1) = _MEM(s1(0, 0)): m(2) = _MEM(s2(0, 0)): m(3) = _MEM(s3(0, 0)): m(4) = _MEM(s4(0, 0)): m(5) = _MEM(s5(0, 0)): m(9) = _MEM(s9(0, 0))
  18.  
  19. rick = _FILEEXISTS("rick.")
  20. MasterLevel1 = VAL(COMMAND$) '                                       only 4 really tested....2 is plenty stupid, odds not tested!
  21. IF MasterLevel1 = 0 THEN MasterLevel1 = 4
  22.  
  23. begin:
  24. Init
  25. OPEN "chess.txt" FOR OUTPUT AS #2
  26.     IF icon&(1) <> 0 THEN _ICON icon&(1) '                           chess.png
  27.     SaveWorB = WorB
  28.  
  29.     mking = 5: oking = 11
  30.     IF humanc = 0 THEN SWAP mking, oking
  31.     FOR r = 1 TO 8
  32.         FOR c = 1 TO 8
  33.             IF b(c, r) = mking THEN mkr = r: mkc = c
  34.             IF b(c, r) = oking THEN okr = r: okc = c
  35.         NEXT c
  36.     NEXT r
  37.     ks$ = alphal$(mkc) + CHR$(48 + mkr)
  38.  
  39.     IF WorB = humanc THEN SaveForTakeBack
  40.  
  41.     redo:
  42.     Reset_To_Zero
  43.     IF Moves(0) = 0 THEN msg$ = "Stalemate": GOTO yoyo
  44.     Start1! = TIMER: Start2! = Start1!
  45.     DebugR = 99
  46.  
  47.     IF human AND (humanc = WorB) OR (human = 2) THEN '               2 is two humans
  48.         IF (iflag = 0) AND (human = 2) THEN invert = -(WorB = 0)
  49.         DO
  50.             pinit = 0 '                                              nudge for the graphics, vary it a little
  51.             _MOUSESHOW
  52.             HumanMove '                                              get a move
  53.             _MOUSEHIDE
  54.             IF LEN(msg$) THEN GOTO yoyo
  55.             IF takebackflag THEN
  56.                 TakeBack '                                           restores board & castling status
  57.                 PlotBoard
  58.                 takebackflag = 0
  59.                 GOTO redo
  60.             END IF
  61.             sm$ = m$
  62.             _MEMCOPY m(0), m(0).OFFSET, m(0).SIZE TO m(9), m(9).OFFSET '         save board
  63.             MoveIt m$, false
  64.             WorB = WorB XOR 1
  65.             CheckBoard 1
  66.             WorB = WorB XOR 1
  67.             m$ = sm$
  68.             _MEMCOPY m(9), m(9).OFFSET, m(9).SIZE TO m(0), m(0).OFFSET '     restore board
  69.             IF Score <> 777 THEN
  70.                 FOR i = 1 TO Moves(0) '                              check against legal list
  71.                     IF m$ = Move$(0, i) THEN EXIT DO '               move found, skip more checking
  72.                 NEXT i
  73.             END IF
  74.             alfred! = TIMER + 5: IF alfred! > maxtime& THEN alfred! = 0
  75.             IF MakeNoise THEN PlaySound "bad"
  76.         LOOP
  77.     ELSE
  78.         abort = false
  79.         DebugR = 99
  80.         rflag = true '                                               flag in recursion to stop displaying board
  81.         bscore = -9999
  82.         Center 0, "", true
  83.         MasterLevel = 2 '                                            fast check in case slow aborted
  84.         Recurse 1 '                                                  try all moves & responses
  85.         TakeBest 0, true '
  86.         ShowBest
  87.         IF (Score < -700) OR (Score > 500) THEN
  88.             rflag = 0
  89.             IF Moves(0) THEN msg$ = "Checkmate!" ELSE msg$ = "Stalemate!"
  90.             msg$ = msg$ + STR$(Score)
  91.             GOTO yoyo
  92.         END IF
  93.         MasterLevel = MasterLevel1 '                                 slow check
  94.         FOR i = 1 TO MasterLevel: Moves(i) = 0: NEXT
  95.         Recurse 1 '                                                  try all moves & responses
  96.         IF MakeNoise THEN PlaySound "ding"
  97.         TakeBest 0, true '
  98.         ShowBest
  99.         rflag = false
  100.         Center 0, "", true
  101.         IF abort THEN _MEMCOPY m(1), m(1).OFFSET, m(1).SIZE TO m(0), m(0).OFFSET '         restore board
  102.         IF msg$ = "abort" THEN msg$ = ""
  103.         IF LEN(msg$) THEN WorBs = WorB + 1: GOTO yoyo
  104.     END IF
  105.  
  106.     IF LEN(msg$) THEN GOTO yoyo
  107.  
  108.     WorB = SaveWorB
  109.  
  110.     sm$ = m$: m2$ = m$ '                                             save move for display in case modified for castling
  111.     IF m$ = "O-O" THEN '                                             castle kingside
  112.         IF WorB THEN
  113.             m$ = "e1g1": m2$ = "h1f1"
  114.         ELSE
  115.             m$ = "e8g8": m2$ = "h8f8"
  116.         END IF
  117.     END IF
  118.     IF m$ = "O-O-O" THEN '                                           castle queenside
  119.         IF WorB THEN
  120.             m$ = "e1c1": m2$ = "a1c1"
  121.         ELSE
  122.             m$ = "e8c8": m2$ = "a8d8"
  123.         END IF
  124.     END IF
  125.  
  126.     IF human <> 1 THEN GOTO doit '                                   people playing, or computer playing itself
  127.  
  128.     waitflag = 1
  129.     IF icon&(2) THEN _ICON icon&(2) '                                clockx or clockx2
  130.  
  131.     FlashMove true
  132.  
  133.     waitflag = 0
  134.  
  135.     doit:
  136.     m$ = sm$
  137.     lm$ = m$
  138.     MoveIt m$, true
  139.     AddMove
  140.     PlotScreen true
  141.     _DISPLAY
  142.  
  143.     check = false
  144.     CheckBoard 0
  145.     IF Score = 777 THEN check = true: TempMess "Check!", 2
  146.  
  147.     'check = 0: incheck = 0
  148.  
  149.     'check = false: z = Level XOR 1
  150.     'k1$ = MID$(alpha$, mkc, 1) + CHR$(48 + mkr) '                   location of King
  151.     'k2$ = MID$(alpha$, okc, 1) + CHR$(48 + okr) '                   location of King
  152.     'ic = 0
  153.     'FOR i = 1 TO Moves(0) '                                         can any opponent piece move there?
  154.     '    s$ = RIGHT$(Move$(z, 0), 2)
  155.     '    IF k1$ = s$ THEN ic = 1 '                                   in check
  156.     '    IF k2$ = s$ THEN ic = 2 '                                   in check
  157.     'NEXT i
  158.     'IF ic THEN
  159.     '    check = true
  160.     '    ic$ = CHR$(48 + ic) + " Check!"
  161.     '    TempMess ic$
  162.     'END IF
  163.  
  164.     WorB = SaveWorB XOR 1 '                                          toggle white/black
  165. LOOP UNTIL Move = 500
  166.  
  167. IF Move = 500 THEN msg$ = "Over 500 moves...."
  168. PRINT #1, ""
  169. PRINT #1, msg$
  170.  
  171. yoyo:
  172. Playagain msg$
  173. msg$ = ""
  174. CLS 0, bg0&
  175. IF i$ = "n" THEN GOTO begin '                                        n for new game
  176. IF WorBs THEN
  177.     WorB = WorBs - 1: WorBs = 0
  178.     WorB = WorB XOR 1
  179. PlotScreen true
  180. GOTO redo
  181.  
  182. o1:
  183. DATA e2e4,e7e5,g1f3,b8c6,f1b5,a7a6,b5a4,b7b5,a4b3,g8f6,b1c3,f8e7,f3g5,h7h6
  184. 'DATA g5f7,O-O
  185. 'DATA f7d8,g8h7
  186.  
  187. Setup:
  188. DATA 1,2,3,4,5,3,2,1
  189. DATA 6,6,6,6,6,6,6,6
  190. DATA 0,0,0,0,0,0,0,0
  191. DATA 0,0,0,0,0,0,0,0
  192. DATA 0,0,0,0,0,0,0,0
  193. DATA 0,0,0,0,0,0,0,0
  194. DATA 12,12,12,12,12,12,12,12
  195. DATA 7,8,9,10,11,9,8,7
  196.  
  197. test:
  198. DATA 0,0,0,0,0,0,0,0
  199. DATA 0,0,0,0,0,0,0,0
  200. DATA 0,0,0,0,0,0,0,0
  201. DATA 0,11,0,0,0,0,0,0
  202. DATA 0,7,0,12,0,0,0,0
  203. DATA 0,0,0,0,0,0,0,0
  204. DATA 9,0,0,0,6,0,0,0
  205. DATA 5,9,0,0,0,0,0,0
  206.  
  207. Legal:
  208. '      udlr,udlr,udlr,udlr,udlr,udlr,udlr,udlr
  209. DATA R,7000,0700,0070,0007,0000,0000,0000,0000
  210. DATA N,2010,2001,0210,0201,1020,1002,0120,0102
  211. DATA B,7070,7007,0770,0707,0000,0000,0000,0000
  212. DATA Q,7000,0700,0070,0007,7070,7007,0770,0707
  213. DATA K,1000,0100,0010,0001,1010,1001,0110,0101
  214. DATA P,1000,1001,1010,0000,0000,0000,0000,0000
  215.  
  216. hg:
  217. '                   1         2         3         4         5
  218. '          12345678901234567890123456789012345678901234567890
  219. DATA "01","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  220. DATA "02","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  221. DATA "03","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  222. DATA "04","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  223. DATA "05","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  224. DATA "06","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  225. DATA "07","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  226. DATA "08","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  227. DATA "09","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  228. DATA "10","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  229. DATA "11","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  230. DATA "12","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  231. DATA "13","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  232. DATA "14","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  233. DATA "15","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  234. DATA "16","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  235. DATA "17","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  236. DATA "18","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  237. DATA "19","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  238. DATA "20","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  239. DATA "21","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  240. DATA "22","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  241. DATA "23","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  242. DATA "24","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  243. DATA "25","               XXXXXXXXXXXXXXXXXXXX               "
  244. DATA "26","                XXXXXXXXXXXXXXXXXX                "
  245. DATA "27","                 XXXXXXXXXXXXXXXX                 "
  246. DATA "28","                  XXXXXXXXXXXXXX                  "
  247. DATA "29","                   XXXXXXXXXXXX                   "
  248. DATA "30","                    XXXXXXXXXX                    "
  249. DATA "31","                     XXXXXXXX                     "
  250. DATA "32","                      XXXXXX                      "
  251.  
  252. DATA "33","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  253. DATA "34","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  254. DATA "35","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  255. DATA "36","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  256. DATA "37","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  257. DATA "38","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  258. DATA "39","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  259. DATA "40","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  260. DATA "41","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  261. DATA "42","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  262. DATA "43","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  263. DATA "44","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  264. DATA "45","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  265. DATA "46","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  266. DATA "47","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  267. DATA "48","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  268. DATA "49","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  269. DATA "50","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  270. DATA "51","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  271. DATA "52","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  272. DATA "53","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  273. DATA "54","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  274. DATA "55","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  275. DATA "56","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  276. DATA "57","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  277. DATA "58","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  278. DATA "59","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  279. DATA "51","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  280. DATA "60","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  281. DATA "61","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  282. DATA "62","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  283. DATA "63","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  284. DATA "64","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  285.  
  286. PiecePatterns:
  287. DATA ........................
  288. DATA ........................
  289. DATA ........................
  290. DATA ........................
  291. DATA ....X..XX..XX..XX..X....
  292. DATA ....X..XX..XX..XX..X....
  293. DATA ....X..XX..XX..XX..X....
  294. DATA ....X..XX..XX..XX..X....
  295. DATA ....X..XX..XX..XX..X....
  296. DATA .....X.XX..XX..XX.X.....
  297. DATA ......XXXXXXXXXXXX......
  298. DATA .....XX..........XX.....
  299. DATA ......X.XXXXXXXX.X......
  300. DATA ......X.XXXXXXXX.X......
  301. DATA ......X.XXXXXXXX.X......
  302. DATA ......X.XXXXXXXX.X......
  303. DATA .....X............X.....
  304. DATA .....X..XXXXXXXX..X.....
  305. DATA ....X..............X....
  306. DATA ...X..XXXXXXXXXXXX..X...
  307. DATA ...X................X...
  308. DATA ...XXXXXXXXXXXXXXXXXX...
  309.  
  310. DATA ........................
  311. DATA ........................
  312. DATA ........................
  313. DATA ........................
  314. DATA ............XXX.........
  315. DATA ..........XX.X.X........
  316. DATA .........X..X.X.XX......
  317. DATA ........X.X.XX.X..X.....
  318. DATA .......X.XXXX.X.X..X....
  319. DATA .......X.X...XXX.X..X...
  320. DATA .....X..XX..X.XXX.X.X...
  321. DATA ....X.XXXXXXX.XXX.X..X..
  322. DATA ...X.XXXXXX.X..XX.X..X..
  323. DATA ...X.XX..XXX.X.XX.X..X..
  324. DATA ....X..XXXX..X.XX.X..X..
  325. DATA .....XX..X..X.XXX.X..X..
  326. DATA ........X..XX.XX.XX.X...
  327. DATA .......X..XX.XX.XX.X....
  328. DATA ......XXXXXXXXXXXXXX....
  329. DATA .....X..............X...
  330. DATA ....X................X..
  331. DATA .....XXXXXXXXXXXXXXXX...
  332.  
  333. DATA ........................
  334. DATA ........................
  335. DATA ........................
  336. DATA ............X...........
  337. DATA ...........X.X..........
  338. DATA ..........X.X.X.........
  339. DATA ........X...XX..X.......
  340. DATA .......X..X..XX..X......
  341. DATA .......X.XXX..XX.X......
  342. DATA .......X.XXXX..X.X......
  343. DATA ........X.......X.......
  344. DATA .......XX.X.X.X.XX......
  345. DATA ......X...........X.....
  346. DATA .......X.XXX.XX.XX......
  347. DATA ........X.XX.XX.X.......
  348. DATA .......X.XXX.XXX.X......
  349. DATA .......X.XXX.XXX.X......
  350. DATA ......X.X.......X.X.....
  351. DATA .....X.XXXXX.XXXXX.X....
  352. DATA .....X.XXXXX.XXXXX.X....
  353. DATA .....X.............X....
  354. DATA ......XXXXXXXXXXXXX.....
  355.  
  356. DATA ............X...........
  357. DATA ...........X.X..........
  358. DATA .....X....X.X.X....X....
  359. DATA ....X.X.XX.XXX..X.X.X...
  360. DATA ...X.X.X..XX.XXX.X.X.X..
  361. DATA ...X.XX.XXX.X.XXX.XX.X..
  362. DATA ...X.XXX.X.XXX.X.XXX.X..
  363. DATA ...X.XXXX.XXXXX.XXXX.X..
  364. DATA ....X.XXXXXX..XXXXX.X...
  365. DATA .....X.XXXXX..XXXX.X....
  366. DATA .....X.............X....
  367. DATA ......XXXXXXXXXXXXX.....
  368. DATA ....X...............X...
  369. DATA ......XX.XXXXXXX.XX.....
  370. DATA .......X.X.XXX.X.X......
  371. DATA ......X.XX.XXX.XX.X.....
  372. DATA ......X.XX.XXX.XX.X.....
  373. DATA .....XXXXXXXXXXXXXXX....
  374. DATA ....X...............X...
  375. DATA ...X..XX.XX.XX.XX.X..X..
  376. DATA ...X.................X..
  377. DATA ....XXXXXXXXXXXXXXXXX...
  378.  
  379. DATA ...........XX...........
  380. DATA .........XX..XX.........
  381. DATA .......XX.X..X.XX.......
  382. DATA .....XX.X......X.XX.....
  383. DATA ....X..XX.X..X.XX..X....
  384. DATA ...X...XXXX..XXXX...X...
  385. DATA ..X...XX........XX...X..
  386. DATA .X..XXX.XXX..XXX.XXX..X.
  387. DATA X..XXX..XXX..XXX..XXX..X
  388. DATA X.XXXX..XXX..XXXX.XXXX.X
  389. DATA X.XXXX.XXXX..XXXX.XXXX.X
  390. DATA X.XXXX..XXXXXXXX..XXXX.X
  391. DATA .X.XXXX..XXXXXX..XXXX.X.
  392. DATA .X..XXXX..XXXX..XXXX..X.
  393. DATA ..X..XXXX......XXXX..X..
  394. DATA ...X....X......X....X...
  395. DATA ...XXXXXXXXXXXXXXXXXX...
  396. DATA ..X..................X..
  397. DATA .X..XXXXXXXXXXXXXXXX..X.
  398. DATA .X..XXXXXXXXXXXXXXXX..X.
  399. DATA ..X..................X..
  400. DATA ...XXXXXXXXXXXXXXXXXX...
  401.  
  402. DATA ........................
  403. DATA ........................
  404. DATA ........................
  405. DATA ..........XXXX..........
  406. DATA .........X....X.........
  407. DATA ........X.XXXX.X........
  408. DATA ........X.XXXX.X........
  409. DATA .........X....X.........
  410. DATA ........XXXXXXXX........
  411. DATA .......X........X.......
  412. DATA ........XXXXXXXX........
  413. DATA .........X.XX.X.........
  414. DATA .........X.XX.X.........
  415. DATA .........X.XX.X.........
  416. DATA ........X..XX..X........
  417. DATA .......X..XXXX..X.......
  418. DATA ......X.XXXXXXXX.X......
  419. DATA ......X.XXXXXXXX.X......
  420. DATA .....X............X.....
  421. DATA ......XXXXXXXXXXXX......
  422. DATA ........................
  423. DATA ........................
  424.  
  425. rgb:
  426. DATA 0,0,0,0,""
  427. 'DATA 1,20,50,0,"board white"
  428. DATA 1,30,60,20,"board white"
  429. DATA 2,1,1,1,"board black"
  430. DATA 3,50,50,50,"white bright"
  431. DATA 4,12,12,30,"white hightlight"
  432. DATA 5,0,0,0,"black bright"
  433. 'DATA 6,32,32,32,"black highlight"
  434. DATA 6,50,12,12,"black highlight"
  435. DATA 7,63,0,0,"red"
  436. DATA 8,0,63,0,"green"
  437. DATA 9,0,0,63,"blue"
  438. DATA 10,50,50,50,"white"
  439. DATA 11,20,20,20,""
  440. DATA 12,20,20,20,""
  441. DATA 13,40,10,30,""
  442. DATA 14,25,25,25,"gray"
  443. DATA 15,30,30,30,"printing"
  444.  
  445. cmenu:
  446. DATA "1 Board white"
  447. DATA "2 Board black"
  448. DATA "3 W piece main"
  449. DATA "4 W piece trim"
  450. DATA "5 B piece main"
  451. DATA "6 B piece trim"
  452.  
  453. Oops:
  454. gronk = gronk + 1
  455. IF gronk < 100 THEN
  456.     RESUME
  457.     PRINT "Error "; DATE$; "  "; TIME$;
  458.     END
  459.  
  460. SUB AddIt (Level, tm$, Score)
  461.     IF rflag THEN mcount&(Level) = mcount&(Level) + 1
  462.     Moves(Level) = Moves(Level) + 1 '                                count ok
  463.     Move$(Level, Moves(Level)) = tm$ '                               save move
  464.     Score(Level, Moves(Level)) = Score
  465.     Index(Level, Moves(Level)) = TieTo(Level)
  466.  
  467. SUB AddMove
  468.  
  469.     IF WorB THEN '                                                   white=1, black=0
  470.         Move = Move + 1 '                                            number the moves
  471.         PRINT #1, RIGHT$("  " + STR$(Move), 3);
  472.         PRINT #1, RIGHT$(SPACE$(10) + m$, 7);
  473.         MoveLog$(Move) = SPACE$(15)
  474.         MID$(MoveLog$(Move), 1, 3) = Rjust$(Move, 3)
  475.         MID$(MoveLog$(Move), 5, LEN(m$)) = m$
  476.     ELSE
  477.         MID$(MoveLog$(Move), 11, LEN(m$)) = m$
  478.         PRINT #1, " "; m$
  479.         IF (Move MOD 5) = 0 THEN PRINT #1, ""
  480.     END IF
  481.  
  482.  
  483. SUB Center (tr, t$, highlight)
  484.     IF t$ = "" THEN
  485.         IF rflag THEN
  486.             t$ = "           Quit   spacebar:move now   Noise           "
  487.         ELSE
  488.             t$ = "Quit Resign Back Color Invert Setup Mode Noise Graphic"
  489.         END IF
  490.     END IF
  491.     z = _WIDTH \ 2 - LEN(t$) * 4 + 8
  492.     SELECT CASE tr
  493.         CASE IS = -1
  494.             y = ym - 40
  495.         CASE IS = 0
  496.             y = ym - 18
  497.         CASE ELSE
  498.             y = tr / (ym / 16) * ym
  499.     END SELECT
  500.     LINE (0, ym)-(xm - 1, ym - 18), bg0&, BF
  501.     'COLOR white&
  502.     _PRINTSTRING (z, y), t$
  503.     IF highlight THEN
  504.         tr = _RED32(cp&(1))
  505.         tg = _GREEN32(cp&(1))
  506.         tb = _BLUE32(cp&(1))
  507.         COLOR _RGB32(255 - tr, 255 - tg, 255 - tb)
  508.         FOR i = 1 TO LEN(t$)
  509.             c$ = MID$(t$, i, 1)
  510.             IF (c$ = UCASE$(c$)) AND (c$ <> ":") THEN
  511.                 _PRINTSTRING (z + (i - 1) * 8, y), c$
  512.             END IF
  513.         NEXT
  514.     END IF
  515.     COLOR fg0&, bg0&
  516.  
  517. SUB ChangeColors
  518.     LINE (0, 500)-(xm, ym), bg0&, BF '                               clear lower area
  519.     k = 1
  520.     DO
  521.         RESTORE cmenu
  522.         FOR i = 1 TO 6
  523.             READ t$
  524.             tx = 40 + INT((i - 1) / 2) * 150
  525.             ty = 540 + ((i - 1) MOD 2) * 16
  526.             IF i = k THEN COLOR white& ELSE COLOR gray& '            highlight palette for change
  527.             _PRINTSTRING (tx, ty), t$
  528.         NEXT i
  529.         COLOR fg0&, bg0&
  530.         t$ = "rgb:down   RGB:up  Esc:exit"
  531.         tx = _WIDTH \ 2 - LEN(t$) * 4 + 8
  532.         _PRINTSTRING (tx, _HEIGHT - 20), t$
  533.  
  534.         FOR i = 1 TO 3 '                                             show 3 colors lines
  535.             x1 = xc - xq * 4: x2 = xc + xq * 4
  536.             y1 = yc + yq * 4 + 20 + i * 8: y2 = y1 + 4
  537.             LINE (x1, y1)-(x2, y2), black&, BF
  538.             LINE (x1, y1)-(x2, y2), gray&, B
  539.             IF i = 1 THEN j = myr(k): tc& = red&
  540.             IF i = 2 THEN j = myg(k): tc& = green&
  541.             IF i = 3 THEN j = myb(k): tc& = blue&
  542.             j = j / 255 * xq * 8
  543.             LINE (x1, y1)-(x1 + j, y2), tc&, BF
  544.         NEXT i
  545.  
  546.         _DISPLAY
  547.  
  548.         DO: _LIMIT 10: i$ = INKEY$: LOOP UNTIL LEN(i$) '             wait for key
  549.         IF i$ = Esc$ THEN EXIT DO '                                  done
  550.         IF i$ = "" THEN i$ = " " '                                   so instr doesn't bomb
  551.         p = INSTR("123456", i$): IF p THEN k = p '                   select palette
  552.  
  553.         z = 10
  554.         SELECT CASE i$
  555.             CASE IS = "r" '                                          red down
  556.                 myr(k) = myr(k) - z
  557.                 IF myr(k) < 0 THEN myr(k) = 0
  558.             CASE IS = "g" '                                          green down
  559.                 myg(k) = myg(k) - z
  560.                 IF myg(k) < 0 THEN myg(k) = 0
  561.             CASE IS = "b" '                                          blue down
  562.                 myb(k) = myb(k) - z
  563.                 IF myb(k) < 0 THEN myb(k) = 0
  564.             CASE IS = "R" '                                          red up
  565.                 myr(k) = myr(k) + z
  566.                 IF myr(k) > 255 THEN myr(k) = 255
  567.             CASE IS = "G" '                                          green up
  568.                 myg(k) = myg(k) + z
  569.                 IF myg(k) > 255 THEN myg(k) = 255
  570.             CASE IS = "B" '                                          blue up
  571.                 myb(k) = myb(k) + z
  572.                 IF myb(k) > 255 THEN myb(k) = 255
  573.         END SELECT
  574.  
  575.         ColorWrite
  576.         Colorassign
  577.         PlotScreen false
  578.     LOOP
  579.  
  580.     LINE (0, 500)-(xm, ym), black&, BF
  581.  
  582.  
  583. SUB CheckBoard (Level)
  584.     Moves(Level) = 0
  585.     prot(Level) = 0
  586.  
  587.     FOR r = 1 TO 8
  588.         FOR c = 1 TO 8
  589.             mp = b(c, r)
  590.             mc = -(mp > 6) - (mp = 0) * 2 '                          evaluates to 0 black 1 white 2 empty
  591.             mp = mp + (mp > 6) * 6
  592.             IF mc = WorB THEN
  593.                 TryMove Level, c, r, mp, mc
  594.             END IF
  595.         NEXT
  596.     NEXT
  597.  
  598.     IF Level > 1 THEN GOTO nocastle '                                only do for current move (speed)
  599.  
  600.     cq = true: ck = true '                                           castling
  601.  
  602.     IF WorB THEN rn$ = "1" ELSE rn$ = "8"
  603.     rn = VAL(rn$)
  604.     tp = b(5, rn): tp = tp + (tp > 6) * 6 '                          e1 (white) or e8 (black)
  605.     IF tp <> King THEN cq = 0: ck = 0: GOTO nocastle '               no King here
  606.  
  607.     t$ = "e" + rn$ '                                                 King home spot algebraic
  608.     FOR lm = 1 TO Moves(1) '                                         can any opponent piece move there?
  609.         IF t$ = RIGHT$(Move$(1, lm), 2) THEN cq = 0: ck = 0: GOTO nocastle ' must be in check
  610.     NEXT lm
  611.  
  612.     ' WHITE                      BLACK
  613.     ' 8 R N B Q K B N R          1 R N B K Q B N R
  614.     ' 7 P P P P P P P P          2 P P P P P P P P
  615.     ' 6                          3
  616.     ' 5                          4
  617.     ' 4                          5
  618.     ' 3                          6
  619.     ' 2 P P P P P P P P          7 P P P P P P P P
  620.     ' 1 R N B Q K B N R          8 R N B K Q B N R
  621.     '   a b c d e f g h            h g f e d c b a
  622.  
  623.     FOR castle = 1 TO 2 '                                            queenside, then kingside
  624.  
  625.         'debug$(castle) = ""
  626.         nr = 0 '   no rook
  627.         pr = 0 '   prior condition
  628.         ne = 0 '   not empty
  629.         co = 0 '   controlled space
  630.  
  631.         '                 bbww
  632.         ' castle$ format "QKQK" blank if ok, X if nulled by King or Rook move
  633.         IF MID$(castle$, WorB * 2 + castle, 1) <> " " THEN pr = castle: GOTO nocando '  prior condition
  634.  
  635.         IF castle = 1 THEN cn = 1 ELSE cn = 8 '                      column number
  636.         p = b(cn, rn): p = p + (p > 6) * 6
  637.         IF p <> Rook THEN nr = 1: GOTO nocando
  638.  
  639.         '                         bcd              fg
  640.         IF castle = 1 THEN ca$ = "234" ELSE ca$ = "67" '             column number
  641.         FOR cs = 1 TO LEN(ca$) '                                     look at spaces between king and rook
  642.             cn = VAL(MID$(ca$, cs, 1))
  643.             IF b(cn, rn) > 0 THEN ne = castle: GOTO nocando '        not empty
  644.  
  645.             IF NOT ((cs = 1) AND (castle = 1)) THEN '                queenside knight
  646.                 t$ = MID$(alpha$, cn, 1) + rn$ '                     controlled square?
  647.                 IF Level THEN lm = 0 ELSE lm = 1
  648.                 FOR i = 1 TO Moves(lm) '                             see what can move here
  649.                     IF t$ = RIGHT$(Move$(lm, i), 2) THEN
  650.                         'debug$(castle) = Move$(lm, i)
  651.                         co = castle: EXIT FOR ' yes
  652.                     END IF
  653.                 NEXT i
  654.             END IF
  655.         NEXT cs
  656.         nocando:
  657.         'debug$(castle) = debug$(castle) + STR$(nr) + STR$(pr) + STR$(ne) + STR$(co)
  658.         IF (nr + pr + ne + co) THEN '                                non-zero means some test failed
  659.             IF castle = 1 THEN cq = false ELSE ck = false
  660.         END IF
  661.     NEXT castle
  662.  
  663.     IF ck THEN AddIt Level, "O-O", 12
  664.     IF cq THEN AddIt Level, "O-O-O", 13
  665.  
  666.     'LOCATE 34 + WorB, 45: PRINT "*"; castle$; "* ";
  667.     'PRINT MID$("K ", ck + 2, 1);
  668.     'PRINT MID$("Q ", cq + 2, 1); cq; ck;
  669.  
  670.     nocastle:
  671.     TakeBest Level, false
  672.  
  673. SUB Colorassign
  674.     tf$ = "ccolor.dat"
  675.     tf = FREEFILE
  676.     IF _FILEEXISTS(tf$) THEN
  677.         OPEN tf$ FOR INPUT AS #tf
  678.         INPUT #tf, bri
  679.         IF bri = 0 THEN bri = obri
  680.         IF bri < 2 THEN bri = 2
  681.         FOR i = 0 TO 31
  682.             INPUT #tf, myr(i), myg(i), myb(i)
  683.             cp&(i) = _RGB32(myr(i) * bri, myg(i) * bri, myb(i) * bri)
  684.         NEXT
  685.         CLOSE #tf
  686.     ELSE
  687.         bri = 4
  688.         RESTORE rgb
  689.         FOR i = 0 TO 31
  690.             IF i < 16 THEN
  691.                 READ PalNum, myr(i), myg(i), myb(i), Desc$
  692.             ELSE
  693.                 myr(i) = 32: myg(i) = 32: myb(i) = 32
  694.             END IF
  695.             cp&(i) = _RGB32(myr(i) * bri, myg(i) * bri, myb(i) * bri)
  696.         NEXT
  697.         ColorWrite
  698.     END IF
  699.     CLOSE #tf
  700.     black& = cp&(0)
  701.     boardwhite& = cp&(1)
  702.     boardblack& = cp&(2)
  703.     red& = cp&(7)
  704.     green& = cp&(8)
  705.     blue& = cp&(9)
  706.     white& = _RGB32(155, 155, 155)
  707.     gray& = _RGB32(40, 40, 40)
  708.     IF altblack THEN cp&(6) = _RGB32(32 * bri, 32 * bri, 32 * bri)
  709.  
  710. SUB ColorWrite
  711.     tf$ = "ccolor.dat"
  712.     tf = FREEFILE
  713.     OPEN tf$ FOR OUTPUT AS #tf
  714.     PRINT #tf, bri
  715.     FOR i = 0 TO 31
  716.         PRINT #tf, myr(i); ","; myg(i); ","; myb(i)
  717.     NEXT
  718.     CLOSE #tf
  719.  
  720. SUB Cursor (br, bc, fl) STATIC
  721.     DIM garr(8000)
  722.     IF (bc < 1) OR (br < 1) OR (bc > 8) OR (br > 8) THEN EXIT SUB
  723.     x1 = xc + (bc - 5) * xq: x2 = x1 + xq
  724.     y1 = yc + (4 - br) * yq: y2 = y1 + yq
  725.     GET (x1, y1)-(x2, y2), garr()
  726.     IF (ctime! = 0) OR (TIMER > ctime!) THEN
  727.         xx = xx XOR 1
  728.         ctime! = TIMER + .25
  729.         IF ctime! > maxtime& THEN ctime! = 0
  730.     END IF
  731.     IF xx THEN
  732.         IF (useidiot AND (icon&(0) <> 0)) OR (TIMER < alfred!) THEN PUT (x1 + 2, y1 + 2), abuff(), PSET ELSE PUT (x1, y1), garr(), PRESET
  733.     END IF
  734.     IF fl THEN _PRINTSTRING (x1 + 16, y1 + 36), "To?"
  735.     _DISPLAY
  736.  
  737. DEFINT A-Z
  738. SUB DispStats
  739.  
  740.     IF waitflag = 0 THEN
  741.         IF rflag = 0 THEN tc = humanc ELSE tc = 1 - humanc
  742.         IF human = 2 THEN tc = WorB
  743.         t! = TIMER - Start2!: IF t! < 0 THEN t! = t! + maxtime&
  744.         etime!(tc) = etime!(tc) + t!
  745.         etime!(2) = TIMER - Start1! + hold! '                        current move
  746.         hold! = 0
  747.         IF etime!(2) > etime!(tc) THEN etime!(2) = etime!(tc)
  748.         etime!(3) = etime!(0) + etime!(1) '                          game total
  749.         emin = etime!(2) \ 60
  750.     END IF
  751.     Start2! = TIMER
  752.  
  753.     IF (dtime! = 0) OR (TIMER > dtime!) THEN
  754.  
  755.         'IF rick AND (vflag = 0) THEN
  756.         '    LOCATE 1, 4
  757.         '    PRINT Moves(0);
  758.         '    FOR i = 1 TO 3
  759.         '        PRINT mcount&(i);
  760.         '    NEXT i
  761.         '    LOCATE 2, 4
  762.         '    FOR i = 0 TO 3
  763.         '        PRINT Moves(i);
  764.         '    NEXT i
  765.         'END IF
  766.  
  767.         'IF tlimit > 0 THEN t$ = LTRIM$(STR$(tlimit)) + "m" ELSE t$ = "unlimited"
  768.         't$ = "Time: " + t$
  769.         'LOCATE 2, 4: PRINT t$;
  770.  
  771.         IF human <> 2 THEN
  772.             IF rick THEN LOCATE 1, 4: PRINT best$; bscore; "        ";
  773.             tcount& = Moves(0) + mcount&(1) + mcount&(2) + mcount&(3)
  774.             mps& = tcount& - ocount&
  775.             IF mps& <= 100 THEN mps& = omps& ELSE opms& = mps&
  776.             t$ = "   " + STR$(mps&)
  777.             tx = _WIDTH - LEN(t$) * 8 - 10
  778.             IF mps& THEN _PRINTSTRING (tx, 2), t$
  779.  
  780.             t$ = STR$(tcount&)
  781.             tx = _WIDTH - LEN(t$) * 8 - 10
  782.             _PRINTSTRING (tx, 16), t$
  783.  
  784.             'bg2& = _RGB32(0, 70, 70)
  785.             'LINE (351, 504)-(xm - 8, ym - 22), bg2&, BF
  786.             COLOR fg0&, bg0&
  787.             ShowTime 32, etime!(0), "Black"
  788.             ShowTime 33, etime!(1), "White"
  789.             ShowTime 34, etime!(3), "Game"
  790.             ShowTime 35, etime!(2), "Move"
  791.             'COLOR white&, black&
  792.         END IF
  793.  
  794.         ocount& = tcount&
  795.         dtime! = TIMER + 1: IF dtime! > maxtime& THEN dtime! = 0
  796.     END IF
  797.  
  798.     IF (showthink = 0) OR (smode < 2) THEN _DISPLAY
  799.  
  800.  
  801. DEFSNG A-Z
  802. FUNCTION f_pl (n1, n2, n3) '                                         plasma function
  803.     f_pl = _RGB32(n1 * 255, n2 * 255, n3 * 255)
  804.  
  805. DEFINT A-Z
  806. SUB FlashMove (eflag)
  807.     fr = VAL(MID$(m$, 2, 1)) '                                       from row (or rank)
  808.     IF invert THEN fr = 9 - fr '                                     invert means black at bottom
  809.     fc = INSTR(alpha$, LEFT$(m$, 1)) '                               from column
  810.  
  811.     IF invert THEN fc = 9 - fc
  812.  
  813.     tr = VAL(MID$(m$, 4, 1)) '                                       row or rank
  814.     IF invert THEN tr = 9 - tr '                                     black at bottom
  815.     tc = INSTR(alpha$, MID$(m$, 3, 1)) '                             column
  816.     IF invert THEN tc = 9 - tc
  817.  
  818.     DO: _LIMIT 100
  819.         'IF (itime! = 0) OR (TIMER > itime!) THEN
  820.         '    iname = iname XOR 1
  821.         '    _ICON icon&(iname + 2) '                                clockx or clockx2
  822.         '    itime! = TIMER + .5
  823.         'END IF
  824.         KeyScan 1, 1 '                                               plotscreen, _display
  825.         Cursor fr, fc, 0
  826.         Cursor tr, tc, 0
  827.         IF eflag AND (WorB = humanc) THEN EXIT DO
  828.     LOOP UNTIL (i$ = Enter$) OR (human = 0) OR LEN(msg$)
  829.  
  830. SUB Init
  831.     xm = 600: ym = 200
  832.     main& = _NEWIMAGE(xm, ym, 32)
  833.     SCREEN main&
  834.     _DELAY .2
  835.     _DELAY .2
  836.  
  837.     RANDOMIZE TIMER '                                                seed generator
  838.     Colorassign '                                                    red&, green&, etc, easier to use than palette numbers
  839.  
  840.     alpha$ = "abcdefgh"
  841.  
  842.     q = 120
  843.     bg0& = _RGB32(q, q, q)
  844.     fg0& = black&
  845.     SWAP bg0&, fg0&
  846.     castle$ = SPACE$(4) '                                            flags QKQK (B then W)
  847.     crlf$ = Enter$ + lf$
  848.     Enter$ = CHR$(13)
  849.     Esc$ = CHR$(27) '                                                to quit program
  850.     graphics = 3 '                                                   graphics for white squares (0-3)
  851.     lcount& = 0 '                                                    line counter for debug output
  852.     lf$ = CHR$(10) '                                                 line feed
  853.     maxtime& = 86400
  854.     Move = 0
  855.     MakeNoise = 1
  856.     showthink = 1
  857.     WorB = 1 '                                                       white=1, black=0
  858.     xq = 56: yq = 56
  859.     xc = 248: yc = 256 '                                             center of board
  860.  
  861.     COLOR fg0&, bg0&
  862.     FOR i = 1 TO 8
  863.         alphal$(i) = MID$(alpha$, i, 1)
  864.     NEXT i
  865.  
  866.     FOR i = 0 TO 3: etime!(i) = 0: NEXT '                            sides, total, current
  867.  
  868.     RESTORE PiecePatterns '                                          bit images
  869.     FOR p = 1 TO 6 '                                                 RNBQKP
  870.         n = 0
  871.         FOR y = 0 TO 21 ' 22 rows
  872.             READ d$
  873.             p1 = INSTR(d$ + "X", "X") '                              find first "on" bit
  874.             FOR t = LEN(d$) TO 1 STEP -1 '                           find last "on" bit
  875.                 IF MID$(d$, t, 1) = "X" THEN
  876.                     p2 = t
  877.                     EXIT FOR
  878.                 END IF
  879.             NEXT t
  880.             FOR x = p1 TO p2
  881.                 pixel = INSTR(".X", MID$(d$, x, 1))
  882.                 n = n + 1
  883.                 IF pixel = 2 THEN c = 3 ELSE c = 4
  884.                 x(p, n) = x + 1
  885.                 y(p, n) = y + 2
  886.                 c(p, n) = c
  887.                 IF pixel = 2 THEN c = 5 ELSE c = 6
  888.                 c(p + 6, n) = c
  889.             NEXT x
  890.         NEXT y
  891.         c(p, 0) = n
  892.         FOR scram = 1 TO 256 '                                       scramble (moves nicer)
  893.             c1 = RND * (c(p, 0) - 1) + 1 '                           any bit
  894.             c2 = RND * (c(p, 0) - 1) + 1 '                           any other bit
  895.             SWAP x(p, c1), x(p, c2)
  896.             SWAP y(p, c1), y(p, c2)
  897.             SWAP c(p, c1), c(p, c2) '                                black
  898.             SWAP c(p + 6, c1), c(p + 6, c2) '                        white
  899.         NEXT scram
  900.     NEXT p
  901.  
  902.     RESTORE Legal '                                                  define how piece moves
  903.     FOR p = 1 TO 6 '                                                 RNBQKP
  904.         READ p$ '                                                    piece, not saved
  905.         FOR t = 0 TO 7 '                                             8 each
  906.             READ udlr$
  907.             du(p, t) = VAL(MID$(udlr$, 1, 1)) '                      direction up
  908.             dd(p, t) = VAL(MID$(udlr$, 2, 1)) '                      direction down
  909.             dl(p, t) = VAL(MID$(udlr$, 3, 1)) '                      direction left
  910.             dr(p, t) = VAL(MID$(udlr$, 4, 1)) '                      direction right
  911.         NEXT t
  912.     NEXT p
  913.  
  914.     FOR i = 1 TO 6
  915.         '                    RNBQKP
  916.         value(i) = VAL(MID$("533901", i, 1)) '                       point value for capture
  917.     NEXT i
  918.  
  919.     RESTORE Setup '                                                  initial board position
  920.     FOR r = 8 TO 1 STEP -1 '                                         row
  921.         FOR c = 1 TO 8 '                                             column
  922.             READ b(c, r) '                                           board
  923.             o(c, r) = b(c, r) '                                      initial setup
  924.         NEXT c
  925.     NEXT r
  926.  
  927.     gm = 0: n = 0
  928.     IF LEN(GameFile$) > 0 THEN ReadGame
  929.     gm = 0
  930.  
  931.     CLOSE
  932.     newf:
  933.     f = f + 1
  934.     f$ = "ch" + RIGHT$("0000000" + LTRIM$(STR$(f)), 6) + ".alg" '    save game for analysis
  935.     IF _FILEEXISTS(f$) THEN GOTO newf
  936.  
  937.     OPEN f$ FOR OUTPUT AS #1 '                                       algrebraic moves
  938.  
  939.     FOR i = 0 TO 3
  940.         SELECT CASE i
  941.             CASE IS = 0
  942.                 f$ = "alfred.jpg" '                                  Alfred E. Neuman
  943.             CASE IS = 1
  944.                 f$ = "chess.png"
  945.             CASE IS = 2
  946.                 f$ = "clockx.png"
  947.             CASE IS = 3
  948.                 f$ = "clockx2.png"
  949.         END SELECT
  950.         isthere = true
  951.         IF _FILEEXISTS(f$) = 0 THEN '                                accomodate Linux, which cares about case
  952.             f$ = UCASE$(f$) '                                        now try uppercase
  953.             IF _FILEEXISTS(f$) = 0 THEN isthere = false
  954.         END IF
  955.         IF isthere THEN
  956.             li1:
  957.             icon&(i) = _LOADIMAGE(f$)
  958.             IF icon&(i) >= -1 THEN _DELAY .2: GOTO li1
  959.         END IF
  960.     NEXT i
  961.     IF icon&(1) <> 0 THEN
  962.         _ICON icon&(1)
  963.         _DELAY .2
  964.     END IF
  965.  
  966.     IF icon&(0) <> 0 THEN
  967.         _SOURCE icon&(0) '                                               Alfred E. Neuman
  968.         _DISPLAY '                                                       hide idiot
  969.         _PUTIMAGE
  970.         GET (0, 0)-(52, 53), abuff(0)
  971.     END IF
  972.  
  973.     CLS 0, bg0&
  974.     _DELAY .2
  975.     Menubox
  976.     Center 6, "White  Black  Humans  Computer", 1
  977.     Center 0, "Quit or Esc to exit", 1
  978.     _DISPLAY
  979.     DO: _LIMIT 10
  980.         i$ = INKEY$
  981.         IF i$ = "" THEN i$ = " "
  982.         IF (LCASE$(i$) = "q") OR (i$ = Esc$) THEN SYSTEM
  983.         p = INSTR("bwhc", i$)
  984.     LOOP UNTIL p
  985.     SELECT CASE p
  986.         CASE IS = 1 '                                                player is black
  987.             human = 1: humanc = 0: invert = 1
  988.         CASE IS = 2 '                                                player is white
  989.             human = 1: humanc = 1
  990.         CASE IS = 3 '                                                human vs. human
  991.             human = 2
  992.         CASE IS = 4 '                                                computer vs. computer, just watch
  993.             human = 0: OnAuto = 1
  994.     END SELECT
  995.  
  996.     'IF human <> 2 THEN
  997.     '    tlimit = 0
  998.     '    DO
  999.     '        CLS
  1000.     '        Menubox
  1001.     '        Center 6, "Time limit in minutes?  (0 unlimited)", 0
  1002.     '        Center 8, STR$(tlimit), 0
  1003.     '        Center 0, "Quit or Esc to exit", 1
  1004.     '        _DISPLAY
  1005.     '        DO: _LIMIT 10
  1006.     '            i$ = INKEY$
  1007.     '        LOOP UNTIL LEN(i$)
  1008.     '        IF (LCASE$(i$) = "q") OR (i$ = Esc$) THEN SYSTEM
  1009.     '        IF i$ = CHR$(8) THEN tlimit = tlimit / 10
  1010.     '        p = INSTR("0123456789", i$): IF p THEN tlimit = tlimit * 10 + p - 1
  1011.     '    LOOP UNTIL i$ = Enter$
  1012.     'END IF
  1013.  
  1014.     'IF rick THEN smode = 2
  1015.     ScreenInit
  1016.     PlotBoard
  1017.  
  1018. SUB HumanMove STATIC
  1019.     cursoron! = TIMER + 3: IF cursoron! > maxtime& THEN cursoron! = 0
  1020.     IF cc = 0 THEN
  1021.         rr = 7
  1022.         cc = 5 + (WorB = 0)
  1023.     END IF
  1024.     FOR i = 0 TO 1
  1025.         DO: _LIMIT 30
  1026.             IF vflag THEN ShowValid cc, rr
  1027.             KeyScan 1, 0 '                                           plotscreen, no _display
  1028.             IF rr < 1 THEN rr = 1
  1029.             IF rr > 8 THEN rr = 8
  1030.             IF cc < 1 THEN cc = 1
  1031.             IF cc > 8 THEN cc = 8
  1032.             IF cursoron! > TIMER THEN Cursor 9 - rr, cc, i
  1033.             IF takebackflag OR LEN(msg$) THEN EXIT SUB
  1034.             WHILE _MOUSEINPUT
  1035.                 mx = _MOUSEX
  1036.                 my = _MOUSEY
  1037.                 xx = (mx - xc - (4 * xq) + xq \ 2) / xq + 8
  1038.                 yy = (my - yc - (4 * yq) + yq \ 2) / yq + 8
  1039.                 IF (xx > 0) AND (xx < 9) AND (yy > 0) AND (yy < 9) THEN rr = yy: cc = xx
  1040.                 IF _MOUSEBUTTON(1) OR _MOUSEBUTTON(2) THEN i$ = Enter$
  1041.             WEND
  1042.             IF LEN(i$) = 2 THEN
  1043.                 kk = ASC(RIGHT$(i$, 1))
  1044.                 cc = cc + (kk = 75) - (kk = 77) '                    left right
  1045.                 rr = rr + (kk = 72) - (kk = 80) '                    up down
  1046.             END IF
  1047.         LOOP UNTIL i$ = Enter$
  1048.         IF i = 0 THEN
  1049.             fr = rr: fc = cc
  1050.             IF invert THEN fr = 9 - fr: fc = 9 - fc
  1051.         ELSE
  1052.             tr = rr: tc = cc
  1053.             IF invert THEN tr = 9 - tr: tc = 9 - tc
  1054.         END IF
  1055.     NEXT i
  1056.  
  1057.     fs$ = alphal$(fc) + LTRIM$(STR$(9 - fr))
  1058.     ts$ = alphal$(tc) + LTRIM$(STR$(9 - tr))
  1059.     m$ = fs$ + ts$
  1060.     IF m$ = "e1g1" THEN m$ = "O-O"
  1061.     IF m$ = "e1c1" THEN m$ = "O-O-O"
  1062.     IF m$ = "e8g8" THEN m$ = "O-O"
  1063.     IF m$ = "e8c8" THEN m$ = "O-O-O"
  1064.  
  1065. SUB KeyScan (kf1, kf2) STATIC '                                      plotscreen, _display
  1066.     TempMess "", 0
  1067.     DispStats
  1068.     dot = 0
  1069.     i$ = INKEY$
  1070.     IF LEN(i$) THEN
  1071.         cursoron! = TIMER + 2
  1072.         IF cursoron! > maxtime& THEN cursoron! = 0
  1073.     END IF
  1074.     IF LEN(i$) = 1 THEN
  1075.         IF (LCASE$(i$) = "q") OR (i$ = Esc$) THEN abort = 9: msg$ = "Quit!"
  1076.         IF i$ = Enter$ THEN EXIT SUB
  1077.         IF i$ = " " THEN msg$ = "abort": abort = 1: EXIT SUB '       move now
  1078.         c = INSTR("123456789ABCDEF0", i$) '                          experiment with colors
  1079.         IF c > 0 THEN
  1080.             IF c = 16 THEN
  1081.                 c = 2
  1082.                 myr(c) = 0: myg(c) = 0: myb(c) = 0
  1083.             ELSE
  1084.                 myr(c) = RND * 64: myg(c) = RND * 64: myb(c) = RND * 64
  1085.             END IF
  1086.             cp&(c) = _RGB32(myr(c) * bri, myg(c) * bri, myb(c) * bri)
  1087.             ColorWrite
  1088.             Colorassign
  1089.             PlotBoard
  1090.         END IF
  1091.         IF i$ = "a" THEN OnAuto = NOT (OnAuto) '                     not currently in use
  1092.         IF i$ = "b" THEN takebackflag = 1
  1093.         IF i$ = "c" THEN ChangeColors
  1094.         IF i$ = "d" THEN SWAP fg0&, bg0&: CLS 0, bg0&
  1095.         IF i$ = "f" THEN PlayFile
  1096.         IF i$ = "g" THEN '                                           change white square graphics scheme
  1097.             graphics = (graphics + 1) MOD 4
  1098.             IF graphics = 0 THEN PlotBoard
  1099.             t$ = "Mode" + STR$(graphics + 1) + " of 4"
  1100.             TempMess t$, 2
  1101.         END IF
  1102.         IF i$ = "G" THEN pinit = pinit XOR 1 '                       adjust current white square graphics
  1103.         IF i$ = "h" THEN dot = 1: history = history XOR 1
  1104.         IF i$ = "i" THEN '                                           flip board around
  1105.             IF human = 2 THEN
  1106.                 iflag = iflag XOR 1
  1107.             ELSE
  1108.                 invert = invert XOR 1
  1109.                 PlotBoard
  1110.             END IF
  1111.         END IF
  1112.         IF i$ = "I" THEN
  1113.             useidiot = useidiot XOR 1
  1114.             t$ = "Idiot " + OnOff$(useidiot)
  1115.             TempMess t$, 2
  1116.         END IF
  1117.         IF i$ = "l" THEN dot = 1: showlegalf = showlegalf XOR 1
  1118.         IF i$ = "L" THEN '                                           look at log file
  1119.             CLOSE #2
  1120.             SHELL _DONTWAIT "notepad chess.txt"
  1121.             OPEN "chess.txt" FOR APPEND AS #2
  1122.         END IF
  1123.         IF i$ = "m" THEN '                                           screen mode
  1124.             smode = (smode + 1) MOD 3
  1125.             ScreenInit
  1126.         END IF
  1127.         IF i$ = "n" THEN '                                           sound effects
  1128.             MakeNoise = MakeNoise XOR 1
  1129.             t$ = "Sound " + OnOff$(MakeNoise)
  1130.             TempMess t$, 2
  1131.         END IF
  1132.         IF i$ = "p" THEN dot = 1: showprotf = showprotf XOR 1
  1133.         IF i$ = "P" THEN
  1134.             pause = pause XOR 1
  1135.             IF pause THEN
  1136.                 LOCATE 2, 29: PRINT "PAUSED";
  1137.                 _DISPLAY
  1138.                 t! = TIMER - etime!(2)
  1139.                 IF t! < 0 THEN t! = t! + maxtime&
  1140.                 hold! = t!
  1141.                 SLEEP
  1142.                 Start1! = TIMER
  1143.                 LOCATE 2, 29: PRINT SPACE$(10);
  1144.                 _DISPLAY '
  1145.             END IF
  1146.         END IF
  1147.         IF (rflag = 0) AND (i$ = "r") THEN abort = 2: msg$ = "Resign!"
  1148.         IF i$ = "s" THEN Setup '                                     setup
  1149.         IF i$ = "t" THEN dot = 1: showthink = showthink XOR 1
  1150.         IF i$ = "v" THEN '                                           show valid moves at top left
  1151.             vflag = vflag XOR 1
  1152.             LOCATE 2, 4: PRINT SPACE$(40);
  1153.             _DISPLAY
  1154.         END IF
  1155.         IF i$ = "x" AND MakeNoise THEN PlaySound "ding" '            sound test
  1156.         IF i$ = "X" THEN
  1157.             SHELL _HIDE "del ccolor.dat" '                           kill color file
  1158.             ColorWrite
  1159.             Colorassign
  1160.             PlotBoard
  1161.         END IF
  1162.         'IF i$ = "y" THEN itest '                                    see how bad icon problem is
  1163.         IF i$ = "z" THEN
  1164.             altblack = altblack XOR 1
  1165.             Colorassign
  1166.             'CLS 0, bg0&
  1167.             PlotBoard
  1168.             TempMess "Alternate black " + OnOff(altblack), 2
  1169.         END IF
  1170.         i$ = ""
  1171.     END IF
  1172.     IF LEN(i$) = 2 THEN
  1173.         k = ASC(RIGHT$(i$, 1))
  1174.         wbri = bri
  1175.         bri = bri - (k = 73) + (k = 81) '                            brightness PgUp/PgDn
  1176.         IF bri < 2 THEN bri = 2
  1177.         IF bri > 4 THEN bri = 4
  1178.         IF bri <> wbri THEN '                                        was changed
  1179.             ColorWrite
  1180.             Colorassign
  1181.             TempMess "Brightness" + STR$(bri), 1
  1182.         END IF
  1183.     END IF
  1184.  
  1185.     IF kf1 THEN PlotScreen true
  1186.     IF dot THEN DebugR = 99: TextInfo ""
  1187.     IF kf2 THEN _DISPLAY
  1188.  
  1189. FUNCTION Make4$ (t$)
  1190.     Make4$ = LEFT$(t$ + SPACE$(4), 4)
  1191.  
  1192. DEFINT A-Z
  1193. SUB LogThinking () STATIC
  1194.     ts = 0: z1$ = "": z2$ = ""
  1195.     FOR t = 1 TO 3
  1196.         ti = TieTo(t)
  1197.         z1$ = z1$ + Make4$(Move$(t - 1, ti)) + " "
  1198.         z2$ = z2$ + Rjust$(Score(t - 1, ti), 3) + " "
  1199.         ts = ts + Score(t - 1, ti)
  1200.     NEXT t
  1201.     ts = ts - Score
  1202.     zz$ = z1$ + Make4$(m$) + z2$ + Rjust$(Score, 3) + " " + Rjust$(ts, 4)
  1203.     PRINT #2, zz$
  1204.  
  1205.     zz = Score(0, 1)
  1206.     z$ = Move$(0, 1)
  1207.     IF zz >= bscore THEN
  1208.         bscore = zz
  1209.         IF zz = bscore THEN best$ = best$ + " " + z$ ELSE best$ = z$
  1210.     END IF
  1211.  
  1212.     TextInfo zz$
  1213.  
  1214. SUB Menubox
  1215.     tx = _WIDTH \ 2: ty = _HEIGHT \ 2
  1216.     xs = 200: ys = 70
  1217.     x1 = tx - xs: y1 = ty - ys
  1218.     x2 = tx + xs: y2 = ty + ys
  1219.  
  1220.     LINE (x1, y1 + 20)-(x2, y2 - 20), _RGBA(1, 1, 1, 220), BF
  1221.     FOR q = 2 TO 20 STEP 4
  1222.         LINE (x1 - q + 0, y1 + q + 0)-(x2 + q + 0, y2 - q + 0), cp&(1), B
  1223.         LINE (x1 - q + 1, y1 + q + 1)-(x2 + q + 1, y2 - q + 1), cp&(1), B
  1224.     NEXT q
  1225.  
  1226. SUB MoveIt (m$, real)
  1227.     IF m$ = ep$ THEN '                                               epfc, epfr, eptc, eptr, eprc, eprr
  1228.         Plotpiece fc, fr, tc, tr
  1229.         b(epfc, epfr) = 0
  1230.         b(eprc, eprr) = 0
  1231.         b(eptc, eptr) = 6 + WorB * 6
  1232.         EXIT SUB
  1233.     END IF
  1234.  
  1235.     IF m$ = "res" THEN EXIT SUB '                                    resign?
  1236.     fs$ = LEFT$(m$, 2) '                                             from square
  1237.     ts$ = RIGHT$(m$, 2) '                                            to square
  1238.     tzz = 1 - (LEFT$(m$, 1) = "O") - (L1$ = "e") '                   two moves for a castle
  1239.  
  1240.     FOR pass = 1 TO tzz
  1241.  
  1242.         IF m$ = "O-O" THEN '                                         castle Kingside
  1243.             IF WorB = 1 THEN '                                       white
  1244.                 IF pass = 1 THEN '                                   first move of KS castle
  1245.                     fs$ = "e1": ts$ = "g1"
  1246.                 ELSE '                                               else 2nd
  1247.                     fs$ = "h1": ts$ = "f1"
  1248.                 END IF
  1249.             ELSE '                                                   black castle
  1250.                 IF pass = 1 THEN
  1251.                     fs$ = "e8": ts$ = "g8"
  1252.                 ELSE
  1253.                     fs$ = "h8": ts$ = "f8"
  1254.                 END IF
  1255.             END IF
  1256.         END IF
  1257.         IF m$ = "O-O-O" THEN '                                       castle Queenside
  1258.             IF WorB THEN '                                           white
  1259.                 IF pass = 1 THEN
  1260.                     fs$ = "e1": ts$ = "c1"
  1261.                 ELSE
  1262.                     fs$ = "a1": ts$ = "d1"
  1263.                 END IF
  1264.             ELSE
  1265.                 IF pass = 1 THEN
  1266.                     fs$ = "e8": ts$ = "c8"
  1267.                 ELSE
  1268.                     fs$ = "a8": ts$ = "d8"
  1269.                 END IF
  1270.             END IF
  1271.         END IF
  1272.         fc = INSTR(alpha$, LEFT$(fs$, 1)) '                          from column
  1273.         fr = VAL(RIGHT$(fs$, 1)) '                                   from row
  1274.         pm = b(fc, fr) '                                             piece to move
  1275.         p = pm + (pm > 6) * 6
  1276.         tc = INSTR(alpha$, LEFT$(ts$, 1)) '                          to column
  1277.         tr = VAL(RIGHT$(ts$, 1)) '                                   to row
  1278.         b(tc, tr) = pm '                                             move piece in array
  1279.         b(fc, fr) = 0 '                                              blank old array spot
  1280.         IF real THEN
  1281.             IF b(c, r) = o(c, r) THEN o(c, r) = -1
  1282.             Plotpiece fc, fr, tc, tr
  1283.             IF p = King THEN MID$(castle$, WorB * 2 + 1, 2) = "XX"
  1284.             IF p = Rook THEN
  1285.                 IF WorB THEN
  1286.                     IF (fc = 1) AND (fr = 1) THEN MID$(castle$, 3, 1) = "X"
  1287.                     IF (fc = 1) AND (fr = 8) THEN MID$(castle$, 4, 1) = "X"
  1288.                 ELSE
  1289.                     IF (fc = 8) AND (fr = 1) THEN MID$(castle$, 1, 1) = "X"
  1290.                     IF (fc = 8) AND (fr = 8) THEN MID$(castle$, 2, 1) = "X"
  1291.                 END IF
  1292.             END IF
  1293.         END IF
  1294.         IF (p = Pawn) AND ((tr = 1) OR (tr = 8)) THEN
  1295.             b(tc, tr) = Queen - (pm > 6) * 6 '                       promote to queen
  1296.             IF real THEN Plotpiece tc, tr, tc, tr '                  show queen
  1297.         END IF
  1298.     NEXT pass
  1299.  
  1300. DEFINT A-Z
  1301. FUNCTION OnOff$ (v)
  1302.     OnOff$ = MID$("OFFON ", v * 3 + 1, 3)
  1303.  
  1304. DEFSNG A-Z
  1305. SUB Plasma STATIC
  1306.     TYPE xy
  1307.         x AS SINGLE
  1308.         y AS SINGLE
  1309.         dx AS SINGLE
  1310.         dy AS SINGLE
  1311.     END TYPE
  1312.  
  1313.     IF pinit% = 0 THEN
  1314.         DIM c(360) AS _UNSIGNED LONG, p(10) AS xy, f(10)
  1315.         r = RND: g = RND: b = RND: i% = 0: q = .5
  1316.         FOR n% = 1 TO 5
  1317.             r1 = r: g1 = g: b1 = b
  1318.             DO: r = RND: LOOP UNTIL ABS(r - r1) > q
  1319.             DO: g = RND: LOOP UNTIL ABS(g - g1) > q
  1320.             DO: b = RND: LOOP UNTIL ABS(g - g1) > q
  1321.             FOR m% = 0 TO 17: m1% = 17 - m%
  1322.                 f1 = (m% * r) / 18: f2 = (m% * g) / 18: f3 = (m% * b) / 18: c(i%) = f_pl(f1, f2, f3): i% = i% + 1
  1323.             NEXT
  1324.             FOR m% = 0 TO 17: m1% = 17 - m%
  1325.                 f1 = (m% + m1% * r) / 18: f2 = (m% + m1% * g) / 18: f3 = (m% + m1% * b) / 18: c(i%) = f_pl(f1, f2, f3): i% = i% + 1
  1326.             NEXT
  1327.             FOR m% = 0 TO 17: m1% = 17 - m%
  1328.                 f1 = (m1% + m% * r) / 18: f2 = (m1% + m% * g) / 18: f3 = (m1% + m% * b) / 18: c(i%) = f_pl(f1, f2, f3): i% = i% + 1
  1329.             NEXT
  1330.             FOR m% = 0 TO 17: m1% = 17 - m%
  1331.                 f1 = (m1% * r) / 18: f2 = (m1% * g) / 18: f3 = (m1% * b) / 18: c(i%) = f_pl(f1, f2, f3): i% = i% + 1
  1332.             NEXT
  1333.         NEXT
  1334.  
  1335.         FOR n% = 0 TO 5
  1336.             p(n%).x = RND * xm%: p(n%).y = RND * ym%: p(n%).dx = RND * 2 - 1: p(n%).dy = RND * 2 - 1
  1337.             f(n%) = RND * .1
  1338.         NEXT
  1339.  
  1340.         xm2% = 8 * xq%: ym2% = xm2%: x1% = xc% - 4 * xq%: y1% = yc% - 4 * yq%: x2% = xc% + 4 * xq%: y2% = yc% + 4 * yq%:
  1341.         pinit% = 1
  1342.     END IF
  1343.  
  1344.     FOR n% = 0 TO 5
  1345.         p(n%).x = p(n%).x + p(n%).dx
  1346.         IF p(n%).x > xm2% OR p(n%).x < 0 THEN p(n%).dx = -p(n%).dx
  1347.         p(n%).y = p(n%).y + p(n%).dy
  1348.         IF p(n%).y > ym2% OR p(n%).y < 0 THEN p(n%).dy = -p(n%).dy
  1349.     NEXT
  1350.  
  1351.     IF graphics% = 2 THEN z% = 1 ELSE z% = 2
  1352.  
  1353.     FOR y% = y1% TO y2% STEP z%
  1354.         FOR x% = x1% TO x2% STEP z%
  1355.             p& = POINT(x%, y%)
  1356.             'IF (p& = boardwhite&) OR (p& = boardblack&) THEN
  1357.             IF (p& = boardwhite&) THEN
  1358.                 d = 0
  1359.                 FOR n% = 0 TO 5
  1360.                     dx = x% - p(n%).x: dy = y% - p(n%).y
  1361.                     k = SQR(dx * dx + dy * dy)
  1362.                     d = d + (SIN(k * f(n%)) + 1) / 2
  1363.                 NEXT
  1364.                 PSET (x%, y%), c(d * 60)
  1365.             END IF
  1366.         NEXT
  1367.         '_DELAY .001
  1368.     NEXT
  1369.  
  1370. DEFINT A-Z
  1371. SUB Playagain (t$)
  1372.     Menubox
  1373.     COLOR _RGBA32(222, 222, 222, 255), _RGBA32(1, 1, 1, 0)
  1374.     Center 18, t$, 0
  1375.     IF INSTR("QR", LEFT$(t$, 1)) THEN '                              Quit or Resign
  1376.         Center 20, "Resume    New game     Quit", 1
  1377.         ks$ = "rn"
  1378.     ELSE
  1379.         Center 20, "New game     Quit", 1
  1380.         ks$ = "rn" '                                                 take out r when working properly (false checkmates)
  1381.     END IF
  1382.     _DISPLAY
  1383.     'COLOR _RGBA(155, 155, 155, 255), _RGBA32(0, 0, 0, 255)
  1384.     COLOR fg0&, bg0&
  1385.  
  1386.     DO: _LIMIT 10
  1387.         i$ = INKEY$
  1388.         IF i$ = "" THEN i$ = " "
  1389.         IF (i$ = Esc$) OR (LCASE$(i$) = "q") THEN SYSTEM
  1390.         IF human = 0 THEN i$ = "n"
  1391.     LOOP UNTIL INSTR(ks$, i$)
  1392.  
  1393. SUB PlayFile
  1394.     tryagain:
  1395.     LOCATE 1, 1: PRINT SPACE$(20);
  1396.     LOCATE 1, 1: INPUT f$
  1397.     IF f$ = "" THEN EXIT SUB
  1398.     f$ = f$ + ".alg"
  1399.     IF NOT (_FILEEXISTS(f$)) THEN GOTO tryagain
  1400.     LOCATE 1, 1: PRINT SPACE$(20);
  1401.     tf = FREEFILE
  1402.     OPEN f$ FOR INPUT AS #tf
  1403.     WHILE NOT (EOF(tf))
  1404.         LINE INPUT #tf, t$
  1405.         IF LEN(LTRIM$(t$)) THEN
  1406.             t$ = t$ + SPACE$(20)
  1407.             FOR WorB = 1 TO 0 STEP -1
  1408.                 m$ = RTRIM$(LTRIM$(MID$(t$, 12 - WorB * 6, 5)))
  1409.                 IF m$ = SPACE$(5) THEN GOTO pbdone
  1410.                 FlashMove false
  1411.                 MoveIt m$, true
  1412.                 PlotScreen true
  1413.                 _DISPLAY
  1414.                 IF (i$ = "q") OR (i$ = Esc$) THEN SYSTEM
  1415.                 IF i$ = " " THEN i$ = "": GOTO pbdone
  1416.             NEXT WorB
  1417.         END IF
  1418.     WEND
  1419.     pbdone:
  1420.     LOCATE 1, 1: PRINT SPACE$(20):
  1421.     CLOSE #tf
  1422.     IF MakeNoise THEN PlaySound "ding"
  1423.  
  1424. DEFSNG A-Z
  1425. SUB PlaySound (f$) STATIC '         ding,tada,notify,windows xp hardware fail, etc.
  1426.     CONST CACHE = 441 '             minimal detected frequency for analyzer is 100 Hz, so this is enought value (with 44100 biterate)
  1427.     TYPE head
  1428.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  1429.         size AS LONG '              4 bytes  (?E??)
  1430.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  1431.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  1432.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  1433.         format AS STRING * 2 '      2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  1434.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  1435.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  1436.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  1437.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  1438.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  1439.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  1440.     END TYPE '                     40 bytes  total
  1441.     TYPE Wav16S
  1442.         Left AS INTEGER
  1443.         Right AS INTEGER
  1444.     END TYPE
  1445.     REDIM scache(CACHE) AS Wav16S
  1446.     DIM H AS head
  1447.     ch = FREEFILE
  1448.     f$ = f$ + ".wav"
  1449.     IF _FILEEXISTS(f$) = 0 THEN EXIT SUB
  1450.     OPEN f$ FOR BINARY AS #ch
  1451.     GET #ch, , H
  1452.     block = H.Block
  1453.     RATE = H.rate
  1454.     chan = H.channels
  1455.     bits = H.Bits
  1456.     L = _SNDOPENRAW
  1457.     R = _SNDOPENRAW
  1458.     REDIM scache(CACHE) AS Wav16S
  1459.     DO WHILE NOT EOF(ch)
  1460.         GET #ch, , scache()
  1461.         FOR P = 0 TO CACHE
  1462.             lef = scache(P).Left
  1463.             IF chan = 1 THEN righ = lef ELSE righ = scache(P).Right
  1464.             lef = lef / RATE
  1465.             righ = righ / RATE
  1466.             IF RATE > 44100 THEN frekvence = RATE ELSE frekvence = 44100
  1467.             FOR plll = 1 TO frekvence / RATE
  1468.                 _SNDRAW lef, L
  1469.                 _SNDRAW righ, R
  1470.             NEXT plll
  1471.         NEXT
  1472.     LOOP
  1473.     CLOSE ch
  1474.  
  1475. DEFINT A-Z
  1476. SUB PlotBoard
  1477.     FOR zr = 1 TO 8
  1478.         FOR zc = 1 TO 8
  1479.             IF rflag = 0 THEN Plotpiece zc, zr, zc, zr
  1480.         NEXT zc
  1481.     NEXT zr
  1482.  
  1483. SUB Plotpiece (fc, fr, tc, tr)
  1484.     x1 = xc + (fc - 5) * xq
  1485.     x2 = xc + (tc - 5) * xq
  1486.     y1 = yc + (4 - fr) * yq
  1487.     y2 = yc + (4 - tr) * yq
  1488.     p = b(tc, tr)
  1489.     IF invert THEN p = b(9 - tc, 9 - tr)
  1490.     IF p > 6 THEN wb = 1: p = p - 6
  1491.     i = p - (wb = 0) * 6
  1492.  
  1493.     FOR ps = 0 TO 1
  1494.         IF ps = 0 THEN
  1495.             c = fr + fc: tx = x1: ty = y1
  1496.         ELSE
  1497.             c = tr + tc: tx = x2: ty = y2
  1498.         END IF
  1499.         IF c MOD 2 THEN
  1500.             LINE (tx, ty)-(tx + xq, ty + yq), boardwhite&, BF
  1501.         ELSE
  1502.             LINE (tx, ty)-(tx + xq, ty + yq), boardblack&, BF '      black square
  1503.             LINE (tx, ty)-(tx + xq, ty + yq), boardwhite&, B '       border
  1504.         END IF
  1505.     NEXT ps
  1506.  
  1507.     FOR t = 1 TO c(p, 0)
  1508.         tx = x1 + x(p, t) * 2
  1509.         ty = y1 + y(p, t) * 2
  1510.         LINE (tx, ty)-STEP(1, 1), cp&(c(i, t)), B
  1511.     NEXT t
  1512.  
  1513. SUB PlotScreen (lflag) STATIC
  1514.     'CLS 0, bg0&
  1515.     PlotBoard
  1516.     TextInfo ""
  1517.     r = _RED32(boardwhite&) \ 2 '                                    legend, dim a-h, 1-8 along sides
  1518.     g = _GREEN32(boardwhite&) \ 2
  1519.     b = _BLUE32(boardwhite&) \ 2
  1520.     COLOR _RGB32(r, g, b)
  1521.     FOR i = 1 TO 8
  1522.         IF invert THEN z = i ELSE z = 9 - i
  1523.         n$ = LTRIM$(STR$(z))
  1524.         IF invert THEN z = 9 - i ELSE z = i
  1525.         a$ = alphal$(z)
  1526.         nx = xc - 4 * xq - 12
  1527.         ny = yc + (i - 4) * yq - 34
  1528.         ax = xc + (i - 5) * xq + 23
  1529.         ay = yc + 4 * yq + 3
  1530.         _PRINTSTRING (nx, ny), n$
  1531.         _PRINTSTRING (ax, ay), a$
  1532.     NEXT i
  1533.     COLOR fg0&, bg0&
  1534.  
  1535.     IF lflag THEN Center 0, "", 1
  1536.  
  1537.     IF graphics = 0 THEN EXIT SUB
  1538.     IF graphics > 1 THEN
  1539.         Plasma
  1540.         EXIT SUB
  1541.     END IF
  1542.  
  1543.     br = 255
  1544.     zz = (zz + 1) MOD 50: IF zz = 1 THEN r! = RND: g! = RND: b! = RND
  1545.     x1 = xc - 4 * xq
  1546.     y1 = yc - 4 * yq
  1547.     x2 = x1 + 8 * xq
  1548.     y2 = y1 + 8 * yq
  1549.     FOR sy = y1 TO y2
  1550.         FOR sx = x1 TO x2
  1551.             p& = POINT(sx, sy)
  1552.             IF p& = boardwhite& THEN
  1553.                 z = ABS((sx - xc - xq \ 2) * (sy - yc - yq \ 2))
  1554.                 PSET (sx, sy), _RGB32(br * SIN(.1 * r! * z + zz), br * SIN(.155 * g! * z + zz), br * SIN(2 * b! * z + zz))
  1555.             END IF
  1556.     NEXT sx: NEXT sy
  1557.  
  1558. SUB ReadGame
  1559.     DIM g$(500)
  1560.     CLS
  1561.     OPEN GameFile$ FOR INPUT AS #8
  1562.     WHILE NOT (EOF(8))
  1563.         INPUT #8, mn, m1$, m2$
  1564.         gm = gm + 1: g$(gm) = LTRIM$(m1$)
  1565.         gm = gm + 1: g$(gm) = LTRIM$(m2$)
  1566.         PRINT m1$; "*"; m2$
  1567.     WEND
  1568.     CLOSE #8
  1569.     _DISPLAY
  1570.     SLEEP
  1571.     CLS
  1572.     _DISPLAY
  1573.  
  1574. SUB Recurse (Level)
  1575.     IF abort OR (Level = MasterLevel) THEN EXIT SUB
  1576.  
  1577.     FOR t = 1 TO Moves(Level - 1)
  1578.  
  1579.         IF Level = 1 THEN '                                                              progress bar
  1580.             x1 = xc - 4 * xq: x2 = xc + 4 * xq
  1581.             y1 = yc + 4 * yq + 20
  1582.             z1 = Moves(Level - 1): z2 = z1 - (z1 = 0)
  1583.             xx = (z1 - t + 1) / z2 * (x2 - x1)
  1584.             IF xx < x1 THEN xx = x1
  1585.             IF xx > x2 THEN xx = x2
  1586.             LINE (x1, y1)-(x2, y1), bg0&
  1587.             IF (xx - x1) > 2 THEN LINE (x1, y1)-(xx, y1), cp&(1)
  1588.  
  1589.             'x1 = 290: x2 = x1 + 50
  1590.             'y1 = 508: y2 = y1 + 64
  1591.             'LINE (x1, y1)-(x2, y2), _RGB32(222, 0, 0), B
  1592.         END IF
  1593.         WorB = SaveWorB
  1594.         IF (Level MOD 2) = 1 THEN WorB = WorB XOR 1
  1595.         TieTo(Level) = t
  1596.         IF ABS(Score(0, t)) <> 777 THEN
  1597.             _MEMCOPY m(0), m(0).OFFSET, m(0).SIZE TO m(Level), m(Level).OFFSET '         save board
  1598.             m$ = Move$(Level - 1, t)
  1599.             MoveIt m$, false
  1600.             lm1 = Level - 1
  1601.             CheckBoard Level
  1602.             Recurse Level + 1
  1603.             TakeBest Level, false
  1604.             i = Index
  1605.             Score = Score(Level, 1)
  1606.             levm1 = Level - 1
  1607.             IF Score(levm1, 1) <> 777 THEN Score(levm1, i) = Score(levm1, i) - Score
  1608.             IF Level = (MasterLevel - 1) THEN
  1609.                 KeyScan 0, 0 '                                                           no plotscreen or _display
  1610.                 'IF (tlimit > 0) AND (emin >= tlimit) THEN abort = true
  1611.                 IF abort THEN EXIT SUB
  1612.                 LogThinking
  1613.             END IF
  1614.             _MEMCOPY m(Level), m(Level).OFFSET, m(Level).SIZE TO m(0), m(0).OFFSET '     restore board
  1615.         END IF
  1616.     NEXT t
  1617.  
  1618. SUB Reset_To_Zero
  1619.     WorB = WorB XOR 1 '      reverse who's moving
  1620.     CheckBoard 1 '           need to know what opponent can do to ensre legal castling
  1621.     WorB = WorB XOR 1 '      restore playing color
  1622.     CheckBoard 0 '           determine legal moves
  1623.  
  1624. FUNCTION Rjust$ (t, n)
  1625.     Rjust$ = RIGHT$("   " + STR$(t), n)
  1626.  
  1627. SUB SaveForTakeBack STATIC '                                         use MEM later to move arrays
  1628.     FOR i = 10 TO 1 STEP -1
  1629.         castle$(i) = castle$(i - 1)
  1630.         FOR r = 1 TO 8
  1631.             FOR c = 1 TO 8
  1632.                 tb(c, r, i) = tb(c, r, i - 1)
  1633.             NEXT c
  1634.         NEXT r
  1635.     NEXT i
  1636.     castle$(0) = castle$
  1637.     FOR r = 1 TO 8
  1638.         FOR c = 1 TO 8
  1639.             tb(c, r, 0) = b(c, r)
  1640.         NEXT c
  1641.     NEXT r
  1642.     tbc = tbc + 1
  1643.     IF tbc > 10 THEN tbc = 10
  1644.  
  1645.  
  1646. SUB ScreenInit
  1647.     xm = 480: ym = 600
  1648.     MaxRow = ym \ 16 - 2
  1649.     k = 99
  1650.     SELECT CASE smode
  1651.         CASE IS = 0
  1652.             SCREEN _NEWIMAGE(xm, ym), 32
  1653.             _SCREENMOVE _DESKTOPWIDTH \ 2 - xm \ 2, _DESKTOPHEIGHT \ 2 - ym \ 2
  1654.         CASE IS = 1
  1655.             _SCREENMOVE 780, 20
  1656.         CASE IS = 2
  1657.             SCREEN _NEWIMAGE(800, 600), 32
  1658.             _SCREENMOVE 472, 20
  1659.     END SELECT
  1660.  
  1661. SUB Setup
  1662.     t1$ = "rnbkqp:black      clear:one     spacebar:flip"
  1663.     t2$ = "RNBKQP:white      Clear:all          Esc:exit"
  1664.  
  1665.     LINE (0, 500)-(xm, ym), black&, BF
  1666.     cc = 1: rr = 8
  1667.     DO
  1668.         Center -1, t1$, 0
  1669.         Center 0, t2$, 0
  1670.         _DISPLAY
  1671.         DO: _LIMIT 20
  1672.             PlotBoard
  1673.             z = z XOR 1
  1674.             IF z THEN Cursor 9 - rr, cc, 0
  1675.             i$ = INKEY$: z = LEN(i$)
  1676.         LOOP UNTIL z
  1677.         SELECT CASE z
  1678.             CASE IS = 1
  1679.                 r2 = 9 - rr
  1680.                 IF i$ = Esc$ THEN EXIT DO
  1681.                 IF (i$ = CHR$(9)) OR (i$ = "c") THEN b(cc, r2) = 0 ' Del or "c" to delete piece
  1682.                 IF i$ = "C" THEN '                                   delete all pieces
  1683.                     FOR c = 1 TO 8: FOR r = 1 TO 8
  1684.                             b(c, r) = 0
  1685.                     NEXT: NEXT
  1686.                 END IF
  1687.                 p = INSTR("rnbqkpRNBQKP", i$)
  1688.                 IF p THEN b(cc, r2) = p '                            set piece by letter
  1689.                 IF INSTR(" t", i$) THEN '                            t or space toggle color
  1690.                     mp = b(cc, r2)
  1691.                     IF mp < 7 THEN mp = mp + 6 ELSE mp = mp - 6
  1692.                     b(cc, r2) = mp
  1693.                 END IF
  1694.                 IF i$ = "x" THEN
  1695.                     FOR c = 1 TO 8
  1696.                         FOR r = 1 TO 8
  1697.                             t = b(c, r)
  1698.                             IF t THEN
  1699.                                 IF t < 7 THEN t = t + 6 ELSE t = t - 6
  1700.                                 s9(c, r) = t
  1701.                             END IF
  1702.                         NEXT r
  1703.                     NEXT c
  1704.                     FOR c = 1 TO 8
  1705.                         FOR r = 1 TO 8
  1706.                             b(c, 9 - r) = s9(c, r)
  1707.                         NEXT r
  1708.                     NEXT c
  1709.                 END IF
  1710.                 IF i$ = "z" THEN
  1711.                     RESTORE test
  1712.                     FOR r = 1 TO 8
  1713.                         FOR c = 1 TO 8
  1714.                             READ b(c, r)
  1715.                     NEXT: NEXT
  1716.                 END IF
  1717.             CASE IS = 2
  1718.                 kk = ASC(RIGHT$(i$, 1))
  1719.                 cc = cc + (kk = 75) - (kk = 77) '                    left right
  1720.                 rr = rr + (kk = 72) - (kk = 80) '                    up down
  1721.                 IF rr < 1 THEN rr = 1
  1722.                 IF rr > 8 THEN rr = 8
  1723.                 IF cc < 1 THEN cc = 1
  1724.                 IF cc > 8 THEN cc = 8
  1725.         END SELECT
  1726.     LOOP
  1727.     LINE (0, 500)-(xm, ym), black&, BF
  1728.     '                        board probably changed - reinitialize legal moves
  1729.     Reset_To_Zero
  1730.  
  1731. SUB ShowBest
  1732.     'bg1& = _RGB32(0, 90, 0)
  1733.     'LINE (22, 504)-(350, ym - 22), bg1&, BF
  1734.  
  1735.     yy = 505
  1736.     ty = yy
  1737.     tx = 29
  1738.     FOR t = 1 TO 20
  1739.         IF t <= Moves(0) THEN
  1740.             t$ = Make4$(Move$(0, t)) + Rjust$(Score(0, t), 5)
  1741.             FOR i = 1 TO LEN(t$) '                                   shift "g" up 2 pixels
  1742.                 c$ = MID$(t$, i, 1)
  1743.                 y2 = ty + (c$ = "g") * 2
  1744.                 _PRINTSTRING (tx + (i - 1) * 8, y2), c$
  1745.             NEXT
  1746.         END IF
  1747.         ty = ty + 14
  1748.         IF ty > 570 THEN ty = yy: tx = tx + 80
  1749.     NEXT t
  1750.  
  1751. SUB ShowMe (dr, dc, t$)
  1752.     EXIT SUB
  1753.     sr = CSRLIN '                                                    save row
  1754.     sc = POS(0) '                                                    save column
  1755.     IF (dr > 0) AND (dr < MaxRow) AND (dc > 0) AND (dc < 76) THEN
  1756.         LOCATE dr, dc '                                              display row & column
  1757.         PRINT t$;
  1758.     END IF
  1759.     LOCATE sr, sc '                                                  restore to old location
  1760.  
  1761. SUB ShowTime (trow, z!, Desc$)
  1762.     t! = z!
  1763.     SELECT CASE t!
  1764.         CASE IS > 3600
  1765.             unit$ = "h"
  1766.             t! = t! / 3600
  1767.         CASE IS > 60
  1768.             unit$ = "m"
  1769.             t! = t! / 60
  1770.         CASE ELSE
  1771.             unit$ = "s"
  1772.     END SELECT
  1773.     x1 = 408
  1774.     x2 = x1 - (LEN(Desc$) + 1) * 8
  1775.     yy = trow / (600 / 16) * 600 - 4
  1776.     t! = INT(t! * 1000) / 1000
  1777.     t$ = LTRIM$(STR$(t!))
  1778.     IF INSTR(t$, ".") = 0 THEN
  1779.         IF t! < 1 THEN t$ = "." + t$ ELSE t$ = t$ + "."
  1780.     END IF
  1781.     zz = 0
  1782.     WHILE INSTR(t$, ".") <> (LEN(t$) - 3)
  1783.         t$ = t$ + "0"
  1784.         zz = zz + 1
  1785.         IF zz > 5 THEN GOTO dammit
  1786.     WEND
  1787.     dammit:
  1788.  
  1789.     IF LEFT$(t$, 1) = "." THEN t$ = "0" + t$
  1790.     t$ = RIGHT$(SPACE$(10) + t$, 6)
  1791.     _PRINTSTRING (x1, yy), t$ + unit$
  1792.     _PRINTSTRING (x2, yy), Desc$
  1793.  
  1794. SUB ShowValid (cc, rr) '                                             show valid moves for piece at cursor
  1795.  
  1796.     IF (cc < 0) OR (rr < 0) OR (cc > 8) OR (rr > 8) THEN EXIT SUB
  1797.     tc = cc: tr = rr
  1798.     IF invert THEN tc = 9 - tc: tr = 9 - tr
  1799.     mp = b(tc, tr): mp = mp + (mp > 6) * 6
  1800.     z$ = alphal$(tc) + LTRIM$(STR$(9 - tr))
  1801.     t$ = z$ + ":"
  1802.     FOR i = 1 TO Moves(0)
  1803.         IF z$ = LEFT$(Move$(0, i), 2) THEN t$ = t$ + " " + RIGHT$(Move$(0, i), 2)
  1804.         IF (mp = King) AND (LEFT$(Move$(0, i), 1) = "O") THEN t$ = t$ + " " + Move$(0, i)
  1805.     NEXT i
  1806.     'IF (tc = epfc) AND (tr = epfc) THEN t$ = t$ + " ep"
  1807.  
  1808.     sw = _WIDTH \ 8 - 3
  1809.     LOCATE 2, 4: PRINT SPACE$(sw);
  1810.     LOCATE 2, 4: PRINT LEFT$(t$, sw);
  1811.     IF LEN(t$) > sw THEN PRINT "..";
  1812.  
  1813.  
  1814. SUB TakeBack '                                                       use MEM to move arrays? speed not an issue here
  1815.     IF tbc < 2 THEN EXIT SUB
  1816.     IF MakeNoise THEN PlaySound "tb" '                               so your mom knows you're cheating  :)
  1817.     castle$ = castle$(2)
  1818.     FOR r = 1 TO 8
  1819.         FOR c = 1 TO 8
  1820.             b(c, r) = tb(c, r, 2)
  1821.         NEXT c
  1822.     NEXT r
  1823.     FOR i = 0 TO 9
  1824.         castle$(i) = castle$(i + 1)
  1825.         FOR r = 1 TO 8
  1826.             FOR c = 1 TO 8
  1827.                 tb(c, r, i) = tb(c, r, i + 1)
  1828.             NEXT c
  1829.         NEXT r
  1830.     NEXT i
  1831.     tbc = tbc - 1
  1832.     Reset_To_Zero
  1833.  
  1834. SUB TakeBest (Level, final)
  1835.  
  1836.     IF final THEN '                                                  feeble attempt to vary response when scores equal
  1837.         upto = 10
  1838.         IF upto > Moves(Level) THEN upto = Moves(Level)
  1839.         FOR scram = 0 TO 199
  1840.             s1 = RND * updo + 1
  1841.             s2 = RND * upto + 1
  1842.             SWAP Score(Level, s1), Score(Level, s2)
  1843.             SWAP Move$(Level, s1), Move$(Level, s2)
  1844.             SWAP Index(Level, s1), Index(Level, s2)
  1845.         NEXT scram
  1846.     END IF
  1847.  
  1848.     passes = 0
  1849.     ReSort:
  1850.     Score = -999 '                                                   assume no moves
  1851.     DO
  1852.         Sorted = true
  1853.         FOR s = 2 TO Moves(Level)
  1854.             IF Score(Level, s - 1) < Score(Level, s) THEN
  1855.                 Sorted = false
  1856.                 SWAP Score(Level, s - 1), Score(Level, s)
  1857.                 SWAP Move$(Level, s - 1), Move$(Level, s)
  1858.                 SWAP Index(Level, s - 1), Index(Level, s)
  1859.             END IF
  1860.         NEXT s
  1861.     LOOP UNTIL Sorted
  1862.  
  1863.     m$ = Move$(Level, 1)
  1864.     Score = Score(Level, 1)
  1865.     Index = Index(Level, 1)
  1866.  
  1867.     best$ = Move$(0, 1)
  1868.     bscore = Score(0, 1)
  1869.  
  1870.     IF final AND (Level < 2) THEN
  1871.         IF Score = -777 THEN '                                       in check, no escape
  1872.             abort = 3: msg$ = "Checkmate!"
  1873.         ELSEIF Score = -999 THEN '                                   no moves
  1874.             abort = 3: msg$ = "Stalemate!"
  1875.         END IF
  1876.  
  1877.         tm = Moves(1)
  1878.         FOR lb = 1 TO 9 '                                            stop repeats
  1879.             IF tm > 8 THEN
  1880.                 IF INSTR(MoveLog$(tm - lb), m$) THEN
  1881.                     'SOUND 888, 1
  1882.                     Score(1, 1) = Score(1, 1) - 10
  1883.                     passes = passes + 1
  1884.                     IF passes < 5 THEN GOTO ReSort '                 repeat may be only move
  1885.                 END IF
  1886.             END IF
  1887.         NEXT lb
  1888.     END IF
  1889.  
  1890.     IF (Level = 1) AND (Score = 777) THEN Score(0, TieTo(1)) = -777
  1891.  
  1892. SUB TextInfo (zz$)
  1893.     IF smode <> 2 THEN EXIT SUB
  1894.  
  1895.     t$ = "History Thinking Legal Protection"
  1896.     LOCATE 3, 61
  1897.     FOR i = 1 TO LEN(t$)
  1898.         c$ = MID$(t$, i, 1)
  1899.         IF c$ = UCASE$(c$) THEN COLOR cp&(1) ELSE COLOR white&
  1900.         PRINT c$;
  1901.     NEXT
  1902.     COLOR fg0&, bg0&
  1903.  
  1904.     'LOCATE 1, 4: PRINT showthink; history; showlegalf; showprotf;
  1905.  
  1906.     z = 0
  1907.     IF showthink THEN z = 1
  1908.     IF history THEN z = 2
  1909.     IF showlegalf THEN z = 3
  1910.     IF showprotf THEN z = 4
  1911.     IF z = 0 THEN EXIT SUB
  1912.  
  1913.     IF DebugR > MaxRow THEN
  1914.         _DISPLAY
  1915.         DebugR = 3: DebugC = 61
  1916.         FOR r = DebugR TO MaxRow
  1917.             LOCATE r, DebugC
  1918.             PRINT SPACE$(100 - DebugC);
  1919.         NEXT r
  1920.     END IF
  1921.  
  1922.     SELECT CASE z '                                                  thinking
  1923.         CASE IS = 1
  1924.             DebugR = DebugR + 1
  1925.             LOCATE DebugR, DebugC
  1926.             PRINT zz$;
  1927.             IF DebugR = MaxRow THEN DebugR = 99
  1928.         CASE IS = 2 '                                                move log
  1929.             BeginAt = Move - 28
  1930.             IF BeginAt < 1 THEN BeginAt = 1
  1931.             tr = 4
  1932.             FOR i = BeginAt TO Move
  1933.                 LOCATE tr, DebugC
  1934.                 PRINT MoveLog$(i);
  1935.                 tr = tr + 1
  1936.                 IF tr > MaxRow THEN EXIT FOR
  1937.             NEXT i
  1938.         CASE IS = 3 '                                                legal
  1939.             FOR i = 1 TO Moves(0)
  1940.                 tr = i + 3
  1941.                 IF tr > MaxRow THEN EXIT FOR
  1942.                 LOCATE tr, 63
  1943.                 PRINT USING "## "; i;
  1944.                 PRINT Move$(0, i);
  1945.             NEXT i
  1946.             FOR i = 1 TO Moves(1)
  1947.                 tr = i + 3
  1948.                 IF tr > MaxRow THEN EXIT FOR
  1949.                 LOCATE tr, 73
  1950.                 PRINT USING "## "; i;
  1951.                 PRINT Move$(1, i);
  1952.             NEXT i
  1953.         CASE IS = 4 '                                                protected
  1954.             FOR i = 1 TO prot(0)
  1955.                 tr = i + 3
  1956.                 IF tr > MaxRow THEN EXIT FOR
  1957.                 LOCATE tr, 63
  1958.                 PRINT USING "## "; i;
  1959.                 PRINT prot$(0, i);
  1960.             NEXT i
  1961.             FOR i = 1 TO prot(1)
  1962.                 tr = i + 3
  1963.                 IF tr > MaxRow THEN EXIT FOR
  1964.                 LOCATE tr, 73
  1965.                 PRINT USING "## "; i;
  1966.                 PRINT prot$(1, i);
  1967.             NEXT i
  1968.     END SELECT
  1969.  
  1970. SUB TryMove (Level, fc, fr, mp, mc) '                                from row, from column
  1971.     IF mc = 1 THEN s = -1 ELSE s = 1 '                               direction a pawn moves
  1972.     incheck = (mc = SaveWorB) AND check
  1973.  
  1974.     '                  rnbqkp
  1975.     nmoves = VAL(MID$("373772", mp, 1))
  1976.  
  1977.     FOR n = 0 TO nmoves '                                            possible 8 dirs
  1978.         du = du(mp, n): dd = dd(mp, n): dl = dl(mp, n): dr = dr(mp, n)
  1979.         IF mp <> Knight THEN du = SGN(du) * s: dd = SGN(dd) * s: dl = SGN(dl) * s: dr = SGN(dr) * s
  1980.         IF du(mp, 0) = 7 THEN TrySq = 7 ELSE TrySq = 1
  1981.         IF (mp = Pawn) AND (n = 0) THEN '                            pawn first move?
  1982.             IF (fr = 2) AND (WorB = 1) THEN TrySq = 2 '              gambit for white
  1983.             IF (fr = 7) AND (WorB = 0) THEN TrySq = 2 '              gambit for black
  1984.         END IF
  1985.         tc = fc: tr = fr '                                           row, column
  1986.         fs$ = alphal$(fc) + CHR$(48 + fr) '                          from square
  1987.         cap = false
  1988.         FOR sq = 1 TO TrySq '                                        up to 7 steps in current direction
  1989.             Score = 0 '                                              must init
  1990.             tc = tc - dl + dr '                                      column=column-left+right
  1991.             tr = tr - du + dd '                                      row=row-up+down
  1992.             IF (tr < 1) OR (tr > 8) OR (tc < 1) OR (tc > 8) THEN EXIT FOR
  1993.             ts$ = alphal$(tc) + CHR$(48 + tr) '                      to square
  1994.             IF fs$ = ts$ THEN SYSTEM
  1995.             cp = b(tc, tr) '                                         capture piece
  1996.             cc = -(cp > 6) - (cp = 0) * 2 '                          capture color
  1997.             cp = cp + (cp > 6) * 6
  1998.             IF mc = cc THEN '                                        own piece
  1999.                 prot(Level) = prot(Level) + 1
  2000.                 IF prot(Level) < q1 THEN prot$(Level, prot(Level)) = fs$ + ts$
  2001.                 IF (mp = Pawn) AND (n = 0) THEN EXIT FOR
  2002.                 IF mp = Knight THEN GOTO nsquare ELSE EXIT FOR
  2003.             ELSEIF (mc XOR 1) = cc THEN '                            capture
  2004.                 IF (mp = Pawn) AND (n = 0) THEN EXIT FOR '           no diag, no cap!
  2005.                 cap = true
  2006.                 Score = Score + value(cp) * 10
  2007.                 IF value(cp) = 0 THEN Score = 777 '                  king capture
  2008.             ELSE
  2009.                 IF (mp = Pawn) AND (n > 0) THEN EXIT FOR
  2010.             END IF
  2011.  
  2012.             IF mp = King THEN
  2013.                 IF Level = 0 THEN lm = 1 ELSE lm = 0 '               wonka
  2014.                 'FOR i = 1 TO Moves(lm) '                            can any opponent piece move there?
  2015.                 '    s$ = RIGHT$(Move$(lm, i), 2)
  2016.                 'IF ts$ = s$ THEN GOTO nsquare '                     would be moving into check
  2017.                 'NEXT
  2018.                 FOR i = 1 TO prot(lm) '                              opponent piece protecting?
  2019.                     s$ = RIGHT$(prot$(lm, i), 2)
  2020.                     IF ts$ = s$ THEN GOTO nsquare '                  would be moving into check
  2021.                 NEXT
  2022.                 IF incheck THEN
  2023.                     Score = Score + 20
  2024.                 ELSE
  2025.                     IF Move < 30 THEN Score = Score - 4 '            usually not good to be moving the King
  2026.                 END IF
  2027.             ELSE
  2028.                 dis1 = ABS(fr - okr) + ABS(fc - okc) '               get closer to king
  2029.                 dis2 = ABS(tr - okr) + ABS(tc - okc)
  2030.                 Score = Score + dis1 - dis2
  2031.                 IF Move < 20 THEN
  2032.                     dir = SGN((fr - tr) * s)
  2033.                     IF dir = 1 THEN Score = Score + 2 '              move ahead at begin & mid game
  2034.                 END IF
  2035.  
  2036.                 ' priority to getting a piece off the bottom rank
  2037.                 IF (fr = 1) AND (tr > 1) AND (WorB = 1) THEN Score = Score + 1
  2038.                 IF (fr = 8) AND (tf < 8) AND (WorB = 0) THEN Score = Score + 1
  2039.                 IF mp <> Rook THEN '                                 priority to getting a piece first moved
  2040.                     IF b(fc, fr) = o(fc, fr) THEN Score = Score + 1
  2041.                 END IF
  2042.             END IF
  2043.             's1 = Score
  2044.  
  2045.             'IF (Score <> 777) AND (NOT (incheck)) THEN
  2046.  
  2047.             IF mp = Pawn THEN
  2048.                 Score = Score + TrySq
  2049.                 IF (tr = 1) OR (tr = 8) THEN '                       promote pawn
  2050.                     Score = Score + 99
  2051.                 END IF
  2052.             END IF
  2053.             'END IF
  2054.             'IF s1 = 777 THEN Score = s1
  2055.  
  2056.             AddIt Level, fs$ + ts$, Score
  2057.  
  2058.             IF cap AND (mp = Pawn) AND (n = 0) THEN EXIT FOR
  2059.             IF cap AND (mp <> Knight) THEN EXIT FOR
  2060.             nsquare:
  2061.         NEXT sq
  2062.     NEXT n
  2063.  
  2064.     IF mp = Pawn THEN '                                              en passant
  2065.         IF WorB THEN othp = 6 ELSE othp = 12 '                       opponent pawn
  2066.         l1 = 7 + (WorB = 0) * 5 '                                    rank 7 for white, 2 for black
  2067.         l2 = 5 - (WorB = 0) '                                        rank 5 for white, 6 for black
  2068.     END IF
  2069.     IF (mp = Pawn) AND (fr = l2) AND (Level < 2) THEN
  2070.         FOR z = -1 TO 1 STEP 2 '                                     look each side
  2071.             lc = fc + z '                                            look column
  2072.             IF (lc > 0) AND (lc < 9) THEN '                          in bounds of board
  2073.                 IF b(lc, fr) = othp THEN '                           it is a pawn
  2074.                     tc$ = alphal$(lc)
  2075.                     tm$ = tc$ + CHR$(48 + l1) + tc$ + CHR$(48 + l2) '  form coordinate
  2076.                     IF tm$ = lm$ THEN '                              yes, add e.p. to list of legal moves
  2077.                         epfc = fc: epfr = fr '                       en passant from row, column
  2078.                         eptc = lc: eptr = fr - s '                   en passant to row, column
  2079.                         eprc = lc: eprr = fr '                       en passant remove piece
  2080.                         ep$ = alphal$(epfc) + CHR$(48 + epfr) + alphal$(eptc) + CHR$(48 + eptr)
  2081.                         AddIt Level, ep$, 1 '                        add with score of 1
  2082.                     END IF
  2083.                 END IF
  2084.             END IF
  2085.         NEXT z
  2086.     END IF
  2087.  
  2088.  
  2089. SUB TempMess (t$, secs) STATIC
  2090.     'EXIT SUB
  2091.     zz = 100: x1 = xc - zz: x2 = xc + zz
  2092.     IF (LEN(t$) > 0) AND (t$ <> current$) THEN
  2093.         x = xc - LEN(t$) * 4
  2094.         y = 12
  2095.         LINE (x1, 0)-(x2, 28), black&, BF
  2096.         _PRINTSTRING (x, y), t$
  2097.         _DISPLAY
  2098.         current$ = t$
  2099.         mtime! = TIMER + secs: IF mtime! > maxtime& THEN mtime! = 0
  2100.     END IF
  2101.     IF (mtime! > 0) AND (TIMER > mtime!) THEN
  2102.         LINE (x1, 0)-(x2, 28), black&, BF
  2103.         _DISPLAY
  2104.         mtime! = 0
  2105.     END IF
  2106.  
  2107.  
Title: Re: A 90% complete chess engine
Post by: TempodiBasic on March 01, 2020, 12:46:39 pm
Hi Richard
thanks for fast reply

I must say that after putting all files in the same folder of chess.bas it runs ok!

here 2 little feedback if you like to get feedback otherwise don't read my following thoughts:

1 I find it very improved except for opening game, not it sees checkmate and it is able to castle, now there is mouse support except for menu. Just some trouble with Alfred, he's fun, but he sometimes doesn't let make the move.

  [ This attachment cannot be displayed inline in 'Print Page' view ]  

2  if I minimize to windows bar, when I recall the window it doesn't draw itself see screenshot

  [ This attachment cannot be displayed inline in 'Print Page' view ]  

3  Sorry I'm not able to count, if I press Spacebar I get the messagebox with New Game and Quit option... but if I make a mistake pressing spacebar I cannot go back to the game.

Thanks to share and to improve


Title: Re: A 90% complete chess engine
Post by: Richard Frost on March 01, 2020, 01:12:27 pm
It's easy to get out of synch when using the arrow keys as to the "from" and "to".
Just press Enter again on the piece, then the cursor will say "To?".  When using
the mouse there's no indication of from/to - debating if that's good or not.  Some
might like it - less distraction from the position. 

There's no book lookup for opening moves.  That I'll have to add, eventually.
Plays a pretty good game considering how minimal the scoring is in SUB TryMove.
There are still bugs - esp. that it allows you to be checked and ignore it!
When that happens I go into Setup mode, put pieces where they should be,
and resume play.  For now.  Until the bugs are fixed.

Pressing the spacebar is meant to abort further thinking by the computer.  If pressed
during your turn, indeed, the New Game or Quit menu shows.  Pressing "r" there will
return to the game.  That's a bug - will add "r" to that menu.  Maybe it should be "c"
for Continue so it doesn't get mixed up with "r" for resign. 

Probably not a good idea to run this thing against itself unattended - uses too much CPU.

This is the ultimate project for me, something I've always wanted that I can work on for
the rest of my life.  QB4.5 didn't have the oomph for it.  QB64 sure does!

It's fun to play with the colors!  A shortcut for changing the primary color is "1".   :)  And
the graphics can be given a kick to re-initialize with "G" (not "g" which changes the mode).
Title: Re: A 90% complete chess engine
Post by: Adrian on December 18, 2020, 10:49:37 am
Hi bplus snd Tempodibasic,

Wow.... it’s been a long while since i checked the forums here. Thanks fir the memories of trying to work on a chess program 😄

Cheers,
Adrian
Title: Re: A 90% complete chess engine
Post by: bplus on December 18, 2020, 11:30:35 am
@Adrian   OMG! How are you? Have you worked any more on Chess?

Richard Frost has a pretty nice one going, been working on it for awhile now.

Welcome!
Title: Re: A 90% complete chess engine
Post by: STxAxTIC on December 18, 2020, 11:45:58 am
Dude this topic was so old, I was like "man who made most of a chess engine"... Scrolled to the first post and was VERY disappointed.
Title: Re: A 90% complete chess engine
Post by: bplus on December 18, 2020, 11:58:23 am
Dude this topic was so old, I was like "man who made most of a chess engine"... Scrolled to the first post and was VERY disappointed.

LOL! I look at some of my old posts and wonder too!

@Adrian
Richard Frost is regularly updating his Chess Program here: https://www.qb64.org/forum/index.php?topic=2437.msg116514#msg116514

but the last "stable" version is in Games Board, last I heard there is a bug in current version at least a week ago.
Title: Re: A 90% complete chess engine
Post by: TempodiBasic on December 18, 2020, 09:33:11 pm
Hi Adrian
welcome back !
Have you worked on something else than chess in this time?
Title: Re: A 90% complete chess engine
Post by: Adrian on December 18, 2020, 10:56:33 pm
Hi bplus and TempodiBasic,

Ive taken a long hiatus from basic programming and chess programming, so nothing done since we last chatted here.

@bplus Richard’s program looks great, good to see others posting their chess programs like Romnichess. I’ve also seen other didactic chess programs on the www ported to QB64 like Huo Chess.

Going forward, maybe its time for me to revisit chess programming again, for fun. Have some ideas to try out.