'=========================================================================== ' Subject: PB CHESS GAME 06/99 Date: 06-21-99 (13:45) ' Author: Alexander Podkolzin Code: PB ' Origin: APP@nw.sbank.e-burg.su Packet: DEMOS.ABC '=========================================================================== '--------------------------------------------------------------------------- ' This project is not finished (some "axception" moves and main EVALUATE ' ("thinking") function), as I'm lazy and work under it about one half an ' hour a week. I'm sending this stuff to ABC-archives because I've promiced ' it to you friends. Maybe in the future I'll return to it... ' So, SEE YOU LATER!! ' ' Copyright status - FREEWARE. '--------------------------------------------------------------------------- ' IMPORTANT NOTES: ' ' A. Any move is represented by one byte variable: ' bits 7 - 4 for X-coordinate, bits 3 - 0 for Y-coordinate. ' For instance, coordinates of a piece E1 (white king) are represented ' by &H51 (01010001). I think it's very handy (e.g. see procedures/ ' functions "fPack", "UnPack"). ' ' B. Lists of moves format. ' ' All lists are strings, but I avoid to use (as far as it's possible) ' any string procedures/functions in the program, as they are slow. ' ASC/ASCII, are about 5 times faster then MID$ and at last using ' pointers we achive speed about 20 times faster then MID$. ' Example: ' mList is a string, but we count it as an array of bytes, then ' mList(1) contains number of moves (or zero) for a piece, ' mList(2) contains coordinates of a piece having been moved, ' elements from mList(3) to 29 contain all possible moves ' (or zeros) for that piece. ' All lists of moves in the program have the same structure or ' consist of such structures. ' ' C. Lists of pieces format. ' pList(1) contains number of pieces in the list, ' elements from pList(2) to 17 contain coordinates of pieces. ' '--------------------------------------------------------------------------- $DIM ALL $LIB GRAPH $COMPILE MEMORY ' $COMPILE EXE $DYNAMIC '--------------------------------------------------------------------------- %FLAGS = 0: %AX = 1: %BX = 2: %CX = 3: %DX = 4 %SI = 5: %DI = 6: %BP = 7: %DS = 8: %ES = 9 %True = -1 %False = 0 %Debug = %True %ESC_key = &H001B %Mouse_Click_Left = 1 %Mouse_Click_Right = 2 %Mark = 1 %Unmark = 0 %Opposite = -1 %Own = 1 %Absent = 0 %OutOfBoard = 99 %Pawn = 1 %Knight = 2 %Bishop = 3 %Rook = 4 %Queen = 5 %King = 6 %WhiteSide = 0 %BlackSide = 1 %White = 1 %Black = -1 %LegalMoves = 0 %CaptureFields = 1 '--------------------------------------------------------------------------- Type PieceInfo TotalMoves As Integer 'Total moves for the piece X,Y Moves As String * 29 'List of possible moves Attacked As Integer 'Attacked (total number) Defended As Integer 'Defended (total number) Attackers As String * 17 'List of attackers (coordinates) Defenders As String * 17 'List of defenders (coordinates) AttWeight As Integer 'Total weight of attackers DefWeight As Integer 'Total weight of defenders End Type '--------------------------------------------------------------------------- Type Position WhiteMoves As String * 128 'List of possible moves BlackMoves As String * 128 'List of possible moves WhiteKingAt As Byte 'Coordinates BlackKingAt As Byte 'Coordinates WhiteKingUnderCheck As Integer 'True/False BlackKingUnderCheck As Integer 'True/False WhiteKingCastlings As String * 4 'List of possible castlings BlackKingCastlings As String * 4 'List of possible castlings XY_PieceList As String * 29 'List of moves for an X,Y piece End Type '--------------------------------------------------------------------------- 'Procedures declarations list of CH.BAS : ' Declare Function MsThere() As Integer Declare Function fAllPossibleMoves( _ ChBoard() As Integer, _ Byval Owner As Integer, _ Byval TypeOfMoves As Integer _ ) As String Declare Function fColorOfBox( _ Byval X As Integer, _ Byval Y As Integer _ ) As Integer Declare Function fColorOfPiece( _ Byval X As Integer, _ Byval Y As Integer _ ) As Integer Declare Function fFindKing( _ ChBoard() As Integer, _ Byval WhichKing As Integer _ ) As Byte Declare Function fGetKey( _ Col As Integer, _ Row As Integer _ ) As Integer Declare Function fHumanPiece( _ Byval X As Integer, _ Byval Y As Integer _ ) As Integer Declare Function fInBoard( _ Byval X As Integer, _ Byval Y As Integer _ ) As Integer Declare Function fLegalMove( _ ChBoard() As Integer, _ Byval FromX As Integer, _ Byval FromY As Integer, _ Byval ToX As Integer, _ Byval ToY As Integer, _ ListOfMoves As String _ ) As Integer Declare Function fPack( _ Byval X As Integer, _ Byval Y As Integer _ ) As Byte Declare Function fPiece( _ ChBoard() As Integer, _ Byval X As Integer, _ Byval Y As Integer, _ Byval xl As Integer, _ Byval yl As Integer _ ) As Integer Declare Function fPieceName( _ Byval X As Integer, _ Byval Y As Integer _ ) As String Declare Sub DoMove( _ Byval X1 As Integer, _ Byval Y1 As Integer, _ Byval X2 As Integer, _ Byval Y2 As Integer _ ) Declare Sub ErrMessage( _ Byval Mess As String _ ) Declare Sub GenMoves( _ ChBoard() As Integer, _ Byval X As Integer, _ Byval Y As Integer, _ ListOfMoves As String, _ Byval What As Integer _ ) Declare Sub GetFieldInfo( _ ChBoard() As Integer, _ Byval X As Integer, _ Byval Y As Integer, _ Info As PieceInfo, _ Byval Mover As Integer _ ) Declare Sub GetPosition( _ ChBoard() As Integer, _ Byval X As Integer, _ Byval Y As Integer, _ PosInfo As Position _ ) Declare Sub GetScrXY( _ Byval X As Integer, _ Byval Y As Integer, _ sX As Integer, _ sY As Integer _ ) Declare Sub InitGame() Declare Sub MarkIt( _ Byval X As Integer, _ Byval Y As Integer, _ Byval State As Integer _ ) Declare Sub MkBoard() Declare Sub MkField( _ Byval X As Integer, _ Byval Y As Integer, _ Byval C As Integer _ ) Declare Sub MsCursorOff() Declare Sub MsCursorOn() Declare Sub MsLocate( _ Byval Row As Integer, _ Byval Column As Integer _ ) Declare Sub MsSetWindow( _ Byval Row As Integer, _ Byval Col As Integer, _ Byval Rows As Integer, _ Byval Cols As Integer _ ) Declare Sub MsStatus( _ Button As Integer, _ Row As Integer, _ Column As Integer _ ) Declare Sub PrepareGame() Declare Sub Show( _ Byval Num As Integer, _ Byval Xx As Integer, _ Byval Yy As Integer, _ Byval Colr As Integer _ ) Declare Sub ShowList( _ Byval ListOfMoves As String _ ) Declare Sub UnPack( _ Byval Move As Byte, _ X As Integer, _ Y As Integer _ ) '--------------------------------------------------------------------------- Dim ChessBoard(8, 8) As Shared Integer Dim Piece(%Pawn To %King) As Shared String Dim WhiteBox As Shared Integer Dim BlackBox As Shared Integer Dim WhiteC As Shared Integer Dim BlackC As Shared Integer Dim HumanPiece As Shared Integer Dim ComputerPiece As Shared Integer Dim HumanSide As Shared Integer Dim HumanMovesFirst As Shared Integer Dim CurX As Shared Integer Dim CurY As Shared Integer Dim OldX As Shared Integer Dim OldY As Shared Integer Dim MarkerColor As Shared Integer Dim i As Integer Dim MouseX As Integer Dim MouseY As Integer Dim ReadyToMove As Shared Integer Dim mList As String Dim Pinfo As PieceInfo Dim PosInfo As Position Dim PosInfo0 As Position Dim WhiteKingMoved As Shared Integer Dim BlackKingMoved As Shared Integer Dim RookA1Moved As Shared Integer Dim RookH1Moved As Shared Integer Dim RookA8Moved As Shared Integer Dim RookH8Moved As Shared Integer Dim WhiteLongCastlingPossible As Shared Integer Dim WhiteShortCastlingPossible As Shared Integer Dim BlackLongCastlingPossible As Shared Integer Dim BlackShortCastlingPossible As Shared Integer '--------------------------------------------------------------------------- If Not MsThere() Then Print "Mouse not presents!" End End If On Timer(1) Gosub ShowTime 'Every second InitGame Do PosInfo = PosInfo0 'Clear position info GetPosition ChessBoard(), 1, 1, PosInfo If HumanMovesFirst Then Gosub HumanMove Gosub ComputerMove Else Gosub ComputerMove Gosub HumanMove End If Loop Finish: Cls Screen 0,0,0,0 End '--------------------------------------------------------------------------- HumanMove: Color 10 Locate 1, 54 Print "YOUR MOVE " Do i = fGetKey(MouseX, MouseY) Select Case i Case %Mouse_Click_Left CurX = MouseX : CurY = MouseY ' If ReadyToMove Then 'Marked field If (OldX = CurX) And (OldY = CurY) Then 'At the same place ReadyToMove = %False ' OldX = 0: OldY = 0 ' MarkIt CurX, CurY, %Unmark 'Remove marker Exit Select ' Else 'Another place If fLegalMove(ChessBoard(), _ ' OldX, OldY, _ ' CurX, CurY, mList) Then ' ' DoMove OldX, OldY, CurX, CurY 'Replace piece MarkIt OldX, OldY, %Unmark 'Remove marker ReadyToMove = %False ' ' RETURN 'Move is done! ' Else 'Illegal move ErrMessage " Illegal move!" ' Iterate Loop ' End If ' End If ' End If ' If ChessBoard(CurX, CurY) = 0 Then 'Can not mark Exit Select 'empty field End If ' If Not fHumanPiece(CurX, CurY) Then 'Can not mark Exit Select 'computer's piece End If ' ReadyToMove = %True ' OldX = CurX: OldY = CurY ' MarkIt CurX, CurY, %Mark 'Make marker GetPosition ChessBoard(), CurX, CurY, PosInfo ' mList = PosInfo.XY_PieceList ' ShowList mList ' Case %ESC_key, %Mouse_Click_Right 'Exit program Goto Finish ' End Select Loop Return '--------------------------------------------------------------------------- ComputerMove: Color 10 Locate 1, 54 Print "COMPUTER MOVE" Timer On '======================================= ' "Mirror" moves for debugging: DoMove OldX, 9 - OldY, CurX, 9 - CurY '======================================= Timer Off Return '--------------------------------------------------------------------------- ShowTime: Color 14 Locate 1, 70: Print Time$ Return '--------------------------------------------------------------------------- Sub GetPosition(ChBoard() As Integer, _ Byval X As Integer, _ Byval Y As Integer, _ PosInfo As Position) Dim s As String Dim n As Integer PosInfo.WhiteMoves = fAllPossibleMoves(ChBoard(), %White, %LegalMoves) PosInfo.BlackMoves = fAllPossibleMoves(ChBoard(), %Black, %LegalMoves) PosInfo.WhiteKingAt = fFindKing(ChBoard(), %White) PosInfo.BlackKingAt = fFindKing(ChBoard(), %Black) PosInfo.WhiteKingUnderCheck = (Instr(PosInfo.BlackMoves, _ Chr$(PosInfo.WhiteKingAt)) <> 0) PosInfo.BlackKingUnderCheck = (Instr(PosInfo.WhiteMoves, _ Chr$(PosInfo.BlackKingAt)) <> 0) GenMoves ChBoard(), X, Y, s, %LegalMoves PosInfo.XY_PieceList = s ' 'Test castlings: ' n = 0 If (Not PosInfo.WhiteKingUnderCheck) And (Not WhiteKingMoved) Then ' 'White long castling ' If Not RookA1Moved Then If ChBoard(2, 1) + ChBoard(3, 1) + ChBoard(4, 1) = 0 Then If Instr(PosInfo.BlackMoves, Any Chr$(&H21, &H31, &H41)) = 0 Then Incr n Asc(PosInfo.WhiteKingCastlings, n + 2) = &H31 End If End If End If ' 'White short castling ' If Not RookH1Moved Then If ChBoard(6, 1) + ChBoard(7, 1) = 0 Then If Instr(PosInfo.BlackMoves, Any Chr$(&H61, &H71)) = 0 Then Incr n Asc(PosInfo.WhiteKingCastlings, n + 2) = &H71 End If End If End If Asc(PosInfo.WhiteKingCastlings, 1) = n Asc(PosInfo.WhiteKingCastlings, 2) = PosInfo.WhiteKingAt End If n = 0 If (Not PosInfo.BlackKingUnderCheck) And (Not BlackKingMoved) Then ' 'Black long castling ' If Not RookA8Moved Then If ChBoard(2, 8) + ChBoard(3, 8) + ChBoard(4, 8) = 0 Then If Instr(PosInfo.WhiteMoves, Any Chr$(&H28, &H38, &H48)) = 0 Then Incr n Asc(PosInfo.BlackKingCastlings, n + 2) = &H38 End If End If End If ' 'Black short castling ' If Not RookH8Moved Then If ChBoard(6, 8) + ChBoard(7, 8) = 0 Then If Instr(PosInfo.WhiteMoves, Any Chr$(&H68, &H78)) = 0 Then Incr n Asc(PosInfo.BlackKingCastlings, n + 2) = &H78 End If End If End If Asc(PosInfo.BlackKingCastlings, 1) = n Asc(PosInfo.BlackKingCastlings, 2) = PosInfo.BlackKingAt End If $IF %Debug Color 14, 0 Locate 3, 54 If PosInfo.WhiteKingUnderCheck Then ? "White king under check!" Else ? " " End If Locate 4, 54 If PosInfo.BlackKingUnderCheck Then ? "Black king under check!" Else ? " " End If Color 2 Locate 5, 54 If Ascii(PosInfo.WhiteKingCastlings, 1) <> 0 Then ? "White castling possible." Else ? " " End If Locate 6, 54 If Ascii(PosInfo.BlackKingCastlings, 1) <> 0 Then ? "Black castling possible." Else ? " " End If $ENDIF End Sub '--------------------------------------------------------------------------- ' This procedure is reserved for future needs... ' Sub GetFieldInfo(ChBoard() As Integer, _ Byval X As Integer, _ Byval Y As Integer, _ Info As PieceInfo, _ Byval Mover As Integer) Dim s As String Dim i as Integer Dim k as Integer Dim l as Integer Dim m as Integer Dim n as Integer Dim Temp As Integer GenMoves ChBoard(), X, Y, s, %LegalMoves Info.Moves = s Info.TotalMoves = Asc(s, 1) ' ' Temporary change, for defenders counting ' Temp = ChBoard(X, Y) If Mover > 0 Then ChBoard(X, Y) = - %Pawn 'If white move Else ChBoard(X, Y) = + %Pawn 'If black move End If s = fAllPossibleMoves(ChBoard(), Mover, %CaptureFields) ChBoard(X, Y) = Temp 'Restore change ' ' Selecting all pieces-defenders for the field X,Y: ' k = 1 l = 2 m = fPack(X, Y) Do While k <= Len(s) n = Asc(s, k) For i = k + 2 To k + 2 + n - 1 If Asc(s, i) = m Then Asc(Info.Defenders, l) = Asc(s, k + 1) 'Update defenders list Incr l End If Next Incr k, n + 2 Loop Decr l, 2 Asc(Info.Defenders, 1) = l 'Length of list Info.Defended = l 'Number of defenders s = fAllPossibleMoves(ChBoard(), -Mover, %LegalMoves) '-Mover for enemy ' ' Selecting all pieces-attackers for the field X,Y: ' k = 1 l = 2 m = fPack(X, Y) Do While k <= Len(s) n = Asc(s, k) For i = k + 2 To k + 2 + n - 1 If Asc(s, i) = m Then Asc(Info.Attackers, l) = Asc(s, k + 1) 'Update attackers list Incr l End If Next Incr k, n + 2 Loop Decr l, 2 Asc(Info.Attackers, 1) = l 'Length of list Info.Attacked = l 'Number of attackers Info.DefWeight = 0 For i = 1 To Asc(Info.Defenders, 1) UnPack Asc(Info.Defenders, i + 1), m, n Incr Info.DefWeight, Abs(ChBoard(m, n)) 'Weight of defenders Next Info.AttWeight = 0 For i = 1 To Asc(Info.Attackers, 1) UnPack Asc(Info.Attackers, i + 1), m, n Incr Info.DefWeight, Abs(ChBoard(m, n)) 'Weight of attackers Next End Sub '--------------------------------------------------------------------------- Function fFindKing(ChBoard() As Integer, _ Byval WhichKing As Integer) As Byte Dim x As Integer Dim y As Integer For x = 1 To 8 For y = 1 To 8 If ChBoard(x, y) = WhichKing * %King Then Function = fPack(x, y) : Exit Function End If Next Next End Function '--------------------------------------------------------------------------- Function fPack(Byval X As Integer, Byval Y As Integer) As Byte ! mov cl, 4 ;Assembler (need speed) ! mov ax, X ! shl ax, cl ! add ax, Y ! mov Function, al $IF 0 Shift Left X, 4 'BASIC Function = X + Y $ENDIF End Function '--------------------------------------------------------------------------- Sub UnPack(Byval Move As Byte, X As Integer, Y As Integer) Y = Move And &HF 'BASIC, we do not need speed here... Shift Right Move, 4 X = Move End Sub '--------------------------------------------------------------------------- Function fLegalMove(ChBoard() As Integer, _ Byval FromX As Integer, _ Byval FromY As Integer, _ Byval ToX As Integer, _ Byval ToY As Integer, _ ListOfMoves As String) As Integer Dim kInfo As PieceInfo Dim TempF As Integer Dim TempT As Integer Dim k As Byte Dim x As Integer Dim y As Integer TempF = ChBoard(FromX, FromY) TempT = ChBoard(ToX, ToY) ChBoard(FromX, FromY) = 0 ChBoard(ToX, ToY) = TempF If Abs(TempF) = %King Then GetFieldInfo ChBoard(), ToX, ToY, kInfo, Sgn(TempF) If kInfo.Attacked Then Gosub RestoreBoard Function = %False Exit Function End If Else k = fFindKing(ChBoard(), Sgn(TempF)) UnPack k, x, y GetFieldInfo ChBoard(), x, y, kInfo, Sgn(TempF) If kInfo.Attacked Then Gosub RestoreBoard Function = %False Exit Function End If End If Gosub RestoreBoard Function = (Instr(3, ListOfMoves, Chr$(fPack(ToX, ToY))) <> 0) Exit Function RestoreBoard: ChBoard(FromX, FromY) = TempF ChBoard(ToX, ToY) = TempT Return End Function '--------------------------------------------------------------------------- 'Generates "theoretically" possible moves for a piece. Sub GenMoves(ChBoard() As Integer, _ Byval X As Integer, _ Byval Y As Integer, _ ListOfMoves As String, _ Byval What As Integer) Dim It As Integer Dim n As Byte '''Integer Dim Sign As Integer Dim xl As Integer Dim yl As Integer Dim ListPtr As Byte Ptr Dim Work As Byte Ptr ' ' Max moves for one piece is 27 (queen). ' ListOfMoves = String$(29, 0) ListPtr = Strptr32(ListOfMoves) It = ChBoard(X, Y) If It > 0 Then Sign = +1 Else Sign = -1 End If n = 3 Select Case Abs(It) Case %Pawn ' ' Pawn moves: ' If What = %LegalMoves Then xl = X: yl = Y + Sign If fPiece(ChBoard(), X, Y, xl, yl) = %Absent Then 'Up Gosub SetXY If Y = 7 Or Y = 2 Then yl = Y + Sign + Sign If fPiece(ChBoard(), X, Y, xl, yl) = %Absent Then 'Up Gosub SetXY End If End If End If ' ' Pawn captures: ' yl = Y + Sign: xl = X - 1 If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then 'Up and left Gosub SetXY End If xl = X + 1 If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then 'Up and right Gosub SetXY End If Elseif What = %CaptureFields Then ' ' Pawn attacks/supports fields: ' yl = Y + Sign: xl = X - 1 Gosub SetXY 'Up and left xl = X + 1 Gosub SetXY 'Up and right End If Case %Knight If fPiece(ChBoard(), X, Y, X+1, Y-2) <> %Own Then xl=X+1: yl=Y-2: Gosub SetXY If fPiece(ChBoard(), X, Y, X+2, Y-1) <> %Own Then xl=X+2: yl=Y-1: Gosub SetXY If fPiece(ChBoard(), X, Y, X+2, Y+1) <> %Own Then xl=X+2: yl=Y+1: Gosub SetXY If fPiece(ChBoard(), X, Y, X+1, Y+2) <> %Own Then xl=X+1: yl=Y+2: Gosub SetXY If fPiece(ChBoard(), X, Y, X-1, Y+2) <> %Own Then xl=X-1: yl=Y+2: Gosub SetXY If fPiece(ChBoard(), X, Y, X-2, Y+1) <> %Own Then xl=X-2: yl=Y+1: Gosub SetXY If fPiece(ChBoard(), X, Y, X-2, Y-1) <> %Own Then xl=X-2: yl=Y-1: Gosub SetXY If fPiece(ChBoard(), X, Y, X-1, Y-2) <> %Own Then xl=X-1: yl=Y-2: Gosub SetXY Case %Bishop Gosub CheckDiagonals Case %Rook Gosub CheckLines Case %Queen Gosub CheckLines Gosub CheckDiagonals Case %King xl = X: yl = Y - 1 If fPiece(ChBoard(), X, Y, xl, yl) <> %Own Then Gosub SetXY xl = X - 1: yl = Y - 1 If fPiece(ChBoard(), X, Y, xl, yl) <> %Own Then Gosub SetXY xl = X + 1: yl = Y - 1 If fPiece(ChBoard(), X, Y, xl, yl) <> %Own Then Gosub SetXY xl = X - 1: yl = Y If fPiece(ChBoard(), X, Y, xl, yl) <> %Own Then Gosub SetXY xl = X + 1: yl = Y If fPiece(ChBoard(), X, Y, xl, yl) <> %Own Then Gosub SetXY xl = X - 1: yl = Y + 1 If fPiece(ChBoard(), X, Y, xl, yl) <> %Own Then Gosub SetXY xl = X: yl = Y + 1 If fPiece(ChBoard(), X, Y, xl, yl) <> %Own Then Gosub SetXY xl = X + 1: yl = Y + 1 If fPiece(ChBoard(), X, Y, xl, yl) <> %Own Then Gosub SetXY End Select Work = ListPtr @Work = n - 3 'Number of moves Incr Work @Work = fPack(X, Y) 'Moves from that field Exit Sub ' ' Checking lines: ' CheckLines: xl = X: yl = Y - 1 Do While yl > 0 'Up If fPiece(ChBoard(), X, Y, xl, yl) = %Own Then Exit Loop Gosub SetXY If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then Exit Loop Decr yl Loop xl = X - 1: yl = Y Do While xl > 0 'Left If fPiece(ChBoard(), X, Y, xl, yl) = %Own Then Exit Loop Gosub SetXY If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then Exit Loop Decr xl Loop xl = X + 1: yl = Y Do While xl < 9 'Right If fPiece(ChBoard(), X, Y, xl, yl) = %Own Then Exit Loop Gosub SetXY If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then Exit Loop Incr xl Loop xl = X: yl = Y + 1 Do While yl < 9 'Down If fPiece(ChBoard(), X, Y, xl, yl) = %Own Then Exit Loop Gosub SetXY If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then Exit Loop Incr yl Loop Return ' ' Checking diagonals: ' CheckDiagonals: xl = X - 1: yl = Y - 1 Do While yl = > 1 And xl > 0 'Up and left If fPiece(ChBoard(), X, Y, xl, yl) = %Own Then Exit Loop Gosub SetXY If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then Exit Loop Decr xl Decr yl Loop xl = X + 1: yl = Y - 1 Do While yl > 0 And xl < 9 'Up and right If fPiece(ChBoard(), X, Y, xl, yl) = %Own Then Exit Loop Gosub SetXY If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then Exit Loop Incr xl Decr yl Loop xl = X - 1: yl = Y + 1 Do While yl < 9 And xl > 0 'Down and left If fPiece(ChBoard(), X, Y, xl, yl) = %Own Then Exit Loop Gosub SetXY If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then Exit Loop Decr xl Incr yl Loop xl = X + 1: yl = Y + 1 Do While yl < 9 And xl < 9 'Down and right If fPiece(ChBoard(), X, Y, xl, yl) = %Own Then Exit Loop Gosub SetXY If fPiece(ChBoard(), X, Y, xl, yl) = %Opposite Then Exit Loop Incr xl Incr yl Loop Return ' ' Writting to list: ' SetXY: If fInBoard(xl, yl) Then Work = ListPtr + n - 1 @Work = fPack(xl, yl) Incr n End If Return End Sub '--------------------------------------------------------------------------- Function fAllPossibleMoves(ChBoard() As Integer, _ Byval Owner As Integer, _ Byval TypeOfMoves As Integer) As String Dim x As Integer Dim y As Integer Dim mL As String 'List of all posiible moves for Owner Dim Temp As String ' ' Owner > 0 - white side, ' Owner < 0 - black side. ' mL = "" For y = 1 To 8 For x = 1 To 8 If ChBoard(x, y) = 0 Then Iterate For If Sgn(ChBoard(x, y)) = Sgn(Owner) Then GenMoves ChBoard(), x, y, Temp, TypeOfMoves If Ascii(Temp, 1) <> 0 Then mL = mL + Rtrim$(Temp, Chr$(0)) End If End If Next Next Function = mL End Function '--------------------------------------------------------------------------- Sub ErrMessage(Byval Mess As String) Locate 27, 28 Print Mess Delay 1 Locate 27, 28 Print Space$(Len(Mess)) End Sub '--------------------------------------------------------------------------- Sub ShowList(Byval ListOfMoves As String) Dim i As Integer Dim n As Integer Dim x As Integer Dim y As Integer Dim pn As String n = Ascii(ListOfMoves, 1) 'Number of moves x = Ascii(ListOfMoves, 2) 'X, Y UnPack x, x, y 'coordinates of a piece pn = fPieceName(x, y) 'Piece name Color 2 Locate 27, 1 If n > 0 Then Print "List of moves "; Chr$(34); pn; Chr$(34); Else Print "No moves for the "; pn Exit Sub End If Color 10 Locate 29, 1 For i = 1 To n x = Ascii(ListOfMoves, i + 2) UnPack x, x, y Print Mid$("ABCDEFGH", x, 1); Ltrim$(Str$(y)); " "; Next Color 2 Locate 28, 1 Print "Length of list ="; Str$(n); End Sub '--------------------------------------------------------------------------- Function fPieceName(Byval X As Integer, Byval Y As Integer) As String Select Case Abs(ChessBoard(X, Y)) Case %Pawn : Function = "Pawn" Case %Knight : Function = "Knight" Case %Bishop : Function = "Bishop" Case %Rook : Function = "Rook" Case %Queen : Function = "Queen" Case %King : Function = "King" End Select End Function '--------------------------------------------------------------------------- Function fPiece(ChBoard() As Integer, _ Byval X As Integer, _ Byval Y As Integer, _ Byval xl As Integer, _ Byval yl As Integer) As Integer If Not fInBoard(xl, yl) Then Function = %OutOfBoard Exit Function End If If ChBoard(xl, yl) = 0 Then Function = %Absent Elseif Sgn(ChBoard(X, Y)) = Sgn(ChBoard(xl, yl)) Then Function = %Own Else Function = %Opposite End If End Function '--------------------------------------------------------------------------- Function fInBoard(Byval X As Integer, Byval Y As Integer) As Integer Function = (X > 0) And (X < 9) And (Y > 0) And (Y < 9) End Function '--------------------------------------------------------------------------- Function fHumanPiece(Byval X As Integer, Byval Y As Integer) As Integer Function = (fColorOfPiece(X, Y) <> ComputerPiece) End Function '--------------------------------------------------------------------------- Function fColorOfPiece(Byval X As Integer, Byval Y As Integer) As Integer If ChessBoard(X, Y) < 0 Then Function = BlackC Elseif ChessBoard(X, Y) > 0 Then Function = WhiteC Else Function = 0 End If End Function '--------------------------------------------------------------------------- Function fGetKey(Col As Integer, Row As Integer) As Integer Dim s As String Dim Button As Integer Dim x As Integer Dim y As Integer Do s = Inkey$ MsStatus Button, y, x x = (x - 3) \ 48 + 1 y = (y - 3) \ 48 + 1 If HumanSide Then 'Calculating Col = 9 - x : Row = y 'chess board Else 'coordinates Col = x : Row = 9 - y 'of a piece End If ' Color 14 Locate 1, 70: Print Time$ Locate 27, 25 Print Mid$("ABCDEFGH", Col, 1); Ltrim$(Str$(Row)) If Button Then Function = Button Do MsStatus Button, y, x Loop Until Button = 0 CurX = Col CurY = Row Exit Function End If Loop Until Len(s) Function = Cvi(s + Chr$(0)) End Function '--------------------------------------------------------------------------- Sub DoMove(Byval X1 As Integer, _ Byval Y1 As Integer, _ Byval X2 As Integer, _ Byval Y2 As Integer) Dim Man As Integer Dim cp As Integer Dim cba As Integer Dim cbb As Integer Dim k As Integer Dim i As Integer Dim x As Integer Dim y As Integer Man = ChessBoard(X1, Y1) Select Case Abs(Man) 'Update castling info Case %King If Man > 0 Then WhiteKingMoved = %True WhiteLongCastlingPossible = %False WhiteShortCastlingPossible = %False Else BlackKingMoved = %True BlackLongCastlingPossible = %False BlackShortCastlingPossible = %False End If Case %Rook If Man > 0 Then If X1 = 1 Then RookA1Moved = %True WhiteLongCastlingPossible = %False End If If X1 = 8 Then RookH1Moved = %True WhiteShortCastlingPossible = %False End If Else If X1 = 1 Then RookA8Moved = %True BlackLongCastlingPossible = %False End If If X1 = 8 Then RookH8Moved = %True BlackShortCastlingPossible = %False End If End If End Select ChessBoard(X1, Y1) = 0 ChessBoard(X2, Y2) = Man x = X2 y = Y2 If Man > 0 Then cp = WhiteC Elseif Man < 0 Then cp = BlackC Else Exit Sub End If cba = fColorOfBox(X1, Y1) cbb = fColorOfBox(X2, Y2) GetScrXY X1, Y1, X1, Y1 GetScrXY X2, Y2, X2, Y2 MsCursorOff k = (X1 - 1) * 48 + 3 i = (Y1 - 1) * 48 + 3 Line(k, i) - (k + 47, i + 47), cba, BF k = (X2 - 1) * 48 + 3 i = (Y2 - 1) * 48 + 3 Line(k, i) - (k + 47, i + 47), cbb, BF Show Abs(Man), x, y, cp MsCursorOn End Sub '--------------------------------------------------------------------------- Sub GetScrXY(Byval X As Integer, _ Byval Y As Integer, _ sX As Integer, _ sY As Integer) If HumanSide Then sX = 9 - X : sY = Y Else sX = X : sY = 9 - Y End If End Sub '--------------------------------------------------------------------------- Sub MarkIt(Byval X As Integer, Byval Y As Integer, Byval State As Integer) Dim k As Integer Dim i As Integer Dim c As Integer If State Then c = MarkerColor Else c = fColorOfBox(X, Y) End If GetScrXY X, Y, X, Y k = (X - 1) * 48 + 4 i = (Y - 1) * 48 + 4 MsCursorOff Color 2 Locate 27, 1: Print Space$(240); Line(k, i) - (k + 45, i + 45), c, B Line(k + 1, i + 1) - (k + 44, i + 44), c, B MsCursorOn End Sub '--------------------------------------------------------------------------- Function fColorOfBox(Byval X As Integer, Byval Y As Integer) As Integer GetScrXY X, Y, X, Y If (X + Y) Mod 2 Then Function = BlackBox Else Function = WhiteBox End If End Function '--------------------------------------------------------------------------- Sub MkBoard() Dim X As Integer Dim Y As Integer Dim CBlack As Integer Dim CWhite As Integer CBlack = BlackBox CWhite = WhiteBox For X = 1 To 8 For Y = 1 To 8 Swap CBlack, CWhite MkField X, Y, CBlack Next Swap CBlack, CWhite Next Line (0, 0) - (389, 389), 2, B Line (1, 1) - (388, 388), 2, B Color 2 Locate 26, 4 If HumanSide Then Print "H G F E D C B A" For Y = 1 To 8 Locate 2 + (Y - 1) * 3, 51: Print Mid$("12345678", Y, 1) Next Else Print "A B C D E F G H" For Y = 1 To 8 Locate 2 + (Y - 1) * 3, 51: Print Mid$("12345678", 9 - Y, 1) Next End If Color 7 End Sub '--------------------------------------------------------------------------- Sub PrepareGame() Dim i As Integer Dim k As Integer Dim c As Integer For i = 1 To 8 ChessBoard(i, 2) = %Pawn ChessBoard(i, 7) = -%Pawn next ChessBoard(1, 1) = %Rook ChessBoard(8, 1) = %Rook ChessBoard(1, 8) = -%Rook ChessBoard(8, 8) = -%Rook ChessBoard(2, 1) = %Knight ChessBoard(7, 1) = %Knight ChessBoard(2, 8) = -%Knight ChessBoard(7, 8) = -%Knight ChessBoard(3, 1) = %Bishop ChessBoard(6, 1) = %Bishop ChessBoard(3, 8) = -%Bishop ChessBoard(6, 8) = -%Bishop If HumanSide Then ChessBoard(5, 1) = %Queen ChessBoard(5, 8) = -%Queen ChessBoard(4, 1) = %King ChessBoard(4, 8) = -%King Else ChessBoard(4, 1) = %Queen ChessBoard(4, 8) = -%Queen ChessBoard(5, 1) = %King ChessBoard(5, 8) = -%King End If For i = 1 To 8 For k = 1 To 8 If ChessBoard(i, k) > 0 Then c = WhiteC Elseif ChessBoard(i, k) < 0 Then c = BlackC Else Iterate For End If Show Abs(ChessBoard(i, k)), i, k, c Next Next End Sub '--------------------------------------------------------------------------- Sub MkField(Byval X As Integer, _ Byval Y As Integer, _ Byval C As Integer) Dim Xb As Integer Dim Yb As Integer Dim Xe As Integer Dim Ye As Integer Xb = 3 + (X - 1) * 48 Yb = 3 + (Y - 1) * 48 Xe = Xb + 47 Ye = Yb + 47 Line (Xb, Yb) - (Xe, Ye), C, BF End Sub '--------------------------------------------------------------------------- Sub Show(Byval Num As Integer, _ Byval Xx As Integer, _ Byval Yy As Integer, _ Byval Colr As Integer) Dim x As Integer Dim y As Integer GetScrXY Xx, Yy, Xx, Yy x = (Xx - 1) * 48 + 10 y = (Yy - 1) * 48 + 46 Draw "C8BM" + Str$(x) + "," + Str$(y) Draw Piece(Num) ' ' Drawing some additional stuff ' Select Case Num Case %Knight Draw "C8BM" + Str$(x + 12) + "," + Str$(y - 31) Draw "URG" Case %Bishop Case %Rook Case %Queen Draw "C8BM" + Str$(x + 1) + "," + Str$(y - 24) Draw "UFL" Draw "C8BM" + Str$(x + 32) + "," + Str$(y - 24) Draw "UGR" Draw "C8BM" + Str$(x + 8) + "," + Str$(y - 29) Draw "HEFG" Draw "C8BM" + Str$(x + 25) + "," + Str$(y - 29) Draw "HEFG" Draw "C8BM" + Str$(x + 16) + "," + Str$(y - 33) Draw "HERFGL" Case %King Draw "C8BM" + Str$(x + 6) + "," + Str$(y - 21) Draw "UEHURFERDGFDLHGL" Draw "C8BM" + Str$(x + 23) + "," + Str$(y - 21) Draw "UEHURFERDGFDLHGL" Draw "C8BM" + Str$(x + 16) + "," + Str$(y - 32) Draw "HUERFDG" End Select If Num <> %Pawn Then Draw "C8BM" + Str$(x + 16) + "," + Str$(y - 10) Draw "U4L3UR3U4RD4R3DL3D4L" End If Draw "BM" + _ 'Filling area Str$(x + 17) + "," + _ Str$(y - 2) + "P" + _ Str$(Colr) + ",8" End Sub '--------------------------------------------------------------------------- Function MsThere() Public As Integer Reg %AX, 0 Call Interrupt &H33 If Reg(%AX) Then Function = %True End If End Function '--------------------------------------------------------------------------- Sub MsCursorOn() Public Reg %AX, 1 : Call Interrupt &H33 End Sub '--------------------------------------------------------------------------- Sub MsCursorOff() Public Reg %AX, 2 : Call Interrupt &H33 End Sub '--------------------------------------------------------------------------- Sub MsStatus(Button As Integer, Row As Integer, Column As Integer) Public Reg %AX, 3 : Call Interrupt &H33 Button = Reg(%BX) : Row = Reg(%DX) : Column = Reg(%CX) If (Pbvscrnmode = 7) Or (Pbvscrnmode = 0) Then Row = (Row \ 8) + 1 Column = (Column \ 8) + 1 End If End Sub '--------------------------------------------------------------------------- Sub MsLocate(Byval Row As Integer, Byval Column As Integer) Public If (Pbvscrnmode = 7) Or (Pbvscrnmode = 0) Then Row = (Row - 1) * 8 Column = (Column - 1) * 8 End If Reg %AX, 4 : Reg %CX, Column : Reg %DX, Row : Call Interrupt &H33 End Sub '--------------------------------------------------------------------------- Sub MsSetWindow(Byval Row As Integer, Byval Col As Integer, _ Byval Rows As Integer, Byval Cols As Integer) Public Rows = Row + Rows - 1 If (Pbvscrnmode = 7) Or (Pbvscrnmode = 0) Then Row = Row * 8 : Rows = Rows * 8 Col = Col * 8 : Cols = Cols * 8 End If Reg %AX, 8 : Reg %CX, Row : Reg %DX, Rows : Call Interrupt &H33 Reg %AX, 7 : Reg %CX, Col : Reg %DX, Cols : Call Interrupt &H33 MsLocate Row, Col End Sub '--------------------------------------------------------------------------- Sub InitGame() Dim s As String Piece(%Pawn) = "E2REHERE8U5HLHER2EH4U3E4R3F4D3G4FR2FGL2D6F8RFGFRF2L32" Piece(%Rook) = "E2REHER2U6R3U12HL2U7R3D3R3U3R3D3R3U3R3D3R3U3R3D7L2GD1" + _ "2R3D6R2FGFRF2L32" Piece(%Knight) = "E2REHER3U4EREH2U4E3REREREREU2HL2GLGL2G3LHLU3E5UE4R3EU" + _ "E2FERD4FRF4DFDFD6GDGDG2LG3DFRFD4R3FGFRF2L32" Piece(%Bishop) = "E2R2U1H1E1R3U5E1U6E1U5E1U4E5U3R3D3F5D4F1D5F1D6F1D4F1R" + _ "3F1G1F1R1F2L33" Piece(%Queen) = "E2REHER2EU3ER2EH13UE3F4G2F2RFRFRFRU2HUHUHUH5E4F4G2DF5" + _ "U8H3UE4RF4DG3D8E5UH2E4F4G5DGDGDGD2RERERERE2H2E4F3DG13" + _ "FR2FD3FR2FGFRF2L32" Piece(%King) = "E3H1E2R2U3E2R2H11U4E6R5F3R1U2H2U1E4R1F4D1G2D2R1E3R5F6" + _ "D4G11R2F2D3R2F2G1F3L32" WhiteBox = 7 BlackBox = 0 WhiteC = 10 BlackC = 9 MarkerColor = 12 Do Cls Print "What side do you want, (B)lack or (W)hite?" s = Input$(1) If Instr("Bb", s) Then HumanSide = %BlackSide 'Human side is black HumanMovesFirst = %False HumanPiece = BlackC ComputerPiece = WhiteC Exit Loop Elseif Instr("Ww", s) Then HumanSide = %WhiteSide 'Human side is white HumanMovesFirst = %True HumanPiece = WhiteC ComputerPiece = BlackC Exit Loop End If Sound 880, .5 Loop Screen 12 MkBoard PrepareGame MsCursorOn MsSetWindow 4, 4, 383, 386 MsLocate 194, 194 End Sub '---------------------------------------------------------------------------