diff --git a/applications/fpchess/engines/kcchess/MOVES.PAS b/applications/fpchess/engines/kcchess/MOVES.PAS
new file mode 100644
index 000000000..2a8f4a098
--- /dev/null
+++ b/applications/fpchess/engines/kcchess/MOVES.PAS
@@ -0,0 +1,534 @@
+{****************************************************************************}
+{* MOVES.PAS: This file contains the routines which generate, move, and *}
+{* otherwise have to do (on a low level) with moves. *}
+{****************************************************************************}
+
+{****************************************************************************}
+{* Attacked By: Given the row and column of a square, this routine will *}
+{* tally the number of other pieces which attack (enemy pieces) or protect *}
+{* (friendly pieces) the piece on that square. This is accomplished by *}
+{* looking around the piece to all other locations from which a piece *}
+{* could protect or protect. This routine does not count an attack by *}
+{* en passent. This routine is called to see if a king is in check and *}
+{* as part of the position strength calculation. *}
+{****************************************************************************}
+ procedure AttackedBy (row, col : RowColType; var Attacked, _Protected : integer);
+ var dir, i, distance : integer;
+ PosRow, PosCol, IncRow, IncCol : RowColType;
+ FriendColor, EnemyColor : PieceColorType;
+ begin
+ {*** initialize ***}
+ Attacked := 0;
+ _Protected := 0;
+ FriendColor := Board[row, col].color;
+ if (FriendColor = C_WHITE) then begin
+ dir := 1; {*** row displacement from which an enemy pawn would attack ***}
+ EnemyColor := C_BLACK;
+ end else begin
+ dir := -1;
+ EnemyColor := C_WHITE;
+ end;
+
+ {*** count number of attacking pawns ***}
+ with Board[row + dir, col - 1] do
+ if (image = PAWN) and (color = EnemyColor) then Attacked := Attacked + 1;
+ with Board[row + dir, col + 1] do
+ if (image = PAWN) and (color = EnemyColor) then Attacked := Attacked + 1;
+
+ {*** count number of protecting pawns ***}
+ with Board[row - dir, col - 1] do
+ if (image = PAWN) and (color = FriendColor) then _Protected := _Protected + 1;
+ with Board[row - dir, col + 1] do
+ if (image = PAWN) and (color = FriendColor) then _Protected := _Protected + 1;
+
+ {*** check for a knight in all positions from which it could attack/protect ***}
+ for i := 1 to PossibleMoves[KNIGHT].NumDirections do begin
+ with PossibleMoves[KNIGHT].UnitMove[i] do begin
+ PosRow := row + DirRow;
+ PosCol := col + DirCol;
+ end;
+ if (Board[PosRow, PosCol].image = KNIGHT) then begin
+ {*** color determines if knight is attacking or protecting ***}
+ if (Board[PosRow, PosCol].color = FriendColor) then
+ _Protected := _Protected + 1
+ else
+ Attacked := Attacked + 1;
+ end;
+ end;
+
+ {*** check for king, queen, bishop, and rook attacking or protecting ***}
+ for i := 1 to 8 do begin
+ {*** get the current search direction ***}
+ with PossibleMoves[QUEEN].UnitMove[i] do begin
+ IncRow := DirRow;
+ IncCol := DirCol;
+ end;
+ {*** set distance countdown and search position ***}
+ distance := 7;
+ PosRow := row;
+ PosCol := col;
+
+ {*** search until something is run into ***}
+ while distance > 0 do begin
+ {*** get new position and check it ***}
+ PosRow := PosRow + IncRow;
+ PosCol := PosCol + IncCol;
+ with Board[PosRow, PosCol] do begin
+ if ValidSquare then begin
+ if image = BLANK then
+ {*** continue searching if search_square is blank ***}
+ distance := distance - 1
+ else begin
+ {*** separate cases of straight or diagonal attack/protect ***}
+ if (IncRow = 0) or (IncCol = 0) then begin
+ {*** straight: check for queen, rook, or one-away king ***}
+ if (image = QUEEN) or (image = ROOK) or
+ ((image = KING) and (distance = 7)) then
+ if (color = FriendColor) then
+ _Protected := _Protected + 1
+ else
+ Attacked := Attacked + 1;
+ end else begin
+ {*** diagonal: check for queen, bishop, or one-away king ***}
+ if (image = QUEEN) or (image = BISHOP) or
+ ((image = KING) and (distance = 7)) then
+ if (color = FriendColor) then
+ _Protected := _Protected + 1
+ else
+ Attacked := Attacked + 1;
+ end;
+ {*** force to stop searching if piece encountered ***}
+ distance := 0;
+ end;
+ end else
+ {*** force to stop searching if border of board encountered ***}
+ distance := 0;
+ end;
+ end;
+ end;
+ end; {AttackedBy}
+
+{****************************************************************************}
+{* Gen Move List: Returns the list of all possible moves for the given *}
+{* player. Searches the board for all pieces of the given color, and *}
+{* adds all of the possible moves for that piece to the move list to be *}
+{* returned. *}
+{****************************************************************************}
+ procedure GenMoveList (Turn : PieceColorType; var Movelist : MoveListType);
+ var row, col : RowColType;
+
+{----------------------------------------------------------------------------}
+{ Gen Piece Move List: Generates all of the moves for the given piece at }
+{ the given board position, and adds them to the move list for the player. }
+{ If the piece is a pawn then all of the moves are checked by brute force. }
+{ If the piece is a king, then the castling move is checked by brute force. }
+{ For all other moves, each allowed direction for the piece is checked, and }
+{ each square off in that direction from the piece, up to the piece's move }
+{ distance limit, is added to the list, until the edge of the board is }
+{ encountered or another piece is encountered. If the piece encountered }
+{ is an enemy piece, then taking that enemy piece is added to the player's }
+{ move list as well. }
+{----------------------------------------------------------------------------}
+ procedure GenPieceMoveList (Piece : PieceType; row, col : integer);
+ var dir : integer;
+ PosRow, PosCol : RowColType; {*** current scanning position ***}
+ OrigRow, OrigCol : RowColType; {*** location to search from ***}
+ IncRow, IncCol : integer; {*** displacement to add to scanning position ***}
+ DirectionNum : 1..8;
+ distance : 0..7;
+ EPPossible : boolean;
+ EnemyColor : PieceColorType;
+ Attacked, _Protected : integer;
+
+{----------------------------------------------------------------------------}
+{ Gen Add Move: Adds the move to be generated to the player's move list. }
+{ Given the location and displacement to move the piece, takes PieceTaken }
+{ and PieceMoved from the current board configuration. }
+{----------------------------------------------------------------------------}
+ procedure GenAddMove (row, col : RowColType; drow, dcol : integer);
+ begin
+ MoveList.NumMoves := MoveList.NumMoves + 1;
+ with MoveList.Move[MoveList.NumMoves] do begin
+ FromRow := row;
+ FromCol := col;
+ ToRow := row + drow;
+ ToCol := col + dcol;
+ PieceTaken := Board [ToRow, ToCol];
+ PieceMoved := Board [FromRow, FromCol];
+ {*** get image of piece after it is moved... ***}
+ {*** same as before the movement except in the case of pawn promotion ***}
+ MovedImage := Board [FromRow, FromCol].image;
+ end;
+ end; {GenAddMove}
+
+{----------------------------------------------------------------------------}
+{ Gen Add Pawn Move: Adds the move to be generated for a pawn to the }
+{ player's move list and checks for pawn promotion. }
+{----------------------------------------------------------------------------}
+ procedure GenAddPawnMove (row, col : RowColType; drow, dcol : integer);
+ begin
+ GenAddMove (row, col, drow, dcol);
+ {*** if pawn will move to an end row ***}
+ if (row + drow = 1) or (row + drow = 8) then
+ {*** assume the pawn will be promoted to a queen ***}
+ MoveList.Move[MoveList.NumMoves].MovedImage := QUEEN;
+ end; {GenAddPawnMove}
+
+{----------------------------------------------------------------------------}
+ begin {GenPieceMoveList}
+ OrigRow := row;
+ OrigCol := col;
+
+ {*** pawn movement is a special case ***}
+ if Piece.image = PAWN then begin
+ {*** check for En Passent ***}
+ if Piece.color = C_WHITE then begin
+ dir := 1;
+ EPPossible := (row = 5);
+ EnemyColor := C_BLACK;
+ end else begin
+ dir := -1;
+ EPPossible := (row = 4);
+ EnemyColor := C_WHITE;
+ end;
+ {*** make sure enemy's last move was push pawn two, beside player's pawn ***}
+ with Player[EnemyColor].LastMove do begin
+ if EPPossible and Game.EnPassentAllowed and (FromRow <> NULL_MOVE) then
+ if (abs (FromRow - ToRow) = 2) then
+ if (abs (ToCol - col) = 1) and (PieceMoved.image = PAWN) then
+ GenAddPawnMove (row, col, dir, ToCol - col);
+ end;
+
+ {*** square pawn is moving to (1 or 2 ahead) is guaranteed to be valid ***}
+ if (Board [row + dir, col].image = BLANK) then begin
+ GenAddPawnMove (row, col, dir, 0);
+ {*** see if pawn can move two ***}
+ if (not Piece.HasMoved) and (Board [row + 2*dir, col].image = BLANK) then
+ GenAddPawnMove (row, col, 2*dir, 0);
+ end;
+
+ {*** check for pawn takes to left ***}
+ with Board[row + dir, col - 1] do begin
+ if (image <> BLANK) and (color = EnemyColor) and ValidSquare then
+ GenAddPawnMove (row, col, dir, -1);
+ end;
+
+ {*** check for pawn takes to right ***}
+ with Board[row + dir, col + 1] do begin
+ if (image <> BLANK) and (color = EnemyColor) and ValidSquare then
+ GenAddPawnMove (row, col, dir, +1);
+ end;
+ end else begin
+ {*** check for the king castling ***}
+ if (Piece.image = KING) and (not Piece.HasMoved) and (not Player[Turn].InCheck) then begin
+ {*** check for castling to left ***}
+ if (Board [row, 1].image = ROOK) and (not Board [row, 1].HasMoved) then
+ if (Board [row, 2].image = BLANK) and (Board [row, 3].image = BLANK)
+ and (Board [row, 4].image = BLANK) then begin
+ {*** make sure not moving through check ***}
+ Board [row, 4].color := Turn;
+ AttackedBy (row, 4, Attacked, _Protected);
+ if (Attacked = 0) then
+ GenAddMove (row, 5, 0, -2);
+ end;
+
+ {*** check for castling to right ***}
+ if (Board [row, 8].image = ROOK) and (not Board [row, 8].HasMoved) then
+ if (Board [row, 6].image = BLANK) and (Board [row, 7].image = BLANK) then begin
+ {*** make sure not moving through check ***}
+ Board [row, 6].color := Turn;
+ AttackedBy (row, 6, Attacked, _Protected);
+ if (Attacked = 0) then
+ GenAddMove (row, 5, 0, 2);
+ end;
+ end;
+
+ {*** Normal moves: for each allowed direction of the piece... ***}
+ for DirectionNum := 1 to PossibleMoves [Piece.image].NumDirections do begin
+ {*** initialize search ***}
+ distance := PossibleMoves [Piece.image].MaxDistance;
+ PosRow := OrigRow;
+ PosCol := OrigCol;
+ with PossibleMoves[Piece.image].UnitMove[DirectionNum] do begin
+ IncRow := DirRow;
+ IncCol := DirCol;
+ end;
+
+ {*** search until something is run into ***}
+ while distance > 0 do begin
+ PosRow := PosRow + IncRow;
+ PosCol := PosCol + IncCol;
+ with Board [PosRow, PosCol] do begin
+ if (not ValidSquare) then
+ distance := 0
+ else begin
+ if image = BLANK then begin
+ {*** sqaure is empty: can move there; keep searching ***}
+ GenAddMove (OrigRow, OrigCol, PosRow - OrigRow, PosCol - OrigCol);
+ distance := distance - 1;
+ end else begin
+ {*** piece is there: can take if enemy; stop searching ***}
+ distance := 0;
+ if color <> Turn then
+ GenAddMove (OrigRow, OrigCol, PosRow - OrigRow, PosCol - OrigCol);
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end; {GenPieceMoveList}
+
+{----------------------------------------------------------------------------}
+ begin {GenMoveList}
+ {*** empty out player's move list ***}
+ MoveList.NumMoves := 0;
+
+ {*** search for player's pieces on board ***}
+ for row := 1 to BOARD_SIZE do
+ for col := 1 to BOARD_SIZE do
+ with Board [row, col] do begin
+ {*** if player's piece, add its moves ***}
+ if (image <> BLANK) and (color = Turn) then
+ GenPieceMoveList (Board [row, col], row, col);
+ end;
+ end; {GenMoveList}
+
+{****************************************************************************}
+{* Make Move: Update the Board to reflect making the given movement. If *}
+{* given is a PermanentMove, then the end of game pointers is set to the *}
+{* current move. Returns the score for the move, which is given by the *}
+{* number of points for the piece taken. *}
+{****************************************************************************}
+ procedure MakeMove (Movement : MoveType; PermanentMove : boolean; var Score : integer);
+ var Row: RowColType;
+ Attacked, _Protected : integer;
+
+ begin
+ Score := 0;
+ {*** update board for most moves ***}
+ with Movement do begin
+ {*** pick piece up ***}
+ Board[FromRow, FromCol].image := BLANK;
+ {*** put piece down ***}
+ Board[ToRow, ToCol] := PieceMoved;
+ end;
+
+ {*** check for en passent, pawn promotion, and castling ***}
+ case Movement.PieceMoved.image of
+ PAWN: begin
+ {*** en passent: blank out square taken; get points ***}
+ if (Movement.FromCol <> Movement.ToCol) and (Movement.PieceTaken.image = BLANK) then begin
+ Board[Movement.FromRow, Movement.ToCol].image := BLANK;
+ Score := Score + CapturePoints[PAWN];
+ end;
+
+ {*** pawn promotion: use the after-moved image; get trade-up points ***}
+ if Movement.PieceMoved.color = C_WHITE then Row := 8 else Row := 1;
+ if Movement.ToRow = Row then begin
+ Board[Movement.ToRow, Movement.ToCol].image := Movement.MovedImage;
+ Score := Score + CapturePoints[Movement.MovedImage] - CapturePoints[PAWN];
+ end;
+ end;
+
+ KING: begin
+ {*** update king position in player record ***}
+ with Player[Movement.PieceMoved.color] do begin
+ KingRow := Movement.ToRow;
+ KingCol := Movement.ToCol;
+ end;
+
+ {*** castling left/right: move the rook too ***}
+ if abs (Movement.FromCol - Movement.ToCol) > 1 then begin
+ if (Movement.ToCol < Movement.FromCol) then begin
+ Board[Movement.FromRow, 4] := Board[Movement.FromRow, 1];
+ Board[Movement.FromRow, 4].HasMoved := true;
+ Board[Movement.FromRow, 1].image := BLANK;
+ end else begin
+ Board[Movement.FromRow, 6] := Board[Movement.FromRow, 8];
+ Board[Movement.FromRow, 6].HasMoved := true;
+ Board[Movement.FromRow, 8].image := BLANK;
+ end;
+ end;
+ end;
+ end;
+
+ {*** update player attributes ***}
+ Player[Movement.PieceMoved.color].LastMove := Movement;
+ Player[Movement.PieceMoved.color].InCheck := false;
+ with Player[EnemyColor[Movement.PieceMoved.color]] do begin
+ AttackedBy (KingRow, KingCol, Attacked, _Protected);
+ InCheck := Attacked <> 0;
+ end;
+
+ {*** remember that piece has been moved, get score ***}
+ Board[Movement.ToRow, Movement.ToCol].HasMoved := true;
+ Score := Score + CapturePoints[Movement.PieceTaken.image];
+
+ {*** update game attributes ***}
+ Game.MoveNum := Game.MoveNum + 1;
+ Game.MovesPointer := Game.MovesPointer + 1;
+ Game.Move[Game.MovesPointer] := Movement;
+ if PermanentMove then
+ Game.MovesStored := Game.MovesPointer;
+ Game.InCheck[Game.MovesPointer] := Attacked <> 0;
+
+ {*** update nondevelopmental moves counter ***}
+ if (Movement.PieceMoved.image = PAWN) or (Movement.PieceTaken.image <> BLANK) then begin
+ Game.NonDevMoveCount[Game.MovesPointer] := 0;
+ end else begin
+ {*** if 50 nondevelopmental moves in a row: stalemate ***}
+ Game.NonDevMoveCount[Game.MovesPointer] := Game.NonDevMoveCount[Game.MovesPointer-1] + 1;
+ if (Game.NonDevMoveCount[Game.MovesPointer] >= NON_DEV_MOVE_LIMIT) then
+ Score := STALE_SCORE;
+ end;
+ end; {MakeMove}
+
+{****************************************************************************}
+{* Un Make Move: Updates the board for taking back the last made move. *}
+{* This routine returns (is not given) the last made movement (so it may *}
+{* be passed to DisplayUnMadeMove). *}
+{****************************************************************************}
+ procedure UnMakeMove (var Movement: Movetype);
+ begin
+ {*** make sure there is a move to un-make ***}
+ if (Game.MovesPointer > 0) then begin
+ Movement := Game.Move[Game.MovesPointer];
+ {*** restore whether player who made move was in check ***}
+ Player[Movement.PieceMoved.color].InCheck := Game.InCheck[Game.MovesPointer - 1];
+ {*** the enemy could not have been in check ***}
+ Player[EnemyColor[Movement.PieceMoved.color]].InCheck := false;
+ {*** restore the From and To squares ***}
+ Board[Movement.FromRow, Movement.FromCol] := Movement.PieceMoved;
+ Board[Movement.ToRow, Movement.ToCol] := Movement.PieceTaken;
+
+ {*** special cases ***}
+ case Movement.PieceMoved.image of
+ KING: begin
+ {*** restore position of king in player attributes ***}
+ with Player[Movement.PieceMoved.color] do begin
+ KingRow := Movement.FromRow;
+ KingCol := Movement.FromCol;
+ end;
+ {*** un-castle left/right if applicable ***}
+ if abs (Movement.FromCol - Movement.ToCol) > 1 then begin
+ if (Movement.FromCol < Movement.ToCol) then begin
+ Board[Movement.FromRow, 8] := Board[Movement.FromRow, 6];
+ Board[Movement.FromRow, 6].image := BLANK;
+ Board[Movement.FromRow, 8].HasMoved := false;
+ end else begin
+ Board[Movement.FromRow, 1] := Board[Movement.FromRow, 4];
+ Board[Movement.FromRow, 4].image := BLANK;
+ Board[Movement.FromRow, 1].HasMoved := false;
+ end;
+ end;
+ end;
+
+ PAWN:
+ {*** un-en passent: restore the pawn that was taken ***}
+ if (Movement.FromCol <> Movement.ToCol) and (Movement.PieceTaken.image = BLANK) then
+ with Board[Movement.FromRow, Movement.ToCol] do begin
+ image := PAWN;
+ if Movement.PieceMoved.color = C_WHITE then
+ color := C_BLACK
+ else
+ color := C_WHITE;
+ HasMoved := true;
+ end;
+ end;
+
+ {*** roll back move number and pointer ***}
+ Game.MoveNum := Game.MoveNum - 1;
+ Game.MovesPointer := Game.MovesPointer - 1;
+
+ {*** restore player previous move attributes ***}
+ if (Game.MovesPointer > 1) then
+ Player[Movement.PieceMoved.color].LastMove := Game.Move[Game.MovesPointer - 1]
+ else
+ Player[Movement.PieceMoved.color].LastMove.FromRow := NULL_MOVE;
+ end else
+ {*** indicate no move to take back ***}
+ Movement.FromRow := NULL_MOVE;
+ end; {UnMakeMove}
+
+{****************************************************************************}
+{* Trim Checks: Given a move list, remove all of the moves which would *}
+{* result in the given player moving into check. This is not done *}
+{* directly by GenMoveList because it is an expensive operation, since *}
+{* each move will have to be made and then unmade. This routine is called *}
+{* by the Human Movement routine. The Computer Movement routine *}
+{* incorporates this code into its code, since the moves have to be made *}
+{* and unmade there anyway. *}
+{****************************************************************************}
+ procedure TrimChecks (Turn : PieceColorType; var MoveList : MoveListType);
+ var DummyMove : MoveType;
+ DummyScore, Attacked, _Protected : integer;
+ ValidMoves, i : integer;
+
+ begin
+ ValidMoves := 0;
+ for i := 1 to MoveList.NumMoves do begin
+ MakeMove (MoveList.Move[i], false, DummyScore);
+ {*** check if the king is attacked (in check) ***}
+ AttackedBy (Player[Turn].KingRow, Player[Turn].KingCol, Attacked, _Protected);
+ if Attacked = 0 then begin
+ {*** if not in check, then re-put valid move ***}
+ ValidMoves := ValidMoves + 1;
+ MoveList.Move[ValidMoves] := MoveList.Move[i];
+ end;
+ UnMakeMove (DummyMove);
+ end;
+ MoveList.NumMoves := ValidMoves;
+ end; {TrimChecks}
+
+{****************************************************************************}
+{* Randomize Move List: Scrambles the order of the given move list. This *}
+{* is done to make choosing between tie scores random. It is necassary *}
+{* to scramble the moves here because the move list will always be *}
+{* generated in the same order. *}
+{****************************************************************************}
+ procedure RandomizeMoveList (var MoveList : MoveListType);
+ var i, Exch : integer;
+ ExchMove : MoveType;
+ begin
+ for i := 1 to MoveList.NumMoves do begin
+ {*** swap the current move with some random other one ***}
+ Exch := Random (MoveList.NumMoves) + 1;
+ ExchMove := MoveList.Move[Exch];
+ MoveList.Move[Exch] := MoveList.Move[i];
+ MoveList.Move[i] := ExchMove;
+ end;
+ end; {RandomizeMoveList}
+
+{****************************************************************************}
+{* Goto Move: Rolls back/forth the game to the given move number. Each *}
+{* move between the current move and the destination is made/retracted to *}
+{* update the board and other game status information. If the given move *}
+{* number is too small or too large, the game is rolled to the first/last *}
+{* move. *}
+{****************************************************************************}
+ procedure GotoMove (GivenMoveTo : integer);
+ var Movement : MoveType;
+ DummyScore : integer;
+ MoveTo, BeginMoveNum, EndMoveNum : integer;
+ begin
+ {*** check the bounds of given move number ***}
+ MoveTo := GivenMoveTo;
+ BeginMoveNum := Game.MoveNum - Game.MovesPointer;
+ EndMoveNum := Game.MoveNum + (Game.MovesStored - Game.MovesPointer);
+ if (MoveTo < BeginMoveNum) then MoveTo := BeginMoveNum;
+ if (MoveTo > EndMoveNum) then MoveTo := EndMoveNum;
+
+ {*** make / retract moves of the game until the destination is reached ***}
+ while (Game.MoveNum <> MoveTo) do begin
+ if MoveTo > Game.MoveNum then begin
+ Movement := Game.Move[Game.MovesPointer + 1];
+ MakeMove (Movement, false, DummyScore);
+ end else
+ UnMakeMove (Movement);
+ end;
+ Game.GameFinished := false;
+ end;
+
+{*** end of the MOVES.PAS include file ***}
+
diff --git a/applications/fpchess/engines/kcchess/mod_kcchess.pas b/applications/fpchess/engines/kcchess/mod_kcchess.pas
new file mode 100644
index 000000000..d238cd8a8
--- /dev/null
+++ b/applications/fpchess/engines/kcchess/mod_kcchess.pas
@@ -0,0 +1,148 @@
+unit mod_kcchess;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+const HIGH = 52; WIDE = 52; SINGLE_IMAGE_SIZE = 1500;
+ BOARD_SIZE = 8; ROW_NAMES = '12345678'; COL_NAMES = 'ABCDEFGH';
+ BOARD_X1 = 19; BOARD_Y1 = 4; BOARD_X2 = 434; BOARD_Y2 = 419;
+ INSTR_LINE = 450; MESSAGE_X = 460;
+ NULL_MOVE = -1; STALE_SCORE = -1000;
+ MOVE_LIST_LEN = 300; GAME_MOVE_LEN = 500;
+ MAX_LOOKAHEAD = 9; PLUNGE_DEPTH = -1; NON_DEV_MOVE_LIMIT = 50;
+
+ {*** pixel rows to print various messages in the conversation area ***}
+ MSG_MOVE = 399; MSG_BOXX1 = 464; MSG_BOXX2 = 635; MSG_MIDX = 550;
+ MSG_WHITE = 165; MSG_BLACK = 54; MSG_MOVENUM = 358; MSG_PLHI = 90;
+ MSG_TURN = 375; MSG_SCAN = 416; MSG_CHI = 17; MSG_HINT = 416;
+ MSG_CONV = 40; MSG_WARN50 = 277; MSG_TIME_LIMIT = 258;
+ MSG_SCORE = 318; MSG_POS_EVAL = 344; MSG_ENEMY_SCORE = 331;
+
+type PieceImageType = (BLANK, PAWN, BISHOP, KNIGHT, ROOK, QUEEN, KING);
+ PieceColorType = (C_WHITE, C_BLACK);
+ {*** the color of the actual square ***}
+ SquareColorType = (S_LIGHT, S_DARK, S_CURSOR);
+ {*** which instructions to print at bottom of screen ***}
+ InstructionType = (INS_MAIN, INS_GAME, INS_SETUP, INS_PLAYER, INS_SETUP_COLOR,
+ INS_SETUP_MOVED, INS_SETUP_MOVENUM, INS_FILE, INS_FILE_INPUT,
+ INS_WATCH, INS_GOTO, INS_OPTIONS, INS_PAWN_PROMOTE);
+ {*** there is a two-thick border of 'dead squares' around the main board ***}
+ RowColType = -1..10;
+ {*** Turbo Pascal requires that parameter string be declared like this ***}
+ string2 = string[2];
+ string10 = string[10];
+ string80 = string[80];
+ {*** memory for a 52*52 pixel image ***}
+ SingleImageType = array [1..SINGLE_IMAGE_SIZE] of byte;
+ {*** images must be allocated on the heap because the stack is not large enough ***}
+ ImageTypePt = ^ImageType;
+ ImageType = array [PieceImageType, PieceColorType, SquareColorType] of SingleImageType;
+ {*** text file records for help mode ***}
+ HelpPageType = array [1..22] of string80;
+
+ {*** directions to scan when looking for all possible moves of a piece ***}
+ PossibleMovesType = array [PieceImageType] of record
+ NumDirections : 1..8;
+ MaxDistance : 1..7;
+ UnitMove : array [1..8] of record
+ DirRow, DirCol: -2..2;
+ end;
+ end;
+
+ {*** attributes for a piece or board square ***}
+ PieceType = record
+ image : PieceImageType;
+ color : PieceColorType;
+ HasMoved : boolean;
+ ValidSquare : boolean;
+ end;
+
+ BoardType = array [RowColType, RowColType] of PieceType;
+
+ {*** representation of the movement of a piece, or 'ply' ***}
+ MoveType = record
+ FromRow, FromCol, ToRow, ToCol : RowColType;
+ PieceMoved : PieceType;
+ PieceTaken : PieceType;
+ {*** image after movement - used for pawn promotion ***}
+ MovedImage : PieceImageType;
+ end;
+
+ {*** string of moves - used to store list of all possible moves ***}
+ MoveListType = record
+ NumMoves : 0..MOVE_LIST_LEN;
+ Move : array [1..MOVE_LIST_LEN] of MoveType;
+ end;
+
+ {*** attributes of both players ***}
+ PlayerType = array [PieceColorType] of record
+ Name : string[20];
+ IsHuman : boolean;
+ LookAhead : 0..MAX_LOOKAHEAD;
+ PosEval : boolean; {*** Position Evaluation On / Off ***}
+ ElapsedTime : LongInt;
+ LastMove : MoveType;
+ InCheck : boolean;
+ KingRow, KingCol : RowColType;
+ CursorRow, CursorCol : RowColType;
+ end;
+
+ {*** attributes to represent an entire game ***}
+ GameType = record
+ MovesStored : 0..GAME_MOVE_LEN; {*** number of moves stored ***}
+ MovesPointer : 0..GAME_MOVE_LEN; {*** move currently displayed - for Takeback, UnTakeback ***}
+ MoveNum : 1..GAME_MOVE_LEN; {*** current move or 'ply' number ***}
+ Player : PlayerType;
+ Move : array [1..GAME_MOVE_LEN] of MoveType;
+ InCheck : array [0..GAME_MOVE_LEN] of boolean; {*** if player to move is in check ***}
+ FinalBoard : BoardType;
+ GameFinished : boolean;
+ TimeOutWhite, TimeOutBlack : boolean; {*** reasons for a game... ***}
+ Stalemate, NoStorage : boolean; {*** being finished ***}
+ NonDevMoveCount : array [0..GAME_MOVE_LEN] of byte; {*** since pawn push or take - Stalemate-50 ***}
+ EnPassentAllowed : boolean;
+ SoundFlag : boolean;
+ FlashCount : integer;
+ WatchDelay : integer;
+ TimeLimit : longint;
+ end;
+
+ {*** global variables ***}
+var Game : GameType;
+ Board : BoardType; {*** current board setup ***}
+ Player : PlayerType; {*** current player attributes ***}
+ CapturePoints : array [PieceImageType] of integer; {*** for taking enemy piece ***}
+ EnemyColor : array [PieceColorType] of PieceColorType; {*** opposite of given color ***}
+ PossibleMoves : PossibleMovesType;
+ LastTime : longint; {*** last read system time-of-day clock value ***}
+ DefaultFileName : string80; {*** for loading and saving games ***}
+ ImageStore : ImageTypePt;
+ GraphDriver, GraphMode : integer; {*** for Turbo Pascal graphics ***}
+
+procedure AttackedBy (row, col : RowColType; var Attacked, _Protected : integer);
+procedure GenMoveList (Turn : PieceColorType; var Movelist : MoveListType);
+procedure MakeMove (Movement : MoveType; PermanentMove : boolean; var Score : integer);
+procedure UnMakeMove (var Movement: Movetype);
+procedure TrimChecks (Turn : PieceColorType; var MoveList : MoveListType);
+procedure RandomizeMoveList (var MoveList : MoveListType);
+procedure GotoMove (GivenMoveTo : integer);
+
+implementation
+
+{*** include files ***}
+
+//{$I MISC.PAS} {*** miscellaneous functions ***}
+//{$I INIT.PAS} {*** initialization of global variables ***}
+//{$I DISPLAY.PAS} {*** display-oriented routines ***}
+//{$I INPUT.PAS} {*** keyboard input routines ***}
+{$I MOVES.PAS} {*** move generation and making routines ***}
+//{$I SETUP.PAS} {*** default board and custom setup routines ***}
+//{$I PLAY.PAS} {*** computer thinking and player input routines ***}
+//{$I MENU.PAS} {*** main menu routines ***}
+
+end.
+
diff --git a/applications/fpchess/fpchess.lpi b/applications/fpchess/fpchess.lpi
index 1873a9e58..ee1af9e78 100644
--- a/applications/fpchess/fpchess.lpi
+++ b/applications/fpchess/fpchess.lpi
@@ -68,7 +68,7 @@
-
+
@@ -130,15 +130,20 @@
-
+
-
+
+
+
+
+
+
@@ -149,6 +154,7 @@
+
diff --git a/applications/fpchess/fpchess.lpr b/applications/fpchess/fpchess.lpr
index eb7a9f042..35732d8b3 100644
--- a/applications/fpchess/fpchess.lpr
+++ b/applications/fpchess/fpchess.lpr
@@ -8,7 +8,7 @@ uses
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, lnetbase, mainform, chessdrawer, chessgame, chessconfig,
- chesstcputils, chessmodules, mod_singleplayer, mod_fics
+ chesstcputils, chessmodules, mod_samecomputer, mod_fics, mod_kcchess
{$ifdef FPCHESS_WEBSERVICES}
,IDelphiChess_Intf
{$endif};
diff --git a/applications/fpchess/mod_singleplayer.pas b/applications/fpchess/mod_samecomputer.pas
similarity index 70%
rename from applications/fpchess/mod_singleplayer.pas
rename to applications/fpchess/mod_samecomputer.pas
index e873d5f8a..74babd2d2 100644
--- a/applications/fpchess/mod_singleplayer.pas
+++ b/applications/fpchess/mod_samecomputer.pas
@@ -1,4 +1,4 @@
-unit mod_singleplayer;
+unit mod_samecomputer;
{$mode objfpc}{$H+}
@@ -13,7 +13,7 @@ type
{ TSinglePlayerChessModule }
- TSinglePlayerChessModule = class(TChessModule)
+ TSameComputerChessModule = class(TChessModule)
private
textSecondPlayerName: TStaticText;
editSecondPlayerName: TEdit;
@@ -32,9 +32,9 @@ type
implementation
-{ TSinglePlayerChessModule }
+{ TSameComputerChessModule }
-constructor TSinglePlayerChessModule.Create;
+constructor TSameComputerChessModule.Create;
begin
inherited Create;
@@ -42,7 +42,7 @@ begin
Kind := cmkSinglePlayer;
end;
-procedure TSinglePlayerChessModule.CreateUserInterface;
+procedure TSameComputerChessModule.CreateUserInterface;
begin
textSecondPlayerName := TStaticText.Create(nil);
textSecondPlayerName.SetBounds(20, 20, 180, 50);
@@ -53,45 +53,45 @@ begin
editSecondPlayerName.Text := 'Second player';
end;
-procedure TSinglePlayerChessModule.ShowUserInterface(AParent: TWinControl);
+procedure TSameComputerChessModule.ShowUserInterface(AParent: TWinControl);
begin
textSecondPlayerName.Parent := AParent;
editSecondPlayerName.Parent := AParent;
end;
-procedure TSinglePlayerChessModule.HideUserInterface();
+procedure TSameComputerChessModule.HideUserInterface();
begin
textSecondPlayerName.Parent := nil;
editSecondPlayerName.Parent := nil;
end;
-procedure TSinglePlayerChessModule.FreeUserInterface();
+procedure TSameComputerChessModule.FreeUserInterface();
begin
textSecondPlayerName.Free;
editSecondPlayerName.Free;
end;
-procedure TSinglePlayerChessModule.PrepareForGame;
+procedure TSameComputerChessModule.PrepareForGame;
begin
SecondPlayerName := editSecondPlayerName.Text;
end;
-function TSinglePlayerChessModule.IsMovingAllowedNow: Boolean;
+function TSameComputerChessModule.IsMovingAllowedNow: Boolean;
begin
Result := True;
end;
-function TSinglePlayerChessModule.GetSecondPlayerName: string;
+function TSameComputerChessModule.GetSecondPlayerName: string;
begin
Result := SecondPlayerName;
end;
-procedure TSinglePlayerChessModule.HandleOnMove(AFrom, ATo: TPoint);
+procedure TSameComputerChessModule.HandleOnMove(AFrom, ATo: TPoint);
begin
end;
initialization
- RegisterChessModule(TSinglePlayerChessModule.Create);
+ RegisterChessModule(TSameComputerChessModule.Create);
end.