You've already forked lazarus-ccr
fpchess: clean up and fixes of the winboard module
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2843 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -18,7 +18,6 @@ type
|
|||||||
textEnginePatch : TStaticText;
|
textEnginePatch : TStaticText;
|
||||||
editEnginePatch : TEdit;
|
editEnginePatch : TEdit;
|
||||||
EngineStringList: TStringList;
|
EngineStringList: TStringList;
|
||||||
side : boolean; //Side to move true=human.
|
|
||||||
public
|
public
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
procedure CreateUserInterface(); override;
|
procedure CreateUserInterface(); override;
|
||||||
@ -27,6 +26,7 @@ type
|
|||||||
procedure FreeUserInterface(); override;
|
procedure FreeUserInterface(); override;
|
||||||
procedure PrepareForGame(); override;
|
procedure PrepareForGame(); override;
|
||||||
procedure HandleOnMove(AFrom, ATo: TPoint); override;
|
procedure HandleOnMove(AFrom, ATo: TPoint); override;
|
||||||
|
procedure HandleOnTimer(); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -78,9 +78,16 @@ var
|
|||||||
CompMove: moveInCoord;
|
CompMove: moveInCoord;
|
||||||
begin
|
begin
|
||||||
moveStr:=vwinboardConn.coordToString(AFrom,ATo,vChessGame.PreviousMove.PieceMoved,vChessGame.PreviousMove.PieceEaten);
|
moveStr:=vwinboardConn.coordToString(AFrom,ATo,vChessGame.PreviousMove.PieceMoved,vChessGame.PreviousMove.PieceEaten);
|
||||||
|
|
||||||
vwinboardConn.tellMove(moveStr);
|
vwinboardConn.tellMove(moveStr);
|
||||||
compMove:=vwinboardConn.engineMove;
|
end;
|
||||||
|
|
||||||
|
procedure TWinboardChessModule.HandleOnTimer;
|
||||||
|
var
|
||||||
|
CompMove: moveInCoord;
|
||||||
|
begin
|
||||||
|
CompMove[1]:=Point(1,1);
|
||||||
|
CompMove[2]:=Point(1,1);
|
||||||
|
CompMove:=vwinboardConn.engineMove;
|
||||||
vChessGame.MovePiece(CompMove[1],CompMove[2]);
|
vChessGame.MovePiece(CompMove[1],CompMove[2]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -101,5 +108,5 @@ end;
|
|||||||
initialization
|
initialization
|
||||||
RegisterChessModule(TWinboardChessModule.Create);
|
RegisterChessModule(TWinboardChessModule.Create);
|
||||||
finalization
|
finalization
|
||||||
vwinboardConn.stopEngine;
|
vwinboardConn.stopEngine(True);
|
||||||
end.
|
end.
|
||||||
|
@ -11,15 +11,16 @@ unit winboardConn;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Forms, Process, StdCtrls, chessgame;
|
Classes, SysUtils, Forms, Process, StdCtrls, SorokinRegExpr, chessgame;
|
||||||
|
|
||||||
type
|
type
|
||||||
moveInCoord = array[1..2] of TPoint;
|
moveInCoord = array[1..2] of TPoint;
|
||||||
|
|
||||||
TwinboardConn = class
|
TWinboardConn = class
|
||||||
public
|
public
|
||||||
procedure startEngine(path : String);
|
procedure startEngine(path : String);
|
||||||
procedure stopEngine;
|
procedure stopEngine(freeProcess : boolean);
|
||||||
|
destructor Destroy; override;
|
||||||
procedure tellMove(move : String);
|
procedure tellMove(move : String);
|
||||||
function engineMove() : moveInCoord;
|
function engineMove() : moveInCoord;
|
||||||
function coordToString(AFrom, ATo : TPoint; pieceFrom, pieceTo : TChessTile) : String;
|
function coordToString(AFrom, ATo : TPoint; pieceFrom, pieceTo : TChessTile) : String;
|
||||||
@ -29,99 +30,85 @@ type
|
|||||||
function extractMove : string;
|
function extractMove : string;
|
||||||
function letterToNumber(num:String) : Integer;
|
function letterToNumber(num:String) : Integer;
|
||||||
function numberToLetter(n : integer) : String;
|
function numberToLetter(n : integer) : String;
|
||||||
procedure detectEngine(path : String);
|
//procedure detectEngine(path : String);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
engineProcess : TProcess;
|
engineProcess : TProcess;
|
||||||
outputText : String;
|
outputText : String;
|
||||||
vwinboardConn : TwinboardConn;
|
vwinboardConn : TWinboardConn;
|
||||||
algebraicInput: boolean;
|
algebraicInput: boolean;
|
||||||
engineMoveComIndex : integer;
|
engineRegExpression: TRegExpr;
|
||||||
engineMoveCommand : array[1..4,1..2] of String;
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
procedure TwinboardConn.startEngine(path : String);
|
destructor TWinboardConn.Destroy;
|
||||||
begin
|
begin
|
||||||
engineMoveCommand[1,1]:='gnuchess 5.07';
|
stopEngine(True);
|
||||||
engineMoveCommand[1,2]:='My move is: ';
|
|
||||||
engineMoveCommand[2,1]:='phalanx';
|
|
||||||
engineMoveCommand[2,2]:='my move is ';
|
|
||||||
engineMoveCommand[3,1]:='gnuchess 5.08';
|
|
||||||
engineMoveCommand[3,2]:='move ';
|
|
||||||
engineMoveCommand[4,1]:='gnuchess 6.0.1';
|
|
||||||
engineMoveCommand[4,2]:='My move is : ';
|
|
||||||
|
|
||||||
if engineProcess<>nil then
|
Inherited Destroy;
|
||||||
if engineProcess.Running then
|
end;
|
||||||
stopEngine;
|
|
||||||
|
procedure TWinboardConn.startEngine(path : String);
|
||||||
|
var extraCommands : String;
|
||||||
|
begin
|
||||||
|
//stop engine if it is running
|
||||||
|
stopEngine(False);
|
||||||
|
|
||||||
|
//create TProcess and start the engine in xboard mode
|
||||||
engineProcess:= TProcess.Create(nil);
|
engineProcess:= TProcess.Create(nil);
|
||||||
|
engineRegExpression:= TRegExpr.Create;
|
||||||
engineProcess.CommandLine := path;
|
engineProcess.CommandLine := path;
|
||||||
|
|
||||||
engineProcess.Options := engineProcess.Options + [poUsePipes];
|
engineProcess.Options := engineProcess.Options + [poUsePipes];
|
||||||
engineProcess.Execute;
|
engineProcess.Execute;
|
||||||
|
extraCommands:='xboard'+#13+#10;
|
||||||
detectEngine(path);
|
EngineProcess.Input.Write(extraCommands[1], length(extraCommands));
|
||||||
end;
|
extraCommands:='level 60 0.5 3'+#13+#10;
|
||||||
|
EngineProcess.Input.Write(extraCommands[1], length(extraCommands));
|
||||||
procedure TwinboardConn.detectEngine(path : String);
|
|
||||||
var engineOut : String;
|
|
||||||
extraCommand : String;
|
|
||||||
begin
|
|
||||||
//crafty only show his moves in abbreviated algebraic notation, it's not in
|
|
||||||
//the array 'engineMoveCommand' because this is not implemented yet.
|
|
||||||
if pos(path,'crafty')<> 0 then algebraicInput:=true;
|
|
||||||
sleep(50); //just to guarantee that the engine has already tell his initial output
|
|
||||||
readFromPipe;
|
|
||||||
if pos('GNU Chess 5.07',outputText)>0 then
|
|
||||||
engineMoveComIndex:=1;
|
|
||||||
if pos('Phalanx',outputText)>0 then
|
|
||||||
engineMoveComIndex:=2;
|
|
||||||
if pos('GNU Chess 5.08',outputText)>0 then
|
|
||||||
engineMoveComIndex:=3;
|
|
||||||
if pos('GNU Chess 6.0.1',outputText)>0 then
|
|
||||||
engineMoveComIndex:=4;
|
|
||||||
extraCommand:='xboard'+#13+#10;
|
|
||||||
EngineProcess.Input.Write(extraCommand[1], length(extraCommand));
|
|
||||||
sleep(100);
|
|
||||||
outputText:='';
|
outputText:='';
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TwinboardConn.stopEngine;
|
procedure TWinboardConn.stopEngine(freeProcess : boolean);
|
||||||
begin
|
begin
|
||||||
if engineProcess<>nil then
|
if engineProcess<>nil then
|
||||||
if engineProcess.Running then
|
if engineProcess.Running then
|
||||||
|
begin
|
||||||
|
engineProcess.Input.WriteAnsiString('quit'+#13+#10);
|
||||||
engineProcess.Terminate(0);
|
engineProcess.Terminate(0);
|
||||||
engineProcess.free;
|
end;
|
||||||
|
if freeProcess then
|
||||||
|
begin
|
||||||
|
engineProcess.free;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TwinboardConn.tellMove(move : String);
|
procedure TWinboardConn.tellMove(move : String);
|
||||||
begin
|
begin
|
||||||
move := move+#13+#10;
|
move := move+#13+#10;
|
||||||
EngineProcess.Input.Write(move[1], length(move));
|
EngineProcess.Input.Write(move[1], length(move));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//return the engine move.
|
//return the engine move.
|
||||||
function TwinboardConn.engineMove : moveInCoord;
|
function TWinboardConn.engineMove : moveInCoord;
|
||||||
var move : String;
|
var move : String;
|
||||||
points: moveInCoord;
|
points: moveInCoord;
|
||||||
begin
|
begin
|
||||||
sleep(500);
|
engineRegExpression.Expression:='(?m)^(My move|my move|move)( is|)(: | : | )';
|
||||||
repeat
|
readFromPipe;
|
||||||
Application.processMessages;
|
if engineRegExpression.Exec(outputText) then
|
||||||
readFromPipe;
|
begin
|
||||||
until pos(engineMoveCommand[engineMoveComIndex][2],outputText)>0;
|
move := extractMove;
|
||||||
move := extractMove;
|
points := stringToCoord(move);
|
||||||
points := stringToCoord(move);
|
result:=points;
|
||||||
result:=points;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TwinboardConn.coordToString(AFrom, ATo : TPoint; pieceFrom, pieceTo : TChessTile) : String;
|
function TWinboardConn.coordToString(AFrom, ATo : TPoint; pieceFrom, pieceTo : TChessTile) : String;
|
||||||
var
|
var
|
||||||
move : String;
|
move : String;
|
||||||
begin
|
begin
|
||||||
//still need to verify castle an en passant
|
|
||||||
|
|
||||||
move:= move + numberToLetter(AFrom.X);
|
move:= move + numberToLetter(AFrom.X);
|
||||||
move:= move + intToStr(AFrom.Y);
|
move:= move + intToStr(AFrom.Y);
|
||||||
@ -132,7 +119,7 @@ begin
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TwinboardConn.numberToLetter(n : integer) : String;
|
function TWinboardConn.numberToLetter(n : integer) : String;
|
||||||
begin
|
begin
|
||||||
case n of
|
case n of
|
||||||
1 : result := 'a';
|
1 : result := 'a';
|
||||||
@ -146,10 +133,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TwinboardConn.stringToCoord(moveStr : String) : moveInCoord;
|
function TWinboardConn.stringToCoord(moveStr : String) : moveInCoord;
|
||||||
var move : moveInCoord;
|
var move : moveInCoord;
|
||||||
begin
|
begin
|
||||||
//need to verify castle here
|
|
||||||
if moveStr[1] in ['P','R','N','B','Q','K'] then
|
if moveStr[1] in ['P','R','N','B','Q','K'] then
|
||||||
Delete(moveStr,1,1);
|
Delete(moveStr,1,1);
|
||||||
move[1].X:=letterToNumber(moveStr[1]);
|
move[1].X:=letterToNumber(moveStr[1]);
|
||||||
@ -163,7 +149,7 @@ begin
|
|||||||
result:=move;
|
result:=move;
|
||||||
end;
|
end;
|
||||||
//Transform collum letter to number
|
//Transform collum letter to number
|
||||||
function TwinboardConn.letterToNumber(num:String) : Integer;
|
function TWinboardConn.letterToNumber(num:String) : Integer;
|
||||||
begin
|
begin
|
||||||
case num[1] of
|
case num[1] of
|
||||||
'a' : result:=1;
|
'a' : result:=1;
|
||||||
@ -178,8 +164,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//read all the output text from the TProcess pipe
|
//read all the output text from the TProcess pipe (basically copy/pasted from the
|
||||||
procedure TwinboardConn.readFromPipe;
|
//TProcess example)
|
||||||
|
procedure TWinboardConn.readFromPipe;
|
||||||
var
|
var
|
||||||
NoMoreOutput: boolean;
|
NoMoreOutput: boolean;
|
||||||
|
|
||||||
@ -211,22 +198,27 @@ begin
|
|||||||
until noMoreOutput;
|
until noMoreOutput;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TwinboardConn.extractMove : string;
|
function TWinboardConn.extractMove : string;
|
||||||
var move : String;
|
var
|
||||||
i,p : integer;
|
initialPos : integer;
|
||||||
begin
|
begin
|
||||||
p := pos(engineMoveCommand[engineMoveComIndex][2],outputText);
|
//delete the text from the start of the engine output
|
||||||
|
engineRegExpression.Expression:='.*(My move|my move|move)( is|)(: | : | )';
|
||||||
|
engineRegExpression.Exec(outputText);
|
||||||
|
initialPos := pos(engineRegExpression.Match[0],outputText);
|
||||||
|
|
||||||
if p>=0 then
|
Delete(outputText,initialPos,Length(engineRegExpression.Match[0]));
|
||||||
|
|
||||||
|
//if there's text after the engine move, delete it too
|
||||||
|
engineRegExpression.Expression:=' .+';
|
||||||
|
if (engineRegExpression.Exec(outputText)) then
|
||||||
begin
|
begin
|
||||||
p := p+length(engineMoveCommand[engineMoveComIndex][2]);
|
initialPos := pos(engineRegExpression.Match[0],outputText);
|
||||||
while outputText[p]<>#10 do
|
Delete(outputText,initialPos,Length(engineRegExpression.Match[0]));
|
||||||
begin
|
|
||||||
move:= move+outputText[p];
|
|
||||||
inc(p);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
result:=move;
|
|
||||||
|
result:= outputText;
|
||||||
|
|
||||||
outputText:='';
|
outputText:='';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user