638 lines
28 KiB
Plaintext
638 lines
28 KiB
Plaintext
{****************************************************************************}
|
||
{* DISPLAY.PAS: This file contains the display-oriented routines. *}
|
||
{****************************************************************************}
|
||
|
||
{****************************************************************************}
|
||
{* Display Init: initialize the Turbo Pascal VGA high resolution graphics *}
|
||
{* driver and load in the character fonts. Displays error messages and *}
|
||
{* aborts the program if something goes wrong. *}
|
||
{****************************************************************************}
|
||
procedure DisplayInit;
|
||
begin
|
||
ClrScr;
|
||
write ('Starting KC Chess...');
|
||
NoSound;
|
||
GraphDriver := VGA;
|
||
GraphMode := VGAHi;
|
||
InitGraph (GraphDriver, GraphMode, '');
|
||
if GraphResult <> grOk then begin
|
||
writeln;
|
||
writeln;
|
||
writeln ('Error using graphics driver file "EGAVGA.BGI" <<or>> this computer does');
|
||
writeln ('not have a VGA graphics card. Aborting');
|
||
Halt (1);
|
||
end;
|
||
SetTextStyle (TriplexFont, HorizDir, 1);
|
||
if GraphResult <> grOk then begin
|
||
CloseGraph;
|
||
writeln ('Error in accessing font file "TRIP.CHR". Aborting!');
|
||
Halt (1);
|
||
end;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Load Piece Images: from the file "PIECES.IMG". These are the pixel *}
|
||
{* images of all of the pieces, including the 'piece' BLANK. Checks for *}
|
||
{* I/O errors and aborts the program if there are any. *}
|
||
{****************************************************************************}
|
||
procedure LoadPieceImages;
|
||
var ImageFile : file of ImageType;
|
||
IOerror : boolean;
|
||
begin
|
||
new (ImageStore);
|
||
assign (ImageFile, 'PIECES.IMG');
|
||
reset (ImageFile);
|
||
IOerror := IOResult <> 0;
|
||
if not IOerror then begin
|
||
read (ImageFile, ImageStore^);
|
||
IOerror := IOResult <> 0;
|
||
if not IOerror then
|
||
close (ImageFile);
|
||
end;
|
||
if IOerror then begin
|
||
CloseGraph;
|
||
writeln ('IO error trying to access images file "PIECES.IMG". Aborting!');
|
||
Halt (1);
|
||
end;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Title Screen: Display the title, authors and notes on the *}
|
||
{* screen when the program starts, in a variety of fonts, sizes, and *}
|
||
{* colors. Then wait for user to type a key. The internal subroutine *}
|
||
{* CenterTitle will display its string argument, centered on the screen, *}
|
||
{* on the given pixel row. *}
|
||
{****************************************************************************}
|
||
procedure DisplayTitleScreen;
|
||
var key : char;
|
||
|
||
procedure CenterTitle (row : integer; str : string80);
|
||
begin
|
||
OutTextXY (320 - TextWidth(str) div 2, row, str);
|
||
end;
|
||
|
||
begin
|
||
ClearDevice;
|
||
SetColor (LightCyan);
|
||
SetTextStyle (TriplexFont, HorizDir, 26);
|
||
CenterTitle (0, 'KC CHESS');
|
||
SetColor (LightGreen);
|
||
SetTextStyle (TriplexFont, HorizDir, 3);
|
||
CenterTitle (200, 'by Craig Bruce and Kevin Phillips, 06-Apr-90.');
|
||
SetTextStyle (TriplexFont, HorizDir, 1);
|
||
CenterTitle (240, 'This program is Public Domain software.'); {*** that's right ***}
|
||
SetColor (LightGray);
|
||
SetTextStyle (TriplexFont, HorizDir, 1);
|
||
CenterTitle (300, 'This program was written using');
|
||
CenterTitle (330, 'Turbo Pascal 5.5 (c) Borland International, Inc.'); {*** required message ***}
|
||
CenterTitle (360, 'as the undergraduate final project for Dr. J. D. Horton');
|
||
CenterTitle (390, 'at the University of New Brunswick.');
|
||
LoadPieceImages; {*** while user is reading title screen ***}
|
||
SetTextStyle (DefaultFont, HorizDir, 2);
|
||
{*** display some piece images on the title screen ***}
|
||
PutImage (320-WIDE*2, 135, ImageStore^[PAWN, C_WHITE, S_DARK], 0);
|
||
PutImage (320-WIDE*1, 135, ImageStore^[KING, C_BLACK, S_LIGHT], 0);
|
||
PutImage (320+WIDE*0, 135, ImageStore^[QUEEN, C_WHITE, S_DARK], 0);
|
||
PutImage (320+WIDE*1, 135, ImageStore^[KNIGHT, C_BLACK, S_LIGHT], 0);
|
||
SetColor (Yellow);
|
||
CenterTitle (450, 'Press any key to begin');
|
||
key := ReadKey;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Make Sound: Will make either the "good" sound (a beep), or the "bad" *}
|
||
{* sound (a buzz), if the sound option is on. *}
|
||
{****************************************************************************}
|
||
procedure MakeSound (Good : boolean);
|
||
begin
|
||
if (Game.SoundFlag) then begin
|
||
if (Good) then begin
|
||
Sound (650); {*** beep = 650 Hz ***}
|
||
Delay (100);
|
||
end else begin
|
||
Sound (110); {*** buzz = 110 Hz ***}
|
||
Delay (350);
|
||
end;
|
||
NoSound;
|
||
end;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Square: and the piece on it on the main game screen, given the *}
|
||
{* row and column and whether to display it in the square's natural shade *}
|
||
{* or the cursor color. *}
|
||
{****************************************************************************}
|
||
procedure DisplaySquare (Row, Col : RowColType; cursor : boolean);
|
||
var x, y : integer;
|
||
SquareColor : SquareColorType;
|
||
Piece : PieceType;
|
||
begin
|
||
Piece := Board[Row, Col];
|
||
{*** get the starting pixel location ***}
|
||
x := BOARD_X1 + (Col - 1) * WIDE;
|
||
y := BOARD_Y1 + (BOARD_SIZE - Row) * HIGH;
|
||
{*** get the square color ***}
|
||
if cursor then begin
|
||
SquareColor := S_CURSOR;
|
||
end else begin
|
||
if (Row + Col) mod 2 = 0 then
|
||
SquareColor := S_DARK
|
||
else
|
||
SquareColor := S_LIGHT;
|
||
end;
|
||
{*** put image onto the screen ***}
|
||
PutImage (x, y, ImageStore^ [Piece.image, Piece.color, SquareColor], 0);
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Clear Lines: Erase all text from the given pixel row for the *}
|
||
{* given number of pixel rows, on the conversation area. *}
|
||
{****************************************************************************}
|
||
procedure DisplayClearLines (from, count : integer);
|
||
begin
|
||
SetFillStyle (SolidFill, DarkGray);
|
||
Bar (MSG_BOXX1 + 1, from, MSG_BOXX2 - 1, from + count - 1);
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Center Text: Display the given string, centered, on the given pixel row *}
|
||
{* of the conversation area. *}
|
||
{****************************************************************************}
|
||
procedure CenterText (row : integer; str : string80);
|
||
begin
|
||
OutTextXY (MSG_MIDX - TextWidth(str) div 2, row, str);
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Player Info: Display the name, elapsed time, player type and *}
|
||
{* skill level, last move, and whether in check or not, for the given *}
|
||
{* player starting at the given pixel row on the conversation area (in *}
|
||
{* the player status box). *}
|
||
{****************************************************************************}
|
||
procedure DisplayPlayerInfo (row : integer; color : PieceColorType);
|
||
var cstr : string10;
|
||
bstr : string80;
|
||
begin
|
||
SetTextStyle (TriplexFont, HorizDir, 1);
|
||
SetColor (Yellow);
|
||
with Player[color] do begin
|
||
CenterText (row, Name);
|
||
CenterText (row + MSG_CHI, TimeString (ElapsedTime));
|
||
if IsHuman then
|
||
bstr := 'Human'
|
||
else begin
|
||
Str (LookAhead, cstr);
|
||
bstr := 'Machine Level ' + cstr;
|
||
if PosEval then bstr := bstr + '+';
|
||
end;
|
||
CenterText (row + MSG_CHI * 2, bstr);
|
||
CenterText (row + MSG_CHI * 3, 'Last: ' + MoveStr (LastMove));
|
||
if InCheck then
|
||
bstr := 'In Check'
|
||
else
|
||
bstr := 'Ok';
|
||
CenterText (row + MSG_CHI * 4, bstr);
|
||
end;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Instructions: display the given set of instructions at the *}
|
||
{* bottom of the screen in the instruction area. OutLine will display the *}
|
||
{* given instructions on the given instruction line number. *}
|
||
{****************************************************************************}
|
||
procedure DisplayInstructions (InstrSet : InstructionType);
|
||
const CHI = 11; {*** character height ***}
|
||
|
||
procedure OutLine (LineNum : integer; OutText : string80);
|
||
begin
|
||
OutTextXY (0, INSTR_LINE + CHI * LineNum, OutText);
|
||
end;
|
||
|
||
begin
|
||
SetFillStyle (SolidFill, Black);
|
||
Bar (0, INSTR_LINE, GetMaxX, GetMaxY);
|
||
SetTextStyle (DefaultFont, HorizDir, 1);
|
||
SetColor (LightRed);
|
||
case InstrSet of
|
||
INS_MAIN: begin
|
||
OutLine (0, 'MAIN MENU RETURN = play, F = File System');
|
||
OutLine (1, 'H = Help, G = Goto move, W = Watch game, O = Options, P = Player info');
|
||
OutLine (2, 'Q = Quit, N = New game, S = Setup board, T = Take-Back Move, U = Un-takeback');
|
||
end;
|
||
INS_GAME : begin
|
||
OutLine (0, 'GAME MENU');
|
||
OutLine (1, 'Human Player: use Cursor Keys, BACKSPACE, and RETURN/SPACE. ESC = main menu');
|
||
OutLine (2, 'M = force computer to Move, H = Hint, A = Attack/protect, C = Check moves');
|
||
end;
|
||
INS_SETUP : begin
|
||
OutLine (0, 'SETUP MENU');
|
||
OutLine (1, 'Use cursor keys. Then type K, Q, R, B, N or P to set piece or SPACE to remove.');
|
||
OutLine (2, 'RETURN = exit, ESC = exit recalling old setup; D = default, C = clear board.');
|
||
end;
|
||
INS_SETUP_COLOR : begin
|
||
OutLine (0, 'SETUP MENU - PIECE COLOR SET');
|
||
OutLine (1, 'Type B to create a BLACK piece');
|
||
OutLine (2, 'Type W to create a WHITE piece');
|
||
end;
|
||
INS_SETUP_MOVED : begin
|
||
OutLine (0, 'SETUP MENU - PIECE MOVED SET');
|
||
OutLine (1, 'Has this piece been moved from its starting position at any time since the');
|
||
OutLine (2, 'start of the game (Y/N)?');
|
||
end;
|
||
INS_SETUP_MOVENUM : begin
|
||
OutLine (0, 'SETUP MENU - SET MOVE NUMBER and COLOR');
|
||
OutLine (1, 'Enter the number then whose turn the next move of the game will be.');
|
||
OutLine (2, 'Use BACKSPACE to edit value, and RETURN to enter it.');
|
||
end;
|
||
INS_PLAYER : begin
|
||
OutLine (0, 'SET PLAYER INFO');
|
||
OutLine (1, 'Type value, use BACKSPACE to edit and press RETURN after each field.');
|
||
OutLine (2, 'For the player type: H = Human and M = Machine. Pos Eval is part of skill level.');
|
||
end;
|
||
INS_OPTIONS : begin
|
||
OutLine (0, 'SET OPTIONS');
|
||
OutLine (1, 'Type value, use BACKSPACE to edit and press RETURN after each field.');
|
||
OutLine (2, 'Press RETURN only to preserve current setting.');
|
||
end;
|
||
INS_FILE : begin
|
||
OutLine (0, 'FILE MENU');
|
||
OutLine (1, 'L = Load Game, S = Save Game, D = Directory, P = Print Game');
|
||
OutLine (2, 'ESC = return to Main Menu');
|
||
end;
|
||
INS_FILE_INPUT: begin
|
||
OutLine (0, 'FILE NAME INPUT');
|
||
OutLine (1, 'Please enter the name of the file you wish to use.');
|
||
OutLine (2, 'Press RETURN only for default file name.');
|
||
end;
|
||
INS_WATCH : begin
|
||
OutLine (0, 'WATCH MODE');
|
||
OutLine (1, 'Press any key to return to Main Menu.');
|
||
end;
|
||
INS_GOTO : begin
|
||
OutLine (0, 'GOTO MOVE NUMBER');
|
||
OutLine (1, 'Please enter the move number and then the color to move.');
|
||
OutLine (2, 'to use. Press RETURN only for default file.');
|
||
end;
|
||
INS_PAWN_PROMOTE : begin
|
||
OutLine (0, 'HUMAN PLAYER PAWN PROMOTION');
|
||
OutLine (1, 'Press the letter of the piece you wish to promote the pawn to:');
|
||
OutLine (2, 'Q = Queen, R = Rook, B = Bishop, N = kNight.');
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Board: call DisplaySquare for each square on the board. A *}
|
||
{* small dot is displayed on the screen immediately before the square *}
|
||
{* image is displayed to show that the screen is being updated, even if *}
|
||
{* the board is being displayed over itself with no changes. *}
|
||
{****************************************************************************}
|
||
procedure DisplayBoard;
|
||
var row, col : RowColType;
|
||
x,y : integer;
|
||
begin
|
||
SetFillStyle (SolidFill, LightCyan);
|
||
for row := 1 to BOARD_SIZE do
|
||
for col := 1 to BOARD_SIZE do begin
|
||
x := BOARD_X1 + (Col-1) * WIDE;
|
||
y := BOARD_Y1 + (BOARD_SIZE - Row) * HIGH;
|
||
Bar (x + 23, y + 23, x + 26, y + 26);
|
||
DisplaySquare (row, col, false);
|
||
end;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Get Finish Reason: given the completion status variables in the Game *}
|
||
{* global data structure, this routine returns the reason and the winner *}
|
||
{* (if any) of the game. The reason can be that a player exceeded the *}
|
||
{* time limit, there are more moves than can be stored in the game, *}
|
||
{* stalemate (fifty non-developmental moves or player cannot move, or *}
|
||
{* last but not least, checkmate. *}
|
||
{****************************************************************************}
|
||
procedure GetFinishReason (var Reason : string80; var IsWinner : boolean;
|
||
var Winner : PieceColorType);
|
||
var KingInCheck : boolean;
|
||
begin
|
||
if Game.TimeOutWhite or Game.TimeOutBlack then begin
|
||
Reason := 'Time-Out';
|
||
if Game.TimeOutWhite and Game.TimeOutBlack then
|
||
IsWinner := false
|
||
else begin
|
||
IsWinner := true;
|
||
if Game.TimeOutWhite then
|
||
Winner := C_BLACK
|
||
else
|
||
Winner := C_WHITE;
|
||
end;
|
||
end else begin
|
||
if Game.NoStorage then begin
|
||
Reason := 'Game Too Long';
|
||
IsWinner := false;
|
||
end else begin
|
||
KingInCheck := Player[C_WHITE].InCheck or Player[C_BLACK].InCheck;
|
||
if Game.Stalemate or not KingInCheck then begin
|
||
Reason := 'Stalemate';
|
||
IsWinner := false;
|
||
end else begin
|
||
Reason := 'Checkmate';
|
||
IsWinner := true;
|
||
if Player[C_WHITE].InCheck then
|
||
Winner := C_BLACK
|
||
else
|
||
Winner := C_WHITE;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Whose Move: displays the move number and color of the current *}
|
||
{* move in the conversation area. If the game is finished, display the *}
|
||
{* reason, and if the fifty move stalemate is close, displays a warning. *}
|
||
{****************************************************************************}
|
||
procedure DisplayWhoseMove;
|
||
var cstr : string10;
|
||
mstr : string80;
|
||
Reason : string80;
|
||
Winner : PieceColorType;
|
||
IsWinner : boolean;
|
||
Turn : PieceColorType;
|
||
OutMove : integer;
|
||
NoDevCount : integer;
|
||
begin
|
||
{*** move number and color ***}
|
||
if Game.GameFinished then
|
||
OutMove := Game.MoveNum - 1
|
||
else
|
||
OutMove := Game.MoveNum;
|
||
Str ((OutMove + 1) div 2, cstr);
|
||
mstr := 'Move ' + cstr + '-';
|
||
if OutMove mod 2 = 1 then begin
|
||
mstr := mstr + 'White';
|
||
Turn := C_WHITE;
|
||
end else begin
|
||
mstr := mstr + 'Black';
|
||
Turn := C_BLACK;
|
||
end;
|
||
SetTextStyle (TriplexFont, HorizDir, 1);
|
||
SetColor (Yellow);
|
||
DisplayClearLines (MSG_SCORE, MSG_POS_EVAL+8-MSG_SCORE);
|
||
DisplayClearLines (MSG_MOVENUM, 80);
|
||
CenterText (MSG_MOVENUM, mstr);
|
||
|
||
{*** if game is over, display reason ***}
|
||
if Game.GameFinished then begin
|
||
GetFinishReason (Reason, IsWinner, Winner);
|
||
SetColor (White);
|
||
CenterText (MSG_TURN + 3, Reason + ':');
|
||
SetColor (LightGreen);
|
||
if IsWinner then
|
||
CenterText (MSG_MOVE - 1, Player[Winner].Name)
|
||
else
|
||
CenterText (MSG_MOVE, 'Neither Player');
|
||
CenterText (MSG_HINT, 'Wins');
|
||
end else begin
|
||
CenterText (MSG_TURN, Player[Turn].Name);
|
||
end;
|
||
|
||
{*** warn if fifty move stalemate is close ***}
|
||
NoDevCount := Game.NonDevMoveCount[Game.MovesPointer];
|
||
DisplayClearLines (MSG_WARN50, 17);
|
||
if (NoDevCount >= NON_DEV_MOVE_LIMIT - 10) then begin
|
||
SetColor (LightRed);
|
||
if (NoDevCount = NON_DEV_MOVE_LIMIT) then
|
||
CenterText (MSG_WARN50, '50 Move Limit')
|
||
else begin
|
||
Str(NON_DEV_MOVE_LIMIT - NoDevCount, cstr);
|
||
CenterText (MSG_WARN50, 'Stalemate in ' + cstr);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Conversation Area: display player status for black and white, *}
|
||
{* move status, and time limit, all in the conversation area. *}
|
||
{****************************************************************************}
|
||
procedure DisplayConversationArea;
|
||
var tempstr : string80;
|
||
begin
|
||
SetFillStyle (SolidFill, DarkGray);
|
||
Bar (MESSAGE_X, MSG_CONV, GetMaxX, INSTR_LINE - 8);
|
||
SetColor (White);
|
||
Rectangle (MSG_BOXX1, MSG_WHITE-2, MSG_BOXX2, MSG_WHITE + MSG_PLHI);
|
||
SetTextStyle (DefaultFont, HorizDir, 1);
|
||
OutTextXY (MSG_BOXX1 + 4, MSG_WHITE - 10, 'White');
|
||
DisplayPlayerInfo (MSG_WHITE, C_WHITE);
|
||
SetColor (Black);
|
||
Rectangle (MSG_BOXX1, MSG_BLACK-2, MSG_BOXX2, MSG_BLACK + MSG_PLHI);
|
||
SetTextStyle (DefaultFont, HorizDir, 1);
|
||
OutTextXY (MSG_BOXX1 + 4, MSG_BLACK - 10, 'Black');
|
||
DisplayPlayerInfo (MSG_BLACK, C_BLACK);
|
||
SetColor (Cyan);
|
||
Rectangle (MSG_BOXX1, 356, MSG_BOXX2, 438);
|
||
SetTextStyle (TriplexFont, HorizDir, 1);
|
||
SetColor (LightGreen);
|
||
if (Game.TimeLimit = 0) then
|
||
tempstr := '<none>'
|
||
else
|
||
tempstr := TimeString (Game.TimeLimit);
|
||
CenterText (MSG_TIME_LIMIT, 'T.Limit = ' + tempstr);
|
||
DisplayWhoseMove;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Game Screen: clear the hires screen, display the board, *}
|
||
{* conversation area, and instructions. *}
|
||
{****************************************************************************}
|
||
procedure DisplayGameScreen;
|
||
var i : integer;
|
||
begin
|
||
ClearDevice;
|
||
{*** display board ***}
|
||
SetFillStyle (SolidFill, Blue);
|
||
Bar (BOARD_X1-4, BOARD_Y1-4, BOARD_X2+3, BOARD_Y2+3);
|
||
DisplayBoard;
|
||
|
||
{*** display row and column letters and numbers around board ***}
|
||
SetColor (LightGreen);
|
||
SetTextStyle (TriplexFont, HorizDir, 2);
|
||
for i := 1 to 8 do begin
|
||
OutTextXY (0, BOARD_Y1+HIGH*i-8-HIGH div 2,
|
||
Copy (ROW_NAMES, BOARD_SIZE - i + 1, 1));
|
||
OutTextXY (BOARD_X2 + 10, BOARD_Y1+HIGH*i-8-HIGH div 2,
|
||
Copy (ROW_NAMES, BOARD_SIZE - i + 1, 1));
|
||
OutTextXY (BOARD_X1+WIDE*i-8-WIDE div 2, BOARD_Y2+4,
|
||
Copy (COL_NAMES, i, 1));
|
||
end;
|
||
|
||
{*** display title and conversation area ***}
|
||
SetFillStyle (SolidFill, DarkGray);
|
||
Bar (MESSAGE_X, 0, GetMaxX, MSG_CONV - 1);
|
||
SetTextStyle (TriplexFont, HorizDir, 4);
|
||
SetColor (LightCyan);
|
||
CenterText (2, 'KC CHESS');
|
||
DisplayConversationArea;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Update Time: get the elapsed time since last call, and if there was a *}
|
||
{* change in the time, the amount of change is added to the current *}
|
||
{* player's elapsed time and the new time is displayed. *}
|
||
{****************************************************************************}
|
||
procedure UpdateTime (Turn : PieceColorType);
|
||
var Elapsed : longint;
|
||
Row : integer;
|
||
begin
|
||
Elapsed := ElapsedTime;
|
||
if (Elapsed > 0) then begin
|
||
Player[Turn].ElapsedTime := Player[Turn].ElapsedTime + Elapsed;
|
||
if (Turn = C_WHITE) then
|
||
Row := MSG_WHITE + MSG_CHI
|
||
else
|
||
Row := MSG_BLACK + MSG_CHI;
|
||
DisplayClearLines (Row, 17);
|
||
SetTextStyle (TriplexFont, HorizDir, 1);
|
||
SetColor (Yellow);
|
||
CenterText (Row, TimeString(Player[Turn].ElapsedTime));
|
||
end;
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Flash Piece: will flash the piece at the given location on the Board *}
|
||
{* alternately against the other given piece image and color. This *}
|
||
{* routine is called to highlight the piece that is moving and what it *}
|
||
{* takes when a move is being displayed. *}
|
||
{****************************************************************************}
|
||
procedure FlashPiece (row, col : RowColType; OldImage : PieceImageType;
|
||
OldColor : PieceColorType);
|
||
var NewImage : PieceImageType;
|
||
NewColor : PieceColorType;
|
||
i : integer;
|
||
begin
|
||
NewImage := Board[row, col].image;
|
||
NewColor := Board[row, col].color;
|
||
for i := 1 to Game.FlashCount do begin
|
||
Board[row,col].image := NewImage; {*** show new image ***}
|
||
Board[row,col].color := NewColor;
|
||
DisplaySquare (row, col, false);
|
||
Delay (80);
|
||
Board[row,col].image := OldImage; {*** show old image ***}
|
||
Board[row,col].color := OldColor;
|
||
DisplaySquare (row, col, false);
|
||
Delay (80);
|
||
end;
|
||
Board[row, col].image := NewImage; {*** store new image ***}
|
||
Board[row, col].color := NewColor;
|
||
DisplaySquare (row, col, false);
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display Move: displays the given move on the screen after it has *}
|
||
{* already been made to the internal data structures. The special cases *}
|
||
{* of castling and en passent are taken care of. No special case is *}
|
||
{* required for pawn promotion, since it is taken care of elsewhere. *}
|
||
{****************************************************************************}
|
||
procedure DisplayMove (Movement : MoveType);
|
||
var row, EnemyRow : integer;
|
||
cstr : string10;
|
||
begin
|
||
{*** for all moves, show the piece leaving old square and taking new square ***}
|
||
with Movement do begin
|
||
FlashPiece (FromRow, FromCol, PieceMoved.image, PieceMoved.color);
|
||
FlashPiece (ToRow, ToCol, PieceTaken.image, PieceTaken.color);
|
||
end;
|
||
case Movement.PieceMoved.image of
|
||
|
||
{*** castling to left or right: must show rook moving ***}
|
||
KING: begin
|
||
if abs (Movement.FromCol - Movement.ToCol) > 1 then begin
|
||
if (Movement.ToCol < Movement.FromCol) then begin
|
||
FlashPiece (Movement.FromRow, 1, ROOK, Movement.PieceMoved.color);
|
||
FlashPiece (Movement.FromRow, 4, BLANK, Movement.PieceMoved.color);
|
||
end else begin
|
||
FlashPiece (Movement.FromRow, 8, ROOK, Movement.PieceMoved.color);
|
||
FlashPiece (Movement.FromRow, 6, BLANK, Movement.PieceMoved.color);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
{*** en passent: must show the pawn being taken ***}
|
||
PAWN: if (Movement.FromCol <> Movement.ToCol) and (Movement.PieceTaken.image = BLANK) then
|
||
FlashPiece (Movement.FromRow, Movement.ToCol, PAWN, EnemyColor[Movement.PieceMoved.color]);
|
||
end;
|
||
|
||
{*** locate and display the new last move and in-check status ***}
|
||
if Movement.PieceMoved.color = C_WHITE then begin
|
||
row := MSG_WHITE;
|
||
EnemyRow := MSG_BLACK;
|
||
end else begin
|
||
row := MSG_BLACK;
|
||
EnemyRow := MSG_WHITE;
|
||
end;
|
||
DisplayClearLines (row + MSG_CHI * 3, 34);
|
||
SetTextStyle (TriplexFont, HorizDir, 1);
|
||
SetColor (Yellow);
|
||
CenterText (row + MSG_CHI * 3, 'Last: ' + MoveStr(Player[Movement.PieceMoved.color].LastMove));
|
||
CenterText (row + MSG_CHI * 4, 'Ok');
|
||
if Player[EnemyColor[Movement.PieceMoved.color]].InCheck then cstr := 'In Check' else cstr := 'Ok';
|
||
DisplayClearLines (EnemyRow + MSG_CHI * 4, 17);
|
||
CenterText (EnemyRow + MSG_CHI * 4, cstr);
|
||
end;
|
||
|
||
{****************************************************************************}
|
||
{* Display UnMade Move: display a move being retracted after the internal *}
|
||
{* data structures have been modified. Special cases are un-castle and *}
|
||
{* un-en passent. *}
|
||
{****************************************************************************}
|
||
procedure DisplayUnMadeMove (Movement : MoveType);
|
||
var row, EnemyRow : integer;
|
||
cstr : string10;
|
||
begin
|
||
if (Movement.FromRow <> NULL_MOVE) then begin
|
||
with Movement do begin
|
||
{*** retract for all pieces ***}
|
||
FlashPiece (ToRow, ToCol, MovedImage, PieceMoved.color);
|
||
FlashPiece (FromRow, FromCol, BLANK, C_WHITE);
|
||
end;
|
||
case Movement.PieceMoved.image of
|
||
|
||
{*** un-castle ***}
|
||
KING: begin
|
||
if abs (Movement.FromCol - Movement.ToCol) > 1 then begin
|
||
if (Movement.ToCol < Movement.FromCol) then begin
|
||
FlashPiece (Movement.FromRow, 4, ROOK, Movement.PieceMoved.color);
|
||
FlashPiece (Movement.FromRow, 1, BLANK, Movement.PieceMoved.color);
|
||
end else begin
|
||
FlashPiece (Movement.FromRow, 6, ROOK, Movement.PieceMoved.color);
|
||
FlashPiece (Movement.FromRow, 8, BLANK, Movement.PieceMoved.color);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
{*** un-en passent ***}
|
||
PAWN: if (Movement.FromCol <> Movement.ToCol) and (Movement.PieceTaken.image = BLANK) then
|
||
FlashPiece (Movement.FromRow, Movement.ToCol, BLANK, EnemyColor[Movement.PieceMoved.color]);
|
||
end;
|
||
|
||
{*** update status for both players ***}
|
||
if Movement.PieceMoved.color = C_WHITE then begin
|
||
row := MSG_WHITE;
|
||
EnemyRow := MSG_BLACK;
|
||
end else begin
|
||
row := MSG_BLACK;
|
||
EnemyRow := MSG_WHITE;
|
||
end;
|
||
DisplayClearLines (row + MSG_CHI * 3, 34);
|
||
SetTextStyle (TriplexFont, HorizDir, 1);
|
||
SetColor (Yellow);
|
||
CenterText (row + MSG_CHI * 3, 'Last: ' + MoveStr(Player[Movement.PieceMoved.color].LastMove));
|
||
if Player[Movement.PieceMoved.color].InCheck then cstr := 'In Check' else cstr := 'Ok';
|
||
CenterText (row + MSG_CHI * 4, cstr);
|
||
DisplayClearLines (EnemyRow + MSG_CHI * 4, 17);
|
||
CenterText (EnemyRow + MSG_CHI * 4, 'Ok');
|
||
DisplayWhoseMove;
|
||
end;
|
||
end;
|
||
|
||
{*** end of DISPLAY.PAS include file ***}
|
||
|