From 6064bfec538038fd1e1ccf4da54fa859241f98fa Mon Sep 17 00:00:00 2001 From: Pavel Perminov Date: Wed, 26 Sep 2012 19:14:19 +0000 Subject: Current line of development release (344 rev. truncated adjusted copy) git-svn-id: http://svn.miranda-ng.org/main/trunk@1669 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Chess4Net/ChessBoardUnit.pas | 1800 +++++++++++++++++----------------- 1 file changed, 895 insertions(+), 905 deletions(-) (limited to 'plugins/Chess4Net/ChessBoardUnit.pas') diff --git a/plugins/Chess4Net/ChessBoardUnit.pas b/plugins/Chess4Net/ChessBoardUnit.pas index 6b655058ad..8a7042f292 100644 --- a/plugins/Chess4Net/ChessBoardUnit.pas +++ b/plugins/Chess4Net/ChessBoardUnit.pas @@ -1,410 +1,396 @@ +//////////////////////////////////////////////////////////////////////////////// +// All code below is exclusively owned by author of Chess4Net - Pavel Perminov +// (packpaul@mail.ru, packpaul1@gmail.com). +// Any changes, modifications, borrowing and adaptation are a subject for +// explicit permition from the owner. + unit ChessBoardUnit; interface uses - Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, TntForms, - Dialogs, StdCtrls, TntStdCtrls, ExtCtrls, Buttons, - // Chess4net - ChessBoardHeaderUnit, ChessRulesEngine, BitmapResUnit, LocalizerUnit; + Forms, ExtCtrls, Classes, Controls, Graphics, Types, Messages, + // + ChessRulesEngine, BitmapResUnit, PromotionUnit; type - TMode = (mView, mGame); // состояние доски - TChessBoardEvent = - (cbeMoved, cbeMate, cbeStaleMate, cbeInsuffMaterial, cbeKeyPressed, - cbeClockSwitched, cbeTimeOut, cbeExit, cbeMenu, cbeActivate, cbeFormMoving, - cbeRefreshAll); // возможно добавление новых событий - // cbeRefreshAll сигнализирует, что были изменены глобальные опции. + TMode = (mView, mGame, mAnalyse, mEdit); // Board mode + + TAnimation = (aNo, aSlow, aQuick); + + TChessBoardEvent = (cbeMate, cbeStaleMate, cbeMoved, cbePosSet, cbeMenu); TChessBoardHandler = procedure(e: TChessBoardEvent; d1: pointer = nil; d2: pointer = nil) of object; - TAnimation = (aNo, aSlow, aQuick); -{$IFDEF THREADED_CHESSCLOCK} - TChessBoard = class; - TTimeLabelThread = class(TThread) - private - ChessBoard: TChessBoard; - player_time: array[TFigureColor] of TDateTime; - protected - procedure Execute; override; - public - WhiteTime, BlackTime: string; - constructor Create(ChessBoard: TChessBoard); - end; -{$ENDIF} + TChessBoardLayerBase = class; - TChessBoard = class(TTntForm, ILocalizable, IChessRulesEngineable) + TChessBoard = class(TForm, IChessRulesEngineable) PBoxBoard: TPaintBox; - TimePanel: TPanel; - WhiteLabel: TTntLabel; - WhiteTimeLabel: TLabel; - BlackLabel: TTntLabel; - BlackTimeLabel: TLabel; - GameTimer: TTimer; AnimateTimer: TTimer; - WhiteFlagButton: TSpeedButton; - BlackFlagButton: TSpeedButton; - WhitePanel: TPanel; - BlackPanel: TPanel; + procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); + procedure FormCanResize(Sender: TObject; var NewWidth, + NewHeight: Integer; var Resize: Boolean); + procedure FormResize(Sender: TObject); + procedure AnimateTimerTimer(Sender: TObject); procedure PBoxBoardPaint(Sender: TObject); procedure PBoxBoardDragDrop(Sender, Source: TObject; X, Y: Integer); procedure PBoxBoardDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); procedure PBoxBoardEndDrag(Sender, Target: TObject; X, Y: Integer); - procedure PBoxBoardMouseDown(Sender: TObject; Button: TMouseButton; - Shift: TShiftState; X, Y: Integer); - procedure PBoxBoardMouseMove(Sender: TObject; Shift: TShiftState; X, - Y: Integer); + procedure PBoxBoardMouseDown(Sender: TObject; + Button: TMouseButton; Shift: TShiftState; X, Y: Integer); + procedure PBoxBoardMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure PBoxBoardMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); - procedure PBoxBoardStartDrag(Sender: TObject; - var DragObject: TDragObject); - procedure AnimateTimerTimer(Sender: TObject); - procedure GameTimerTimer(Sender: TObject); - procedure FormClose(Sender: TObject; var Action: TCloseAction); - procedure FormKeyDown(Sender: TObject; var Key: Word; - Shift: TShiftState); - procedure FormActivate(Sender: TObject); - procedure FlagButtonClick(Sender: TObject); - procedure FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; - var Resize: Boolean); - procedure FormResize(Sender: TObject); - procedure TimePanelResize(Sender: TObject); + procedure PBoxBoardStartDrag(Sender: TObject; var DragObject: TDragObject); private m_ChessRulesEngine: TChessRulesEngine; + m_BitmapRes: TBitmapRes; // Manager for bitmaps - m_i0, m_j0: integer; - m_fig: TFigure; + FHandler: TChessBoardHandler; - mode_var: TMode; dx, dy: integer; // Расстояние от курсора до верхнего левого угла x0, y0: integer; // Предыдущие координаты курсора _flipped: boolean; // Доска перевёрнута или нет - hilighted: boolean; // Подсветка делаемого хода + m_bHilighted: boolean; // Hilight the move that is being done + + m_i0, m_j0: integer; + m_fig: TFigure; + + m_Mode: TMode; + m_bViewGaming: boolean; + m_bmHiddenBoard: TBitmap; m_bmChessBoard: TBitmap; m_bmFigure: array[TFigure] of TBitmap; m_bmBuf: TBitmap; - Handler: TChessBoardHandler; + m_iSquareSize: integer; // Size of one chess board field - m_animation: TAnimation; // скорость анимации + m_animation: TAnimation; // Animation speed + m_iAnimStep, m_iPrevAnimStep, m_iAnimStepsCount: integer; + anim_dx, anim_dy: real; // Variables for animation of a dragged piece - anim_dx, anim_dy: real; // переменные для анимации перемещения фигуры - anim_step, anim_step_num: integer; // количество шагов в анимации - player_color: TFigureColor; // цвет игрока клиента - dragged_moved: boolean; // индикатор включения перетаскивания - last_hilight: boolean; // флаг подсветки последнего хода - m_bFlash_move: boolean; // flag for flashing on icoming move - coord_show: boolean; // флаг координат - - auto_flag: boolean; // индикатор автофлага - player_time: array[TFigureColor] of TDateTime; // время белых и чёрных - past_time: TDateTime; // время начала обдумывания хода - unlimited_var: array[TFigureColor] of boolean; // партия без временного контроля - clock_color: TFigureColor; // цвет анимируемой фигуры - - shuted: boolean; // индикатор внешнего закрытия окна + m_PlayerColor: TFigureColor; // Color of player client + m_bDraggedMoved: boolean; // Flag for switching of dragging + last_hilight: boolean; // Flag for hilighting of the last move done + coord_show: boolean; // Flag for showing coordinates // Resizing m_ResizingType: (rtNo, rtHoriz, rtVert); m_iDeltaWidthHeight: integer; - m_BitmapRes: TBitmapRes; // Manager for bitmaps - m_iTimePanelInitialWidth: integer; - m_iWhitePanelInitialLeft, m_iBlackPanelInitialLeft: integer; - m_iWhitePanelInitialWidth, m_iBlackPanelInitialWidth: integer; - m_TimeFont: TFont; + m_bDeltaWidthHeightFlag: boolean; - m_bViewGaming: boolean; + m_PromotionForm: TPromotionForm; -{$IFDEF THREADED_CHESSCLOCK} - TimeLabelThread: TTimeLabelThread; // нить используется для борьбы с лагом в Миранде -{$ENDIF} + m_EditPiece: TFigure; + + m_iUpdateCounter: integer; + + m_lstLayers: TList; procedure HilightLastMove; - procedure WhatSquare(const P: TPoint; var i: Integer; var j: Integer); - procedure Animate(const i, j: integer); // Анимирует перемещение фигуры с (i0,j0) до (i,j) - procedure SetMode(const m: TMode); - procedure ShowTime(const c: TFigureColor); - procedure SetPlayerColor(const color: TFigureColor); - procedure SetTime(color: TFigureColor; const tm: TDateTime); - function GetTime(color: TFigureColor): TDateTime; - procedure SetUnlimited(color: TFigureColor; const unl: boolean); - function GetUnlimited(color: TFigureColor): boolean; procedure Evaluate; - procedure SetHilightLastMove(const yes: boolean); - procedure SetCoordinates(const yes: boolean); - procedure SetFlipped(const f: boolean); // Переварачивает позицию при отображении - function GetStayOnTop: boolean; - procedure SetStayOnTop(onTop: boolean); - procedure FCancelAnimationDragging; // отмена анимации и перетаскивания для удаления грязи при прорисовки - procedure SetAutoFlag(auto_flag: boolean); - procedure FFlashWindow; - // Localization - procedure ILocalizable.Localize = FLocalize; - procedure FLocalize; - - procedure WMMoving(var Msg: TWMMoving); message WM_MOVING; - procedure WMSizing(var Msg: TMessage); message WM_SIZING; - function FGetPositinoColor: TFigureColor; + function FGetLastMove: PMoveAbs; + property lastMove: PMoveAbs read FGetLastMove; + function FGetPosition: PChessPosition; + property Position: PChessPosition read FGetPosition; + function AskPromotionFigure(FigureColor: TFigureColor): TFigureName; - function FGetLastMove: PMoveAbs; + procedure FSetMode(const Value: TMode); + + function FDoMove(i, j: integer; prom_fig: TFigureName = K): boolean; + procedure FOnAfterMoveDone; + procedure FOnAfterSetPosition; + + procedure FAnimate(const i, j: integer); // Animates a disposition of a piece from (i0,j0) to (i,j) + procedure FDoAnimationStep; + procedure FEndAnimation; + procedure FWhatSquare(const P: TPoint; var i: Integer; var j: Integer); + + procedure FSetPlayerColor(const Value: TFigureColor); + procedure FCancelAnimationDragging; // Caneling of animation and dragging for trace removal after draw + procedure FSetFlipped(Value: boolean); // Flips chess position + procedure FSetCoordinatesShown(Value: boolean); + procedure FSetLastMoveHilighted(Value: boolean); function FGetPositionsList: TList; + function FGetPositionColor: TFigureColor; + function FGetMoveNotationFormat: TMoveNotationFormat; + procedure FSetMoveNotationFormat(Value: TMoveNotationFormat); + function FGetFENFormat: boolean; + procedure FSetFENFormat(bValue: boolean); - procedure FOnAfterMoveDone; + procedure FDrawHiddenBoard; + function FGetHiddenBoardCanvas: TCanvas; - property ChessRulesEngine: TChessRulesEngine read m_ChessRulesEngine; - property Position: PChessPosition read FGetPosition; + procedure FDrawBoard; + procedure FOnDrawLayerUpdate(const ADrawLayer: TChessBoardLayerBase); - property lastMove: PMoveAbs read FGetLastMove; + function FGetMovesOffset: integer; + function FGetColorStarts: TFigureColor; - protected - iSquareSize: integer; // Size of a chess board field - bmHiddenBoard: TBitmap; - procedure RDrawBoard; + procedure WMSizing(var Msg: TMessage); message WM_SIZING; - procedure RDrawHiddenBoard; virtual; - procedure ROnAfterSetPosition; virtual; - function RDoMove(i, j: integer; prom_fig: TFigureName = K): boolean; - procedure ROnAfterMoveDone; virtual; + procedure FDoHandler(e: TChessBoardEvent; d1: pointer = nil; d2: pointer = nil); - property PositionsList: TList read FGetPositionsList; + property SquareSize: integer read m_iSquareSize; + property PositionsList: TList read FGetPositionsList; public - constructor Create(Owner: TComponent; h: TChessBoardHandler = nil); reintroduce; + constructor Create(Owner: TComponent; AHandler: TChessBoardHandler = nil); reintroduce; - procedure TakeBack; // взятие хода обратно - procedure SwitchClock(clock_color: TFigureColor); + function DoMove(const strMove: string): boolean; + procedure ResetMoveList; + function SetPosition(const strPosition: string): boolean; + function GetPosition: string; procedure InitPosition; procedure PPRandom; - procedure StopClock; + procedure TakeBack; + function NMoveDone: integer; + function NPlysDone: integer; - procedure ResetMoveList; - function SetPosition(const posstr: string): boolean; - function GetPosition: string; - function NMoveDone: integer; // количество сделанных ходов - function DoMove(move_str: string): boolean; - procedure Shut; - - property Unlimited[color: TFigureColor]: boolean read GetUnlimited write SetUnlimited; - property Time[color: TFigureColor]: TDateTime read GetTime write SetTime; - property PlayerColor: TFigureColor read player_color write SetPlayerColor; - property PositionColor: TFigureColor read FGetPositinoColor; // чей ход в текущей позиции - property ClockColor: TFigureColor read clock_color; - property Mode: TMode read mode_var write SetMode; - property CoordinatesShown: boolean read coord_show write SetCoordinates; - - property flipped: boolean read _flipped write SetFlipped; - property LastMoveHilighted: boolean read last_hilight write SetHilightLastMove; - property FlashOnMove: boolean read m_bFlash_move write m_bFlash_move; - property StayOnTop: boolean read GetStayOnTop write SetStayOnTop; - property AutoFlag: boolean read auto_flag write SetAutoFlag; - property animation: TAnimation read m_animation write m_animation; + function IsMoveAnimating: boolean; + + procedure BeginUpdate; + procedure EndUpdate; + + procedure AddLayer(const ALayer: TChessBoardLayerBase); + procedure RemoveLayer(const ALayer: TChessBoardLayerBase); + + property PlayerColor: TFigureColor read m_PlayerColor write FSetPlayerColor; + property Mode: TMode read m_Mode write FSetMode; + property CoordinatesShown: boolean read coord_show write FSetCoordinatesShown; + property Flipped: boolean read _flipped write FSetFlipped; + property LastMoveHilighted: boolean read last_hilight write FSetLastMoveHilighted; + property Animation: TAnimation read m_animation write m_animation; property ViewGaming: boolean read m_bViewGaming write m_bViewGaming; + property PositionColor: TFigureColor read FGetPositionColor; // Whos move it is in the current position + property MoveNotationFormat: TMoveNotationFormat + read FGetMoveNotationFormat write FSetMoveNotationFormat; + property MovesOffset: integer read FGetMovesOffset; + property FENFormat: boolean read FGetFENFormat write FSetFENFormat; + property EditPiece: TFigure read m_EditPiece write m_EditPiece; end; -implementation -{$J+} + TChessBoardLayerBase = class + private + m_ChessBoard: TChessBoard; + function FGetSquareSize: integer; + function FGetCanvas: TCanvas; + function FGetPosition: PChessPosition; + function FGetPositionsList: TList; + protected + procedure RDraw; virtual; abstract; + function RGetColorStarts: TFigureColor; + + procedure RDoUpdate; + + procedure ROnAfterMoveDone; virtual; + procedure ROnAfterSetPosition; virtual; + procedure ROnAfterModeSet(const OldValue, NewValue: TMode); virtual; + procedure ROnResetMoveList; virtual; + + property ChessBoard: TChessBoard read m_ChessBoard write m_ChessBoard; + property SquareSize: integer read FGetSquareSize; + property Canvas: TCanvas read FGetCanvas; + property Position: PChessPosition read FGetPosition; + property PositionsList: TList read FGetPositionsList; + end; + +implementation {$R *.dfm} uses - StrUtils, Math, DateUtils, - // Chess4Net - PromotionUnit; + Math, SysUtils, Windows, + // + ChessBoardHeaderUnit; const HILIGHT_WIDTH = 1; HILIGHT_COLOR: TColor = clRed; HILIGHT_LAST_MOVE_WIDTH = 1; HILIGHT_LAST_MOVE_COLOR: TColor = clBlue; - ANIMATION_SLOW = 30; // Время анимации хода в фреймах >= 1 + ANIMATION_SLOW = 30; // Time of animation in frames >= 1 ANIMATION_QUICK = 9; CHB_WIDTH = 4; - TIME_COLOR = clBlack; -// FULL_TIME_FORMAT = 'h:n:s"."z'; - HOUR_TIME_FORMAT = 'h:nn:ss'; - MIN_TIME_FORMAT = 'n:ss'; - ZEITNOT_BOARDER = 10; // сек - цетйтнотная граница - ZEITNOT_COLOR = clMaroon; - ZEITNOT_FORMAT = 's"."zzz'; -// CHEAT_TIME_CONST = 1.5; // > 1 - WHITE_LONG_LABEL: WideString = 'White '; - WHITE_MEDIUM_LABEL: WideString = 'White '; - WHITE_SHORT_LABEL: WideString = 'W '; - BLACK_LONG_LABEL: WideString = 'Black '; - BLACK_MEDIUM_LABEL: WideString = 'Black '; - BLACK_SHORT_LABEL: WideString = 'B '; //////////////////////////////////////////////////////////////////////////////// -// Globals +// TChessBoard -function TChessBoard.DoMove(move_str: string): boolean; +constructor TChessBoard.Create(Owner: TComponent; AHandler: TChessBoardHandler = nil); begin - // Отмена анимации - if (AnimateTimer.Enabled) then - begin - AnimateTimer.Enabled := FALSE; - anim_step := anim_step_num; - AnimateTimerTimer(nil); - end; + FHandler := AHandler; + inherited Create(Owner); +end; - Result := ChessRulesEngine.DoMove(move_str); - if (Result) then - begin - FOnAfterMoveDone; - Animate(lastMove.i, lastMove.j); - SwitchClock(PositionColor); - if (m_bFlash_move and (mode_var = mGame)) then - FFlashWindow; - end; +procedure TChessBoard.AnimateTimerTimer(Sender: TObject); +begin + FDoAnimationStep; + if (m_iAnimStep >= m_iAnimStepsCount) then + FEndAnimation; end; -procedure TChessBoard.ShowTime(const c: TFigureColor); +procedure TChessBoard.FDoAnimationStep; var - time_label: TLabel; + iX, iY: integer; + rect: TRect; begin - if c = fcWhite then time_label:= WhiteTimeLabel - else time_label:= BlackTimeLabel; - - if unlimited_var[c] then - begin - time_label.Caption:= ''; - exit; - end; + if (m_iAnimStep < m_iAnimStepsCount) then + begin + inc(m_iAnimStep); - time_label.Font.Color:= TIME_COLOR; + iX := round(x0 + anim_dx * m_iAnimStep); + iY := round(y0 + anim_dy * m_iAnimStep); + dx := iX - x0 - Round(anim_dx * m_iPrevAnimStep); + dy := iY - y0 - Round(anim_dy * m_iPrevAnimStep); - LongTimeFormat:= MIN_TIME_FORMAT; - if player_time[c] >= EncodeTime(1, 0, 0, 0) then - LongTimeFormat:= HOUR_TIME_FORMAT - else - if (player_time[c] < EncodeTime(0, 0, ZEITNOT_BOARDER, 0)) and - (player_time[c] > 0) then - begin - LongTimeFormat:= ZEITNOT_FORMAT; - time_label.Font.Color:= ZEITNOT_COLOR; - end; + // Восстановить фрагмент на m_bmHiddenBoard + m_bmHiddenBoard.Canvas.Draw(iX - dx, iY - dy, m_bmBuf); + // Копировать новый фрагмент в буфер + m_bmBuf.Canvas.CopyRect(Bounds(0, 0, m_iSquareSize, m_iSquareSize), + m_bmHiddenBoard.Canvas, Bounds(iX, iY, m_iSquareSize, m_iSquareSize)); + // Нарисовать перетаскиваемую фигуру в новой позиции + m_bmHiddenBoard.Canvas.Draw(iX, iY, m_bmFigure[m_fig]); + // Перенести новый фрагмент на экран + rect := Bounds(Min(iX - dx, iX), Min(iY - dy, iY), + abs(dx) + m_iSquareSize, abs(dy) + m_iSquareSize); + PBoxBoard.Canvas.CopyRect(rect, m_bmHiddenBoard.Canvas, rect); + end; - time_label.Caption:= TimeToStr(player_time[c]); + m_iPrevAnimStep := m_iAnimStep; + end; - -procedure TChessBoard.SetFlipped(const f: boolean); +procedure TChessBoard.FEndAnimation; begin - // TODO: ??? - _flipped:= f; - RDrawBoard; -end; + AnimateTimer.Enabled := FALSE; + m_iAnimStep := m_iAnimStepsCount; -procedure TChessBoard.ResetMoveList; -begin - ChessRulesEngine.ResetMoveList; + FDrawBoard; + HilightLastMove; + Evaluate; end; -function TChessBoard.SetPosition(const posstr: string): boolean; +procedure TChessBoard.FDrawBoard; +var + i: integer; begin - Result := ChessRulesEngine.SetPosition(posstr); - if (not Result) then + if (csDestroying in ComponentState) then exit; - FCancelAnimationDragging; - ROnAfterSetPosition; - clock_color := Position.color; - RDrawBoard; -end; + if (m_iUpdateCounter > 0) then + exit; + FDrawHiddenBoard; -function TChessBoard.GetPosition: string; -begin - Result := ChessRulesEngine.GetPosition; + for i := 0 to m_lstLayers.Count - 1 do + TChessBoardLayerBase(m_lstLayers[i]).RDraw; + + PBoxBoardPaint(nil); end; -procedure TChessBoard.FormCreate(Sender: TObject); +procedure TChessBoard.HilightLastMove; +var + i, j, l, + _i0, _j0, x, y: integer; begin - m_iDeltaWidthHeight := Width - Height; - - m_iTimePanelInitialWidth := TimePanel.Width; - m_iWhitePanelInitialLeft := WhitePanel.Left; - m_iWhitePanelInitialWidth := WhitePanel.Width; - m_iBlackPanelInitialLeft := BlackPanel.Left; - m_iBlackPanelInitialWidth := BlackPanel.Width; - - m_TimeFont := TFont.Create; - m_TimeFont.Assign(WhiteTimeLabel.Font); - - m_BitmapRes := TBitmapRes.Create(Size(PBoxBoard.Width, PBoxBoard.Height)); - - BlackFlagButton.Glyph := WhiteFlagButton.Glyph; // чтоб не тащить лишнего - coord_show:= TRUE; - last_hilight:= FALSE; - m_animation := aQuick; - - TLocalizer.Instance.AddSubscriber(self); - FLocalize; + if (not (m_Mode in [mGame, mAnalyse])) then + exit; + + // Output the last move done + if (last_hilight and (lastMove.i0 <> 0)) then + begin + if (_flipped) then + begin + _i0 := 9 - lastMove.i0; + _j0 := lastMove.j0; + i := 9 - lastMove.i; + j := lastMove.j; + end + else + begin + _i0 := lastMove.i0; + _j0 := 9 - lastMove.j0; + i := lastMove.i; + j := 9 - lastMove.j; + end; - m_ChessRulesEngine := TChessRulesEngine.Create(self); + x := m_iSquareSize * (_i0 - 1) + CHB_X; + y := m_iSquareSize * (_j0 - 1) + CHB_Y; + m_bmHiddenBoard.Canvas.Pen.Color := HILIGHT_LAST_MOVE_COLOR; + m_bmHiddenBoard.Canvas.Pen.Width := HILIGHT_LAST_MOVE_WIDTH; - // Clock initialization - SetUnlimited(fcWhite, TRUE); SetUnlimited(fcBlack, TRUE); + for l := 1 to 2 do + with m_bmHiddenBoard.Canvas do + begin + MoveTo(x, y); + LineTo(x + m_iSquareSize - 1, y); + LineTo(x + m_iSquareSize - 1, y + m_iSquareSize - 1); + LineTo(x, y + m_iSquareSize - 1); + LineTo(x, y); - InitPosition; + x := m_iSquareSize * (i - 1) + CHB_X; + y := m_iSquareSize * (j - 1) + CHB_Y; + end; + PBoxBoardPaint(nil); + end; end; -procedure TChessBoard.RDrawHiddenBoard; +procedure TChessBoard.FDrawHiddenBoard; var i, j: integer; x, y: integer; begin - if (not Assigned(bmHiddenBoard)) then + if (not Assigned(m_bmHiddenBoard)) then exit; // Copy empty board to the hidden one - with bmHiddenBoard do + with m_bmHiddenBoard do begin Canvas.CopyRect(Bounds(0,0, Width,Height), m_bmChessBoard.Canvas, Bounds(0,0, Width,Height)); end; // Draw coordinates if (coord_show) then - with bmHiddenBoard, bmHiddenBoard.Canvas do + with m_bmHiddenBoard, m_bmHiddenBoard.Canvas do begin - x:= CHB_X + iSquareSize div 2; - y:= (bmHiddenBoard.Height + CHB_Y + 8 * iSquareSize + CHB_WIDTH) div 2; + x:= CHB_X + m_iSquareSize div 2; + y:= (m_bmHiddenBoard.Height + CHB_Y + 8 * m_iSquareSize + CHB_WIDTH) div 2; if _flipped then j := ord('h') else j:= ord('a'); for i:= 1 to 8 do // буквы begin TextOut(x - TextWidth(chr(j)) div 2, y + 1 - TextHeight(chr(j)) div 2 , chr(j)); - x := x + iSquareSize; + x := x + m_iSquareSize; if _flipped then dec(j) else inc(j); end; x:= (CHB_X - CHB_WIDTH) div 2; - y:= CHB_Y + iSquareSize div 2; + y:= CHB_Y + m_iSquareSize div 2; if _flipped then j:= ord('1') else j := ord('8'); for i := 1 to 8 do // цифры begin TextOut(x - TextWidth(chr(j)) div 2, y - TextHeight(chr(j)) div 2, chr(j)); - y:= y + iSquareSize; + y:= y + m_iSquareSize; if _flipped then inc(j) else dec(j); end; @@ -417,251 +403,171 @@ begin if ((Position.board[i,j] = ES)) then continue; // There's nothing to draw if not _flipped then // Загрузить нужную фигуру из ресурса и нарисовать - bmHiddenBoard.Canvas.Draw(CHB_X + iSquareSize * (i-1), - CHB_Y + iSquareSize * (8-j), + m_bmHiddenBoard.Canvas.Draw(CHB_X + m_iSquareSize * (i-1), + CHB_Y + m_iSquareSize * (8-j), m_bmFigure[Position.board[i,j]]) else // Black is below - bmHiddenBoard.Canvas.Draw(CHB_X + iSquareSize * (8-i), - CHB_Y + iSquareSize * (j-1), + m_bmHiddenBoard.Canvas.Draw(CHB_X + m_iSquareSize * (8-i), + CHB_Y + m_iSquareSize * (j-1), m_bmFigure[Position.board[i,j]]); end; end; -procedure TChessBoard.RDrawBoard; +function TChessBoard.FGetHiddenBoardCanvas: TCanvas; begin - RDrawHiddenBoard; - PBoxBoardPaint(nil); + if (Assigned(m_bmHiddenBoard)) then + Result := m_bmHiddenBoard.Canvas + else + Result := nil; end; -procedure TChessBoard.PBoxBoardPaint(Sender: TObject); +procedure TChessBoard.Evaluate; begin - PBoxBoard.Canvas.Draw(0,0, bmHiddenBoard); // Вывод скрытой доски на форму -// PBoxBoard.Canvas.StretchDraw(Bounds(0, 0, PBoxBoard.Width, PBoxBoard.Height), bmHiddenBoard); + case m_ChessRulesEngine.GetEvaluation of + evMate: + FDoHandler(cbeMate, self); + evStaleMate: + FDoHandler(cbeStaleMate, self); + end; end; -constructor TChessBoard.Create(Owner: TComponent; h: TChessBoardHandler); +procedure TChessBoard.PBoxBoardPaint(Sender: TObject); begin - inherited Create(Owner); - Handler:= h; + PBoxBoard.Canvas.Draw(0, 0, m_bmHiddenBoard); // Draw hidden board on the form +// PBoxBoard.Canvas.StretchDraw(Bounds(0, 0, PBoxBoard.Width, PBoxBoard.Height), m_bmHiddenBoard); end; -procedure TChessBoard.FormDestroy(Sender: TObject); -var - _fig: TFigure; +function TChessBoard.FGetLastMove: PMoveAbs; begin - m_ChessRulesEngine.Free; - - bmHiddenBoard.Free; - m_bmBuf.Free; - - for _fig := Low(TFigure) to High(TFigure) do - m_bmFigure[_fig].Free; - m_bmChessBoard.Free; + Result := m_ChessRulesEngine.lastMove; +end; - m_BitmapRes.Free; - m_TimeFont.Free; - TLocalizer.Instance.DeleteSubscriber(self); +function TChessBoard.FGetPosition: PChessPosition; +begin + Result := m_ChessRulesEngine.Position; end; -procedure TChessBoard.PBoxBoardDragDrop(Sender, Source: TObject; X, - Y: Integer); +function TChessBoard.AskPromotionFigure(FigureColor: TFigureColor): TFigureName; var - i, j: Integer; + frmOwner: TForm; begin - WhatSquare(Point(X, Y), i, j); - if (Mode = mGame) then + if (Owner is TForm) then + frmOwner := TForm(Owner) + else + frmOwner := self; + + if (Showing) then begin - if (RDoMove(i, j)) then - begin - SwitchClock(PositionColor); - dragged_moved:= TRUE; + m_PromotionForm := TPromotionForm.Create(frmOwner, m_BitmapRes); + try + Result := m_PromotionForm.ShowPromotion(FigureColor); + finally + FreeAndNil(m_PromotionForm); end; - end; // if + end + else + Result := Q; end; -procedure TChessBoard.PBoxBoardDragOver(Sender, Source: TObject; X, - Y: Integer; State: TDragState; var Accept: Boolean); -var - rect: TRect; - i, j: integer; +procedure TChessBoard.FSetPlayerColor(const Value: TFigureColor); begin - case State of - dsDragEnter: - hilighted:= FALSE; - dsDragMove: - begin - // Восстановить фрагмент на bmHiddenBoard - bmHiddenBoard.Canvas.Draw(x0 - dx, y0 - dy, m_bmBuf); - // Копировать новый фрагмент в буфер - m_bmBuf.Canvas.CopyRect(Bounds(0, 0, iSquareSize, iSquareSize), - bmHiddenBoard.Canvas, Bounds(X - dx, Y - dy, iSquareSize, iSquareSize)); - // Нарисовать перетаскиваемую фигуру в новой позиции - bmHiddenBoard.Canvas.Draw(X - dx, Y - dy, m_bmFigure[m_fig]); - // Перенести новый фрагмент на экран - rect:= Bounds(Min(x0,X) - dx, Min(y0, Y) - dy, - abs(X - x0) + iSquareSize, abs(Y - y0) + iSquareSize); - PBoxBoard.Canvas.CopyRect(rect, bmHiddenBoard.Canvas, rect); - - x0 := X; - y0 := Y; - - WhatSquare(Point(X,Y), i,j); - - Accept := ((i in [1..8]) and (j in [1..8])); - end; - end; + FCancelAnimationDragging; + m_PlayerColor := Value; + if (m_PlayerColor = fcWhite) then + FSetFlipped(FALSE) + else // fcBlack + FSetFlipped(TRUE); end; -procedure TChessBoard.PBoxBoardEndDrag(Sender, Target: TObject; X, - Y: Integer); +procedure TChessBoard.FCancelAnimationDragging; begin - if hilighted then - with bmHiddenBoard.Canvas do - begin - Pen.Color:= HILIGHT_COLOR; - Pen.Width := HILIGHT_WIDTH; - x0:= x0 - dx; - y0:= y0 - dy; - MoveTo(x0,y0); - LineTo(x0 + iSquareSize - 1, y0); - LineTo(x0 + iSquareSize - 1, y0 + iSquareSize - 1); - LineTo(x0, y0 + iSquareSize - 1); - LineTo(x0,y0); - - PBoxBoardPaint(nil); - end - else - begin - RDrawBoard; - if dragged_moved then - begin - HilightLastMove; - Evaluate; - dragged_moved:= FALSE; - end; - end; + // Cancel animation and dragging + if (AnimateTimer.Enabled) then + begin + AnimateTimer.Enabled := FALSE; + // iAnimStep := iAnimStepsCount; + // AnimateTimerTimer(nil); + end; + + if (PBoxBoard.Dragging) then + begin + m_bDraggedMoved := FALSE; + PBoxBoard.EndDrag(FALSE); + end; end; -procedure TChessBoard.WhatSquare(const P: TPoint; - var i: Integer; var j: Integer); +procedure TChessBoard.FSetFlipped(Value: boolean); begin - with P do - begin - i := (X - CHB_X + iSquareSize) div iSquareSize; - j := 8 - (Y - CHB_Y) div iSquareSize; - if (_flipped) then - begin - i := 9 - i; - j := 9 - j; - end; - end; + // TODO: ??? + _flipped := Value; + FDrawBoard; end; -procedure TChessBoard.PBoxBoardMouseDown(Sender: TObject; - Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +procedure TChessBoard.FSetMode(const Value: TMode); var - i, j: Integer; - f: TFigure; + OldMode: TMode; + i: integer; begin - WhatSquare(Point(X, Y), i, j); - if (not ((i in [1..8]) and (j in [1..8]))) then + if (m_Mode = Value) then exit; - f := Position.board[i,j]; - - case Mode of - mGame: - begin - if (ViewGaming) then - exit; - if (Button <> mbLeft) or (Position.color <> player_color) or - (((Position.color <> fcWhite) or (f >= ES)) and - ((Position.color <> fcBlack) or (f <= ES))) then - exit; - end; - else - exit; - end; + OldMode := m_Mode; + m_Mode := Value; - if (anim_step < anim_step_num) then - begin - anim_step:= anim_step_num; - AnimateTimerTimer(nil); - end; + if ((m_Mode in [mView, mEdit]) and (Assigned(m_PromotionForm))) then + m_PromotionForm.Close; - if ((i = m_i0) and (j = m_j0)) then - hilighted := (hilighted xor TRUE) - else - hilighted:= TRUE; + for i := 0 to m_lstLayers.Count - 1 do + TChessBoardLayerBase(m_lstLayers[i]).ROnAfterModeSet(OldMode, m_Mode); - m_fig := f; - m_i0 := i; - m_j0 := j; + FDrawBoard; + HilightLastMove; +end; - dx := (X - CHB_X) mod iSquareSize; - dy := (Y - CHB_Y) mod iSquareSize; - x0 := X; - y0 := Y; - dragged_moved := TRUE; - PBoxBoard.BeginDrag(FALSE); +procedure TChessBoard.FSetCoordinatesShown(Value: boolean); +begin + coord_show := Value; + FDrawBoard; + HilightLastMove; end; -procedure TChessBoard.PBoxBoardMouseMove(Sender: TObject; - Shift: TShiftState; X, Y: Integer); -var - f: TFigure; - i,j: Integer; +procedure TChessBoard.FSetLastMoveHilighted(Value: boolean); begin - WhatSquare(Point(X,Y), i,j); - if (not ((i in [1..8]) and (j in [1..8]))) then - begin - PBoxBoard.Cursor:= crDefault; - exit; - end; + last_hilight := Value; + FDrawBoard; + HilightLastMove; +end; - f := Position.board[i,j]; - case Mode of - mGame: - begin - if (ViewGaming) then - exit; - - if (player_color = Position.color) and - (((Position.color = fcWhite) and (f < ES)) or - ((Position.color = fcBlack) and (f > ES))) then - PBoxBoard.Cursor:= crHandPoint - else - PBoxBoard.Cursor:= crDefault; - end; +function TChessBoard.DoMove(const strMove: string): boolean; +begin + Result := FALSE; - else - PBoxBoard.Cursor:= crDefault; - end; -end; + if (m_Mode = mEdit) then + exit; + // Animation canceling + if (AnimateTimer.Enabled) then + FEndAnimation; -procedure TChessBoard.ROnAfterMoveDone; -var - strLastMove: string; -begin - if (Assigned(Handler) and - ((Mode = mGame) and (Position.color <> player_color))) then + Result := m_ChessRulesEngine.DoMove(strMove); + + if (Result) then begin - strLastMove := ChessRulesEngine.LastMoveStr; - Handler(cbeMoved, @strLastMove, self); + FOnAfterMoveDone; + FAnimate(lastMove.i, lastMove.j); end; end; @@ -669,6 +575,8 @@ end; procedure TChessBoard.FOnAfterMoveDone; var _fig: TFigure; + strLastMove: string; + i: integer; begin m_i0 := lastMove.i0; m_j0 := lastMove.j0; @@ -684,499 +592,615 @@ begin else m_fig := _fig; - ROnAfterMoveDone; -end; + strLastMove := m_ChessRulesEngine.LastMoveStr; + FDoHandler(cbeMoved, @strLastMove, self); + if (m_Mode = mAnalyse) then + m_PlayerColor := PositionColor; -function TChessBoard.RDoMove(i, j: integer; prom_fig: TFigureName = K): boolean; -begin - Result := ChessRulesEngine.DoMove(m_i0, m_j0, i, j, prom_fig); - if (Result) then - FOnAfterMoveDone; + for i := 0 to m_lstLayers.Count - 1 do + TChessBoardLayerBase(m_lstLayers[i]).ROnAfterMoveDone; end; -function TChessBoard.FGetPositionsList: TList; -begin - Result := ChessRulesEngine.PositionsList; -end; - - -procedure TChessBoard.PBoxBoardMouseUp(Sender: TObject; - Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +procedure TChessBoard.FAnimate(const i, j: integer); var - i, j: integer; -begin - case Button of - mbLeft: - case Mode of - mGame: - begin - if (not hilighted) then - exit; - WhatSquare(Point(X, Y), i, j); - if (dragged_moved) then - RDrawBoard - else - begin - hilighted:= FALSE; - if (RDoMove(i, j)) then - begin - Animate(i, j); - SwitchClock(PositionColor); - end - else - RDrawBoard; - end; - end; - end; - - mbRight: - if (Assigned(Handler)) then - Handler(cbeMenu, self); - end; -end; - -procedure TChessBoard.PBoxBoardStartDrag(Sender: TObject; - var DragObject: TDragObject); + x, y: integer; begin - // Копировать изображение пустого поля в m_bmBuf - m_bmBuf.Width:= iSquareSize; m_bmBuf.Height:= iSquareSize; - if (((m_i0 + m_j0) and 1) <> 0) then - m_bmBuf.Canvas.CopyRect(Bounds(0,0, iSquareSize, iSquareSize), - m_bmFigure[ES].Canvas, Bounds(0,0, iSquareSize, iSquareSize)) - else - m_bmBuf.Canvas.CopyRect(Bounds(0,0, iSquareSize, iSquareSize), - m_bmFigure[ES].Canvas, Bounds(iSquareSize,0, iSquareSize, iSquareSize)); - - dragged_moved:= FALSE; -end; + if (not Showing) then + exit; + if ((m_i0 = 0) or (m_j0 = 0)) then + exit; -procedure TChessBoard.Animate(const i, j: integer); -var - x, y: integer; -begin - if not Showing then exit; + if (AnimateTimer.Enabled) then + begin + m_iAnimStep := m_iAnimStepsCount; + exit; + end; case animation of - aNo: anim_step_num:= 1; - aSlow: anim_step_num:= ANIMATION_SLOW; - aQuick: anim_step_num:= ANIMATION_QUICK; + aNo: + m_iAnimStepsCount := 1; + aSlow: + m_iAnimStepsCount := ANIMATION_SLOW; + aQuick: + m_iAnimStepsCount := ANIMATION_QUICK; end; if (_flipped) then begin - x0 := (8 - m_i0) * iSquareSize + CHB_X; - y0 := (m_j0 - 1) * iSquareSize + CHB_Y; - x := (8 - i) * iSquareSize + CHB_X; - y := (j - 1) * iSquareSize + CHB_Y; + x0 := (8 - m_i0) * m_iSquareSize + CHB_X; + y0 := (m_j0 - 1) * m_iSquareSize + CHB_Y; + x := (8 - i) * m_iSquareSize + CHB_X; + y := (j - 1) * m_iSquareSize + CHB_Y; end else begin - x0:= (m_i0 - 1) * iSquareSize + CHB_X; - y0:= (8 - m_j0) * iSquareSize + CHB_Y; - x:= (i - 1) * iSquareSize + CHB_X; - y:= (8 - j) * iSquareSize + CHB_Y; + x0 := (m_i0 - 1) * m_iSquareSize + CHB_X; + y0 := (8 - m_j0) * m_iSquareSize + CHB_Y; + x := (i - 1) * m_iSquareSize + CHB_X; + y := (8 - j) * m_iSquareSize + CHB_Y; end; - anim_dx:= (x-x0) / anim_step_num; - anim_dy:= (y-y0) / anim_step_num; + anim_dx := (x - x0) / m_iAnimStepsCount; + anim_dy := (y - y0) / m_iAnimStepsCount; - anim_step:= 0; + m_iAnimStep := 0; + m_iPrevAnimStep := m_iAnimStep; - // Копировать изображение пустого поля в m_bmBuf - m_bmBuf.Width := iSquareSize; - m_bmBuf.Height := iSquareSize; + // Copy image of the empty square to m_bmBuf + m_bmBuf.Width := m_iSquareSize; + m_bmBuf.Height := m_iSquareSize; if (((m_i0 + m_j0) and 1) <> 0) then - m_bmBuf.Canvas.CopyRect(Bounds(0, 0, iSquareSize, iSquareSize), - m_bmFigure[ES].Canvas, Bounds(0, 0, iSquareSize, iSquareSize)) + m_bmBuf.Canvas.CopyRect(Bounds(0, 0, m_iSquareSize, m_iSquareSize), + m_bmFigure[ES].Canvas, Bounds(0, 0, m_iSquareSize, m_iSquareSize)) else - m_bmBuf.Canvas.CopyRect(Bounds(0, 0, iSquareSize, iSquareSize), - m_bmFigure[ES].Canvas, Bounds(iSquareSize, 0, iSquareSize, iSquareSize)); + m_bmBuf.Canvas.CopyRect(Bounds(0, 0, m_iSquareSize, m_iSquareSize), + m_bmFigure[ES].Canvas, Bounds(m_iSquareSize, 0, m_iSquareSize, m_iSquareSize)); AnimateTimer.Enabled := TRUE; end; -procedure TChessBoard.AnimateTimerTimer(Sender: TObject); +procedure TChessBoard.ResetMoveList; var - X,Y: integer; - rect: TRect; + i: integer; begin - inc(anim_step); - if (anim_step < anim_step_num) then - begin - X := round(x0 + anim_dx * anim_step); - Y := round(y0 + anim_dy * anim_step); - dx := X - x0 - round(anim_dx * (anim_step - 1)); - dy := Y - y0 - round(anim_dy * (anim_step - 1)); + m_ChessRulesEngine.ResetMoveList; - // Восстановить фрагмент на bmHiddenBoard - bmHiddenBoard.Canvas.Draw(X - dx, Y - dy, m_bmBuf); - // Копировать новый фрагмент в буфер - m_bmBuf.Canvas.CopyRect(Bounds(0, 0, iSquareSize, iSquareSize), - bmHiddenBoard.Canvas, Bounds(X, Y, iSquareSize, iSquareSize)); - // Нарисовать перетаскиваемую фигуру в новой позиции - bmHiddenBoard.Canvas.Draw(X, Y, m_bmFigure[m_fig]); - // Перенести новый фрагмент на экран - rect := Bounds(Min(X - dx, X), Min(Y - dy, Y), - abs(dx) + iSquareSize, abs(dy) + iSquareSize); - PBoxBoard.Canvas.CopyRect(rect, bmHiddenBoard.Canvas, rect); - end - else + for i := 0 to m_lstLayers.Count - 1 do + TChessBoardLayerBase(m_lstLayers[i]).ROnResetMoveList; +end; + + +function TChessBoard.SetPosition(const strPosition: string): boolean; +begin + Result := m_ChessRulesEngine.SetPosition(strPosition); + if (Result) then begin - AnimateTimer.Enabled := FALSE; - RDrawBoard; - HilightLastMove; - Evaluate; + FCancelAnimationDragging; + FOnAfterSetPosition; + FDrawBoard; end; end; -procedure TChessBoard.InitPosition; +function TChessBoard.GetPosition: string; begin - ChessRulesEngine.InitNewGame; - RDrawBoard; + Result := m_ChessRulesEngine.GetPosition; end; -procedure TChessBoard.SetMode(const m: TMode); +procedure TChessBoard.FOnAfterSetPosition; +var + strPosition: string; + i: integer; begin - mode_var := m; - RDrawBoard; - HilightLastMove; - if (mode_var <> mGame) then - begin - WhiteFlagButton.Visible := FALSE; - BlackFlagButton.Visible := FALSE; + case m_Mode of + mAnalyse: + m_PlayerColor := PositionColor; + + mEdit: + ResetMoveList; end; + + m_i0 := 0; + m_j0 := 0; + + strPosition := GetPosition; + FDoHandler(cbePosSet, @strPosition, self); + + for i := 0 to m_lstLayers.Count - 1 do + TChessBoardLayerBase(m_lstLayers[i]).ROnAfterSetPosition; end; -procedure TChessBoard.SetTime(color: TFigureColor; const tm: TDateTime); +procedure TChessBoard.FormCreate(Sender: TObject); begin - if (not Unlimited[color]) then - begin - if ((not auto_flag) and (not ViewGaming)) then - begin - case color of - fcWhite: - WhiteFlagButton.Visible := ((player_color = fcBlack) and (tm = 0.0)); - fcBlack: - BlackFlagButton.Visible := ((player_color = fcWhite) and (tm = 0.0)); - end; - end; - player_time[color]:= tm; - ShowTime(color); - end; + // m_iDeltaWidthHeight := Width - Height; + + m_BitmapRes := TBitmapRes.Create(Size(PBoxBoard.Width, PBoxBoard.Height)); + + coord_show:= TRUE; + last_hilight:= FALSE; + m_animation := aQuick; + + m_ChessRulesEngine := TChessRulesEngine.Create(self); + m_lstLayers := TList.Create; end; -function TChessBoard.GetTime(color: TFigureColor): TDateTime; +procedure TChessBoard.FormDestroy(Sender: TObject); +var + _fig: TFigure; + i: integer; begin - Result:= player_time[color]; + for i := m_lstLayers.Count - 1 downto 0 do + RemoveLayer(m_lstLayers[i]); + m_lstLayers.Free; + + m_ChessRulesEngine.Free; + + m_bmHiddenBoard.Free; + m_bmBuf.Free; + + for _fig := Low(TFigure) to High(TFigure) do + m_bmFigure[_fig].Free; + m_bmChessBoard.Free; + + m_BitmapRes.Free; end; -procedure TChessBoard.GameTimerTimer(Sender: TObject); +procedure TChessBoard.PBoxBoardDragDrop(Sender, Source: TObject; X, + Y: Integer); +var + i, j: Integer; begin - if unlimited_var[clock_color] then + FWhatSquare(Point(X, Y), i, j); + case m_Mode of + mGame, mAnalyse: begin - GameTimer.Enabled := FALSE; - exit; + if (FDoMove(i, j)) then + m_bDraggedMoved := TRUE; end; - // TODO: cheating check - player_time[clock_color] := player_time[clock_color] - (Now - past_time); - if player_time[clock_color] <= 0.0 then - begin - player_time[clock_color] := 0.0; - ShowTime(clock_color); - if ((not auto_flag) and (player_color <> clock_color) and (not ViewGaming)) then - begin - case clock_color of - fcWhite: - WhiteFlagButton.Visible := TRUE; - fcBlack: - BlackFlagButton.Visible := TRUE; - end; - end; - if ((player_color <> clock_color) and Assigned(Handler) and (Mode = mGame) and (auto_flag)) then - Handler(cbeTimeOut, self); - GameTimer.Enabled := FALSE; - end; -{$IFNDEF THREADED_CHESSCLOCK} - ShowTime(clock_color); -{$ENDIF} - past_time:= Now; + mEdit: + m_bDraggedMoved := TRUE; + end; end; -procedure TChessBoard.SetUnlimited(color: TFigureColor; const unl: boolean); +procedure TChessBoard.FWhatSquare(const P: TPoint; + var i: Integer; var j: Integer); begin - unlimited_var[color]:= unl; - ShowTime(color); + with P do + begin + i := (X - CHB_X + m_iSquareSize) div m_iSquareSize; + j := 8 - (Y - CHB_Y) div m_iSquareSize; + if (_flipped) then + begin + i := 9 - i; + j := 9 - j; + end; + end; end; -function TChessBoard.GetUnlimited(color: TFigureColor): boolean; +function TChessBoard.FDoMove(i, j: integer; prom_fig: TFigureName = K): boolean; begin - Result := unlimited_var[color]; + Result := m_ChessRulesEngine.DoMove(m_i0, m_j0, i, j, prom_fig); + if (Result) then + FOnAfterMoveDone; end; -procedure TChessBoard.SwitchClock(clock_color: TFigureColor); +procedure TChessBoard.PBoxBoardDragOver(Sender, Source: TObject; X, + Y: Integer; State: TDragState; var Accept: Boolean); +var + rect: TRect; + i, j: integer; begin - self.clock_color := clock_color; - if (not GameTimer.Enabled) then - begin - past_time := Now; - GameTimer.Enabled := TRUE; - end; - if (Assigned(Handler) and (Mode = mGame)) then - Handler(cbeClockSwitched, self); - ShowTime(clock_color); + case State of + dsDragEnter: + m_bHilighted := FALSE; + + dsDragMove: + begin + // Repaint a fragment on m_bmHiddenBoard + m_bmHiddenBoard.Canvas.Draw(x0 - dx, y0 - dy, m_bmBuf); + // Copy new fragment to the buffer + m_bmBuf.Canvas.CopyRect(Bounds(0, 0, m_iSquareSize, m_iSquareSize), + m_bmHiddenBoard.Canvas, Bounds(X - dx, Y - dy, m_iSquareSize, m_iSquareSize)); + // Draw the dragging piece in a new position + m_bmHiddenBoard.Canvas.Draw(X - dx, Y - dy, m_bmFigure[m_fig]); + // Copy the new fragment to the screen + rect:= Bounds(Min(x0,X) - dx, Min(y0, Y) - dy, + abs(X - x0) + m_iSquareSize, abs(Y - y0) + m_iSquareSize); + PBoxBoard.Canvas.CopyRect(rect, m_bmHiddenBoard.Canvas, rect); -{$IFDEF THREADED_CHESSCLOCK} - if (not Assigned(TimeLabelThread)) then - TimeLabelThread := TTimeLabelThread.Create(self); -{$ENDIF} + x0 := X; + y0 := Y; + + FWhatSquare(Point(X,Y), i, j); + + Accept := ((i in [1..8]) and (j in [1..8])); + end; + end; end; -procedure TChessBoard.HilightLastMove; +procedure TChessBoard.PBoxBoardEndDrag(Sender, Target: TObject; X, Y: Integer); var - i, j, l, - _i0, _j0, x, y: integer; + i, j: integer; + bRes: boolean; begin - // вывод последнего сделанного хода - if (last_hilight and (lastMove.i0 <> 0)) then - begin - if (_flipped) then - begin - _i0 := 9 - lastMove.i0; - _j0 := lastMove.j0; - i := 9 - lastMove.i; - j := lastMove.j; - end - else + case m_Mode of + mGame, mAnalyse: begin - _i0 := lastMove.i0; - _j0 := 9 - lastMove.j0; - i := lastMove.i; - j := 9 - lastMove.j; + if (m_bHilighted) then + begin + with m_bmHiddenBoard.Canvas do + begin + Pen.Color:= HILIGHT_COLOR; + Pen.Width := HILIGHT_WIDTH; + x0:= x0 - dx; + y0:= y0 - dy; + MoveTo(x0,y0); + LineTo(x0 + m_iSquareSize - 1, y0); + LineTo(x0 + m_iSquareSize - 1, y0 + m_iSquareSize - 1); + LineTo(x0, y0 + m_iSquareSize - 1); + LineTo(x0, y0); + + PBoxBoardPaint(nil); + end; + end + else + begin + if (AnimateTimer.Enabled) then + AnimateTimer.Enabled := FALSE; + FDrawBoard; + if (m_bDraggedMoved) then + begin + HilightLastMove; + Evaluate; + m_bDraggedMoved := FALSE; + end; + end; end; - x := iSquareSize * (_i0 - 1) + CHB_X; - y := iSquareSize * (_j0 - 1) + CHB_Y; - bmHiddenBoard.Canvas.Pen.Color := HILIGHT_LAST_MOVE_COLOR; - bmHiddenBoard.Canvas.Pen.Width := HILIGHT_LAST_MOVE_WIDTH; - - for l := 1 to 2 do - with bmHiddenBoard.Canvas do + mEdit: + begin + if (m_bDraggedMoved) then begin - MoveTo(x, y); - LineTo(x + iSquareSize - 1, y); - LineTo(x + iSquareSize - 1, y + iSquareSize - 1); - LineTo(x, y + iSquareSize - 1); - LineTo(x, y); + FWhatSquare(Point(X, Y), i, j); + bRes := (((i <> m_i0) or (j <> m_j0)) and Position.SetPiece(i, j, m_fig)); + end + else + bRes := TRUE; - x := iSquareSize * (i - 1) + CHB_X; - y := iSquareSize * (j - 1) + CHB_Y; + if (bRes) then + begin + Position.SetPiece(m_i0, m_j0, ES); + FOnAfterSetPosition; end; - PBoxBoardPaint(nil); - end; + + FDrawBoard; + end; + end; // case end; -procedure TChessBoard.SetPlayerColor(const color: TFigureColor); +procedure TChessBoard.PBoxBoardMouseDown(Sender: TObject; + Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + i, j: Integer; + f: TFigure; begin - FCancelAnimationDragging; - player_color:= color; - if (player_color = fcWhite) then - SetFlipped(FALSE) + if (Button <> mbLeft) then + exit; + + FWhatSquare(Point(X, Y), i, j); + if (not ((i in [1..8]) and (j in [1..8]))) then + exit; + + m_bDraggedMoved := FALSE; + + f := Position.board[i,j]; + + case m_Mode of + mGame, mAnalyse: + begin + if (m_bViewGaming) then + exit; + if ((Position.color <> m_PlayerColor) or + (((Position.color <> fcWhite) or (f >= ES)) and + ((Position.color <> fcBlack) or (f <= ES)))) then + exit; + + if ((i = m_i0) and (j = m_j0)) then + m_bHilighted := (m_bHilighted xor TRUE) + else + m_bHilighted := TRUE; + end; + + mEdit: + begin + if (f = ES) then + exit; + end; + else - SetFlipped(TRUE); // player_color = fcBlack -end; + exit; + end; + if (m_iAnimStep < m_iAnimStepsCount) then + FEndAnimation; -procedure TChessBoard.StopClock; -begin - GameTimer.Enabled := FALSE; - WhiteFlagButton.Visible := FALSE; - BlackFlagButton.Visible := FALSE; + m_fig := f; + m_i0 := i; + m_j0 := j; + + dx := (X - CHB_X) mod m_iSquareSize; + dy := (Y - CHB_Y) mod m_iSquareSize; + x0 := X; + y0 := Y; + + m_bDraggedMoved := TRUE; + PBoxBoard.BeginDrag(FALSE); end; -procedure TChessBoard.FormCanResize(Sender: TObject; var NewWidth, - NewHeight: Integer; var Resize: Boolean); +procedure TChessBoard.PBoxBoardMouseMove(Sender: TObject; Shift: TShiftState; + X, Y: Integer); var - - NewBoardSize: TSize; + f: TFigure; + i,j: Integer; begin - Resize := (m_ResizingType <> rtNo); - if (not Resize) then + FWhatSquare(Point(X,Y), i,j); + if (not ((i in [1..8]) and (j in [1..8]))) then + begin + PBoxBoard.Cursor:= crDefault; exit; + end; - if (m_ResizingType = rtVert) then - NewWidth := NewHeight + m_iDeltaWidthHeight - else // rtHoriz - NewHeight := NewWidth - m_iDeltaWidthHeight; + f := Position.board[i,j]; - NewBoardSize := m_BitmapRes.GetOptimalBoardSize( - Size(PBoxBoard.Width + (NewWidth - Width), PBoxBoard.Height + (NewHeight - Height))); + case m_Mode of + mGame, mAnalyse: + begin + if (m_bViewGaming) then + exit; - Resize := (NewBoardSize.cx > 0) and (NewBoardSize.cy > 0) and - ((NewBoardSize.cx <> PBoxBoard.Width) or (NewBoardSize.cy <> PBoxBoard.Height)); - if (Resize) then - begin - NewWidth := Width + (NewBoardSize.cx - PBoxBoard.Width); - NewHeight := Height + (NewBoardSize.cy - PBoxBoard.Height); + if (m_PlayerColor = Position.color) and + (((Position.color = fcWhite) and (f < ES)) or + ((Position.color = fcBlack) and (f > ES))) then + PBoxBoard.Cursor:= crHandPoint + else + PBoxBoard.Cursor:= crDefault; + end; + + mEdit: + begin + if (f <> ES) then + PBoxBoard.Cursor:= crHandPoint + else + PBoxBoard.Cursor:= crDefault; + end; + + else + PBoxBoard.Cursor := crDefault; end; end; -procedure TChessBoard.FormClose(Sender: TObject; var Action: TCloseAction); +function TChessBoard.FGetPositionsList: TList; begin - if ((not shuted) and Assigned(Handler)) then - begin - Handler(cbeExit, self); - Action:= caNone; - end - else - shuted := FALSE; + Result := m_ChessRulesEngine.PositionsList; end; -procedure TChessBoard.Shut; +function TChessBoard.FGetColorStarts: TFigureColor; begin - shuted:= TRUE; - Close; + Result := m_ChessRulesEngine.GetColorStarts; end; -procedure TChessBoard.Evaluate; +procedure TChessBoard.PBoxBoardMouseUp(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +var + i, j: integer; begin - if (Assigned(Handler)) then - begin - case ChessRulesEngine.GetEvaluation of - evMate: - Handler(cbeMate, self); - evStaleMate: - Handler(cbeStaleMate, self); + case Button of + mbLeft: + begin + case m_Mode of + mGame, mAnalyse: + begin + if (not m_bHilighted) then + exit; + FWhatSquare(Point(X, Y), i, j); + if (m_bDraggedMoved) then + FDrawBoard + else + begin + m_bHilighted := FALSE; + if (FDoMove(i, j)) then + FAnimate(i, j) + else + FDrawBoard; + end; + end; + + mEdit: + begin + if (m_bDraggedMoved) then + exit; + // Assert(empty field) + FWhatSquare(Point(X, Y), i, j); + if (Position.SetPiece(i, j, m_EditPiece)) then + begin + FOnAfterSetPosition; + FDrawBoard; + end; + end; + + end; // case end; + + mbRight: + begin + FDoHandler(cbeMenu, self); + end; + end; end; -procedure TChessBoard.PPRandom; +procedure TChessBoard.PBoxBoardStartDrag(Sender: TObject; + var DragObject: TDragObject); begin - ChessRulesEngine.InitNewPPRandomGame; - RDrawBoard; + // Copy image of an empty square to m_bmBuf + m_bmBuf.Width := m_iSquareSize; + m_bmBuf.Height:= m_iSquareSize; + if (((m_i0 + m_j0) and 1) <> 0) then + m_bmBuf.Canvas.CopyRect(Bounds(0,0, m_iSquareSize, m_iSquareSize), + m_bmFigure[ES].Canvas, Bounds(0,0, m_iSquareSize, m_iSquareSize)) + else + m_bmBuf.Canvas.CopyRect(Bounds(0,0, m_iSquareSize, m_iSquareSize), + m_bmFigure[ES].Canvas, Bounds(m_iSquareSize,0, m_iSquareSize, m_iSquareSize)); + + m_bDraggedMoved := FALSE; end; -procedure TChessBoard.TakeBack; +procedure TChessBoard.InitPosition; begin - if (not ChessRulesEngine.TakeBack) then - exit; - ROnAfterSetPosition; - // TODO: animation - RDrawBoard; + m_ChessRulesEngine.InitNewGame; + + FCancelAnimationDragging; + FOnAfterSetPosition; + + FDrawBoard; end; -procedure TChessBoard.SetHilightLastMove(const yes: boolean); +procedure TChessBoard.PPRandom; begin - last_hilight := yes; - RDrawBoard; - HilightLastMove; + m_ChessRulesEngine.InitNewPPRandomGame; + + FCancelAnimationDragging; + FOnAfterSetPosition; + + FDrawBoard; end; -procedure TChessBoard.SetCoordinates(const yes: boolean); +procedure TChessBoard.TakeBack; begin - coord_show := yes; - RDrawBoard; - HilightLastMove; + if (m_Mode = mEdit) then + exit; + + if (not m_ChessRulesEngine.TakeBack) then + exit; + + FOnAfterSetPosition; + // TODO: animation + FDrawBoard; end; function TChessBoard.NMoveDone: integer; begin - Result := ChessRulesEngine.NMovesDone; + Result := m_ChessRulesEngine.NMovesDone; end; -procedure TChessBoard.ROnAfterSetPosition; +function TChessBoard.NPlysDone: integer; begin + Result := m_ChessRulesEngine.NPlysDone; end; -{$IFDEF THREADED_CHESSCLOCK} -procedure TTimeLabelThread.Execute; + +function TChessBoard.FGetMovesOffset: integer; begin - while ChessBoard.GameTimer.Enabled do - begin - if self.player_time[fcWhite] <> ChessBoard.player_time[fcWhite] then - ChessBoard.ShowTime(fcWhite); - if self.player_time[fcBlack] <> ChessBoard.player_time[fcBlack] then - ChessBoard.ShowTime(fcBlack); - Sleep(ChessBoard.GameTimer.Interval div 2); - end; - ChessBoard.TimeLabelThread := nil; + Result := m_ChessRulesEngine.MovesOffset; end; -constructor TTimeLabelThread.Create(ChessBoard: TChessBoard); +function TChessBoard.FGetPositionColor: TFigureColor; begin - self.ChessBoard := ChessBoard; - self.player_time[fcWhite] := ChessBoard.player_time[fcWhite]; - self.player_time[fcBlack] := ChessBoard.player_time[fcBlack]; - - inherited Create(TRUE); -//Priority := tpNormal; - FreeOnTerminate := TRUE; - Resume; + Result := Position.color; end; -{$ENDIF} -procedure TChessBoard.FormKeyDown(Sender: TObject; var Key: Word; - Shift: TShiftState); + +procedure TChessBoard.FormCanResize(Sender: TObject; var NewWidth, + NewHeight: Integer; var Resize: Boolean); +var + NewBoardSize: TSize; begin - if Assigned(Handler) then - Handler(cbeKeyPressed, Pointer(Key), self); -end; + if (not m_bDeltaWidthHeightFlag) then + begin + m_iDeltaWidthHeight := Width - Height; + m_bDeltaWidthHeightFlag := TRUE; + end; + Resize := (m_ResizingType <> rtNo); + if (not Resize) then + exit; -function TChessBoard.GetStayOnTop: boolean; -begin - Result := (self.FormStyle = fsStayOnTop); -end; + if (m_ResizingType = rtVert) then + NewWidth := NewHeight + m_iDeltaWidthHeight + else // rtHoriz + NewHeight := NewWidth - m_iDeltaWidthHeight; + NewBoardSize := m_BitmapRes.GetOptimalBoardSize( + Size(PBoxBoard.Width + (NewWidth - Width), PBoxBoard.Height + (NewHeight - Height))); -procedure TChessBoard.SetStayOnTop(onTop: boolean); -begin - if (onTop) then - self.FormStyle := fsStayOnTop - else - self.FormStyle := fsNormal; + Resize := (NewBoardSize.cx > 0) and (NewBoardSize.cy > 0) and + ((NewBoardSize.cx <> PBoxBoard.Width) or (NewBoardSize.cy <> PBoxBoard.Height)); + if (Resize) then + begin + NewWidth := Width + (NewBoardSize.cx - PBoxBoard.Width); + NewHeight := Height + (NewBoardSize.cy - PBoxBoard.Height); + end; end; -procedure TChessBoard.FormActivate(Sender: TObject); +procedure TChessBoard.FormResize(Sender: TObject); +var + _fig: TFigure; begin - if Assigned(Handler) then - Handler(cbeActivate, self); -end; + FreeAndNil(m_bmChessBoard); + m_BitmapRes.CreateBoardBitmap(Size(PBoxBoard.Width, PBoxBoard.Height), self.Color, + m_bmChessBoard); + m_iSquareSize := m_BitmapRes.SquareSize; + + for _fig := Low(TFigure) to High(TFigure) do + begin + FreeAndNil(m_bmFigure[_fig]); + m_BitmapRes.CreateFigureBitmap(_fig, m_bmFigure[_fig]); + end; + // Graphics initialization + if (not Assigned(m_bmHiddenBoard)) then + begin + m_bmHiddenBoard := Graphics.TBitmap.Create; + m_bmHiddenBoard.Palette := m_bmChessBoard.Palette; + m_bmHiddenBoard.Canvas.Font := PBoxBoard.Font; // Характеристики шрифта координат задаются в инспекторе + m_bmHiddenBoard.Canvas.Brush.Style := bsClear; + end; + m_bmHiddenBoard.Width := m_bmChessBoard.Width; + m_bmHiddenBoard.Height := m_bmChessBoard.Height; -procedure TChessBoard.WMMoving(var Msg: TWMMoving); -begin - // TODO: it's possible to handle if form is outside of the screen - if Assigned(Handler) then - Handler(cbeFormMoving, Pointer(Msg.DragRect.Left - Left), Pointer(Msg.DragRect.Top - Top)); - inherited; + if (not Assigned(m_bmBuf)) then + begin + m_bmBuf := Graphics.TBitmap.Create; + m_bmBuf.Palette:= m_bmChessBoard.Palette; + end; + + FDrawBoard; end; @@ -1193,199 +1217,165 @@ begin PRect(Msg.LParam).Left := Left; PRect(Msg.LParam).Top := Top; end; - end; { case } + end; // case end; -function TChessBoard.FGetPositinoColor: TFigureColor; +procedure TChessBoard.FDoHandler(e: TChessBoardEvent; d1: pointer = nil; d2: pointer = nil); begin - Result := Position.color; + if (Assigned(FHandler)) then + FHandler(e, d1, d2); end; -function TChessBoard.FGetPosition: PChessPosition; +function TChessBoard.FGetMoveNotationFormat: TMoveNotationFormat; begin - Result := ChessRulesEngine.Position; + Result := m_ChessRulesEngine.MoveNotationFormat; end; -function TChessBoard.AskPromotionFigure(FigureColor: TFigureColor): TFigureName; +procedure TChessBoard.FSetMoveNotationFormat(Value: TMoveNotationFormat); begin - if (Showing) then - begin - with TPromotionForm.Create(self, m_BitmapRes) do - try - Result := ShowPromotion(FigureColor); - finally - Free; - end; - end - else - Result := Q; + m_ChessRulesEngine.MoveNotationFormat := Value; end; -function TChessBoard.FGetLastMove: PMoveAbs; +function TChessBoard.FGetFENFormat: boolean; begin - Result := ChessRulesEngine.lastMove; + Result := m_ChessRulesEngine.FENFormat; end; -procedure TChessBoard.FCancelAnimationDragging; +procedure TChessBoard.FSetFENFormat(bValue: boolean); begin - // Отмена анимации и перетаскивания - if (AnimateTimer.Enabled) then - begin - AnimateTimer.Enabled := FALSE; - // anim_step := anim_step_num; - // AnimateTimerTimer(nil); - end; - if (PBoxBoard.Dragging) then - begin - dragged_moved := FALSE; - PBoxBoard.EndDrag(FALSE); - end; + m_ChessRulesEngine.FENFormat := bValue; end; -procedure TChessBoard.FlagButtonClick(Sender: TObject); +procedure TChessBoard.BeginUpdate; begin - if Assigned(Handler) and (Mode = mGame) then - Handler(cbeTimeOut, self); + inc(m_iUpdateCounter); end; -procedure TChessBoard.SetAutoFlag(auto_flag: boolean); +procedure TChessBoard.EndUpdate; begin - self.auto_flag := auto_flag; - if (auto_flag) then + if (m_iUpdateCounter > 0) then begin - WhiteFlagButton.Visible := FALSE; - BlackFlagButton.Visible := FALSE; + dec(m_iUpdateCounter); + if (m_iUpdateCounter = 0) then + FDrawBoard; end; end; -procedure TChessBoard.FormResize(Sender: TObject); -var - _fig: TFigure; +procedure TChessBoard.FOnDrawLayerUpdate(const ADrawLayer: TChessBoardLayerBase); begin - FreeAndNil(m_bmChessBoard); - m_BitmapRes.CreateBoardBitmap(Size(PBoxBoard.Width, PBoxBoard.Height), self.Color, - m_bmChessBoard); - iSquareSize := m_BitmapRes.SquareSize; + if (not AnimateTimer.Enabled) then + FDrawBoard; +end; - for _fig := Low(TFigure) to High(TFigure) do - begin - FreeAndNil(m_bmFigure[_fig]); - m_BitmapRes.CreateFigureBitmap(_fig, m_bmFigure[_fig]); - end; - // Graphics initialization - if (not Assigned(bmHiddenBoard)) then - begin - bmHiddenBoard := TBitmap.Create; - bmHiddenBoard.Palette := m_bmChessBoard.Palette; - bmHiddenBoard.Canvas.Font := PBoxBoard.Font; // Характеристики шрифта координат задаются в инспекторе - bmHiddenBoard.Canvas.Brush.Style := bsClear; - end; - bmHiddenBoard.Width := m_bmChessBoard.Width; - bmHiddenBoard.Height := m_bmChessBoard.Height; +procedure TChessBoard.AddLayer(const ALayer: TChessBoardLayerBase); +begin + if (m_lstLayers.IndexOf(ALayer) >= 0) then + exit; - if (not Assigned(m_bmBuf)) then + ALayer.ChessBoard := self; + m_lstLayers.Add(ALayer); + + FOnDrawLayerUpdate(ALayer); +end; + + +procedure TChessBoard.RemoveLayer(const ALayer: TChessBoardLayerBase); +begin + if (m_lstLayers.Remove(ALayer) >= 0) then begin - m_bmBuf := TBitmap.Create; - m_bmBuf.Palette:= m_bmChessBoard.Palette; + ALayer.ChessBoard := nil; + + FOnDrawLayerUpdate(ALayer); end; +end; - RDrawBoard; + +function TChessBoard.IsMoveAnimating: boolean; +begin + Result := AnimateTimer.Enabled; end; +//////////////////////////////////////////////////////////////////////////////// +// TChessBoardDrawBase -procedure TChessBoard.TimePanelResize(Sender: TObject); -var - rRatio: real; +procedure TChessBoardLayerBase.RDoUpdate; +begin + if (Assigned(m_ChessBoard)) then + m_ChessBoard.FOnDrawLayerUpdate(self); +end; + + +function TChessBoardLayerBase.FGetSquareSize: integer; begin - // Adjust panels on TimePanel - rRatio := TimePanel.Width / m_iTimePanelInitialWidth; - WhitePanel.Left := Round(rRatio * m_iWhitePanelInitialLeft); - WhitePanel.Width := m_iWhitePanelInitialWidth; - BlackPanel.Left := Round(rRatio * m_iBlackPanelInitialLeft); - BlackPanel.Width := m_iBlackPanelInitialWidth; + if (Assigned(m_ChessBoard)) then + Result := m_ChessBoard.SquareSize + else + Result := 0; +end; - WhiteTimeLabel.Font.Assign(m_TimeFont); - BlackTimeLabel.Font.Assign(m_TimeFont); - if (WhitePanel.Left + WhitePanel.Width < BlackPanel.Left) then - begin - WhiteLabel.Caption := WHITE_LONG_LABEL; - BlackLabel.Caption := BLACK_LONG_LABEL; - end +function TChessBoardLayerBase.FGetCanvas: TCanvas; +begin + if (Assigned(m_ChessBoard)) then + Result := m_ChessBoard.FGetHiddenBoardCanvas else - begin - WhitePanel.Left := 4; - WhitePanel.Width := TimePanel.Width div 2; - BlackPanel.Left := TimePanel.Width div 2; - BlackPanel.Width := TimePanel.Width div 2 - 4; + Result := nil; +end; - WhiteLabel.Caption := WHITE_MEDIUM_LABEL; - BlackLabel.Caption := BLACK_MEDIUM_LABEL; - end; - // Adjust color labels - if ((WhiteTimeLabel.Left + WhiteTimeLabel.Width > WhitePanel.Width) or - (BlackTimeLabel.Left + BlackTimeLabel.Width > BlackPanel.Width)) then - begin - WhiteTimeLabel.Font.Size := WhiteTimeLabel.Font.Size - 4; - BlackTimeLabel.Font.Size := BlackTimeLabel.Font.Size - 4; - WhiteLabel.Caption := WHITE_SHORT_LABEL; - BlackLabel.Caption := BLACK_SHORT_LABEL; - end; +function TChessBoardLayerBase.FGetPosition: PChessPosition; +begin + if (Assigned(m_ChessBoard)) then + Result := m_ChessBoard.Position + else + Result := nil; end; -procedure TChessBoard.FFlashWindow; -var - flushWindowInfo: TFlashWInfo; +function TChessBoardLayerBase.RGetColorStarts: TFigureColor; begin - // Flash with taskbar - flushWindowInfo.cbSize := SizeOf(flushWindowInfo); - flushWindowInfo.hwnd := Application.Handle; - flushWindowInfo.dwflags := FLASHW_TRAY; // FLASHW_ALL; //FLASHW_TRAY; - flushWindowInfo.ucount := 3; // Flash times - flushWindowInfo.dwtimeout := 0; // speed in msec, 0 - frequency of cursor flashing - FlashWindowEx(flushWindowInfo); + if (Assigned(m_ChessBoard)) then + Result := m_ChessBoard.FGetColorStarts + else + Result := fcWhite; +end; + - if (self.Focused) then - exit; - // Flash window - flushWindowInfo.hwnd := self.Handle; // handle of the flashing window - flushWindowInfo.dwflags := FLASHW_CAPTION; // FLASHW_TRAY; // FLASHW_ALL; //FLASHW_TRAY; - FlashWindowEx(flushWindowInfo); +function TChessBoardLayerBase.FGetPositionsList: TList; +begin + if (Assigned(m_ChessBoard)) then + Result := m_ChessBoard.PositionsList + else + Result := nil; end; -procedure TChessBoard.FLocalize; +procedure TChessBoardLayerBase.ROnAfterMoveDone; begin - with TLocalizer.Instance do - begin - WHITE_LONG_LABEL := GetLabel(13); - WHITE_MEDIUM_LABEL := GetLabel(14); - WHITE_SHORT_LABEL := GetLabel(15); - BLACK_LONG_LABEL := GetLabel(16); - BLACK_MEDIUM_LABEL := GetLabel(17); - BLACK_SHORT_LABEL := GetLabel(18); - end; +end; - TimePanelResize(nil); + +procedure TChessBoardLayerBase.ROnAfterSetPosition; +begin end; -initialization +procedure TChessBoardLayerBase.ROnAfterModeSet(const OldValue, NewValue: TMode); begin - Randomize; // для PP Random end; -finalization + +procedure TChessBoardLayerBase.ROnResetMoveList; +begin +end; end. -- cgit v1.2.3