{****************************************************************************} {* SETUP.PAS: This file contains the routines to either put the board in *} {* its normal start of game setup or a custom user defined setup. *} {****************************************************************************} {****************************************************************************} {* Default Board Set Pieces: Puts the pieces on the board for the normal *} {* initial configuration. *} {****************************************************************************} procedure DefaultBoardSetPieces; var row, col : RowColType; begin {*** put in the row of pawns for each player ***} for col := 1 to BOARD_SIZE do begin Board[2,col].image := PAWN; Board[7,col].image := PAWN; end; {*** blank out the middle of the board ***} for row := 3 to 6 do for col := 1 to BOARD_SIZE do Board[row,col].image := BLANK; {*** put in white's major pieces and then copy for black ***} Board[1,1].image := ROOK; Board[1,2].image := KNIGHT; Board[1,3].image := BISHOP; Board[1,4].image := QUEEN; Board[1,5].image := KING; Board[1,6].image := BISHOP; Board[1,7].image := KNIGHT; Board[1,8].image := ROOK; for col := 1 to BOARD_SIZE do Board[8,col] := Board[1,col]; {*** set the piece colors for each side ***} for row := 1 to 4 do for col := 1 to BOARD_SIZE do begin Board[row,col].color := C_WHITE; Board[row,col].HasMoved := false; Board[row+4,col].color := C_BLACK; Board[row+4,col].HasMoved := false; end; end; {DefaultBoardSetPieces} {****************************************************************************} {* Default Board: Sets the pieces in their default positions and sets *} {* some of the player attributes to their defaults. Some of the *} {* attributes of the game are also set to their startup values. *} {****************************************************************************} procedure DefaultBoard; var row,col : RowColType; begin DefaultBoardSetPieces; {*** player attributes ***} with Player[C_WHITE] do begin CursorRow := 2; CursorCol := 4; InCheck := false; KingRow := 1; KingCol := 5; ElapsedTime := 0; LastMove.FromRow := NULL_MOVE; end; with Player[C_BLACK] do begin CursorRow := 7; CursorCol := 4; InCheck := false; KingRow := 8; KingCol := 5; ElapsedTime := 0; LastMove.FromRow := NULL_MOVE; end; {*** game attributes ***} Game.MoveNum := 1; Game.MovesStored := 0; Game.GameFinished := false; Game.MovesPointer := 0; Game.InCheck[0] := false; Game.NonDevMoveCount[0] := 0; end; {DefaultBoard} {****************************************************************************} {* Setup Board: Input a custom configuration of the pieces on the board *} {* from the user. Will anyone actually read these comments. The user *} {* moves the cursor to the square to be changed, and presses the key to *} {* select the piece to put there. The standards K Q R B N P select a *} {* piece and SPACE blanks out the square. The user can also clear the *} {* board or ask for the default setup. RETURN saves the changes and asks *} {* the user for the move number to continue the game from. ESCAPE *} {* restores the setup upon entry to this routine and exits back to the *} {* main menu. This routine is called from the main menu. *} {****************************************************************************} {$ifdef FPCHESS_DISPLAY_ON} procedure SetupBoard; var row, col, ClearRow, ClearCol : RowColType; key : char; image : PieceImageType; LegalKey, InvalidSetup : boolean; KingCount, Attacked, _Protected, Error, NewMoveNum : integer; TempStr : string80; SaveGame : GameType; {----------------------------------------------------------------------------} { Put Piece On Board: Puts the global Image onto the board at the cursor } { position. If the image is not a blank, then the user is asked for the } { color (B or W). If the piece is a rook or king being placed in the } { piece's startup position, the user is asked if the piece has been moved } { since the start of the game. } {----------------------------------------------------------------------------} procedure PutPieceOnBoard; var KingHomeRow, PawnHomeRow : RowColType; begin Board[row,col].image := image; if (image = BLANK) then begin Board[row,col].color := C_WHITE; Board[row,col].HasMoved := false; end else begin {*** get color ***} DisplayInstructions (INS_SETUP_COLOR); repeat key := GetKey; until (key = 'B') or (key = 'W'); {*** check if piece has moved ***} if key = 'W' then begin Board[row,col].color := C_WHITE; KingHomeRow := 1; PawnHomeRow := 2; end else begin Board[row,col].color := C_BLACK; KingHomeRow := 8; PawnHomeRow := 7; end; {*** may have to ask if piece has been moved ***} if ((image = KING) and (row = KingHomeRow) and (col = 5)) or ((image = ROOK) and (row = KingHomeRow) and ((col = 1) or (col = 8))) then begin DisplayInstructions (INS_SETUP_MOVED); repeat key := GetKey; until (key = 'Y') or (key = 'N'); Board[row,col].HasMoved := key = 'Y'; end else Board[row, col].HasMoved := not ((image = PAWN) and (row = PawnHomeRow)); DisplaySquare (row, col, false); DisplayInstructions (INS_SETUP); end; end; {PutPieceOnBoard} {----------------------------------------------------------------------------} { Check Valid Setup: Makes sure that each player has exactly one king on } { the board and updates the Player's King location attributes. Both kings } { cannot be in check. The other relevant player attributes are set to. } {----------------------------------------------------------------------------} procedure CheckValidSetup; const NULL_ROW = NULL_MOVE; var row, col : RowColType; begin {*** locate kings ***} Player[C_WHITE].KingRow := NULL_ROW; Player[C_BLACK].KingRow := NULL_ROW; KingCount := 0; for row := 1 to BOARD_SIZE do for col := 1 to BOARD_SIZE do if (Board[row, col].image = KING) then begin KingCount := KingCount + 1; Player[Board[row, col].color].KingRow := row; Player[Board[row, col].color].KingCol := col; end; InvalidSetup := (KingCount <> 2) or (Player[C_WHITE].KingRow = NULL_ROW) or (Player[C_BLACK].KingRow = NULL_ROW); {*** make sure both kings are not in check ***} if not InvalidSetup then begin AttackedBy (Player[C_WHITE].KingRow, Player[C_WHITE].KingCol, Attacked, _Protected); Player[C_WHITE].InCheck := (Attacked <> 0); AttackedBy (Player[C_BLACK].KingRow, Player[C_BLACK].KingCol, Attacked, _Protected); Player[C_BLACK].InCheck := (Attacked <> 0); InvalidSetup := (Player[C_WHITE].InCheck) and (Player[C_BLACK].InCheck); end; {*** set other player attributes ***} Game.GameFinished := false; with Player[C_WHITE] do begin CursorRow := 2; CursorCol := 4; LastMove.FromRow := NULL_MOVE; end; with Player[C_BLACK] do begin CursorRow := 7; CursorCol := 4; LastMove.FromRow := NULL_MOVE; end; DisplayConversationArea; {*** report invalid setup ***} if InvalidSetup then begin SetColor (White); SetFillStyle (SolidFill, Black); Bar (0,INSTR_LINE, GetMaxX, GetMaxY); SetTextStyle (TriplexFont, HorizDir, 3); OutTextXY (0,INSTR_LINE, 'Illegal Setup - King(s) not set correctly. Press Key.'); MakeSound (false); while GetKey = 'n' do ; DisplayInstructions (INS_SETUP); end; end; {CheckValidSetup} {----------------------------------------------------------------------------} { Get Move Num: Asks the user for the next move number of the game and } { whose turn it is to move next. If one of the players is in check, then } { that player is the one who must move next and the latter question is not } { asked. } {----------------------------------------------------------------------------} procedure GetMoveNum; const ex = 190; ey = 40; var cx, cy : integer; begin DisplayInstructions (INS_SETUP_MOVENUM); Game.MovesStored := 0; Game.MovesPointer := 0; Game.InCheck[0] := (Player[C_WHITE].InCheck) or (Player[C_BLACK].InCheck); {*** open up 'window' ***} cx := (BOARD_X1 + BOARD_X2) div 2; cy := (BOARD_Y1 + BOARD_Y2) div 2; SetFillStyle (SolidFill, DarkGray); Bar (cx - ex, cy - ey, cx + ex, cy + ey); {*** ask for move number ***} SetTextStyle (DefaultFont, HorizDir, 2); SetColor (Yellow); Str ((Game.MoveNum + 1) div 2, TempStr); UserInput (67, cy - 18, 4, 'Move Number: ', TempStr); Val (TempStr, NewMoveNum, Error); if Error <> 0 then NewMoveNum := 1 else NewMoveNum := NewMoveNum * 2 - 1; {*** ask for whose turn to move next if not in check ***} if Game.InCheck[0] then begin if Player[C_BLACK].InCheck then NewMoveNum := NewMoveNum + 1 end else begin if Game.MoveNum mod 2 = 1 then TempStr := 'W' else TempStr := 'B'; UserInput (67, cy + 4, 1, 'Next Player (B/W): ', TempStr); if TempStr = 'B' then NewMoveNum := NewMoveNum + 1; end; Game.MoveNum := NewMoveNum; Game.NonDevMoveCount[0] := 0; DisplayWhoseMove; end; {GetMoveNum} {----------------------------------------------------------------------------} begin {SetupBoard} DisplayInstructions (INS_SETUP); {*** remember old setup incase of escape ***} SaveGame := Game; SaveGame.Player := Player; SaveGame.FinalBoard := Board; row := 4; col := 4; repeat repeat {*** move cursor and get key ***} MoveCursor (row, col, C_WHITE, false, key); LegalKey := true; {*** interpret key ***} case key of 'K': image := KING; 'Q': image := QUEEN; 'R': image := ROOK; 'B': image := BISHOP; 'N': image := KNIGHT; 'P': begin image := PAWN; if (row = 1) or (row = 8) then begin LegalKey := false; MakeSound (false); end; end; ' ': image := BLANK; {*** clear board ***} 'C': begin for ClearRow := 1 to BOARD_SIZE do for ClearCol := 1 to BOARD_SIZE do Board[ClearRow, ClearCol].image := BLANK; DisplayBoard; LegalKey := false; end; {*** default setup of pieces ***} 'D': begin DefaultBoardSetPieces; DisplayBoard; LegalKey := false; end; else LegalKey := false; end; if LegalKey then PutPieceOnBoard; until (key = 'e') or (key = 'x'); {*** make sure setup is valid and repeat above if not ***} if (key = 'x') then InvalidSetup := false else CheckValidSetup; until not InvalidSetup; if (key = 'x') then begin {*** restore the old setup if user presses escape ***} Game := SaveGame; Player := SaveGame.Player; Board := SaveGame.FinalBoard; end else GetMoveNum; DisplayBoard; end; {SetupBoard} {$endif} {*** end of SETUP.PAS include file ***}