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;
|
||||
editEnginePatch : TEdit;
|
||||
EngineStringList: TStringList;
|
||||
side : boolean; //Side to move true=human.
|
||||
public
|
||||
constructor Create; override;
|
||||
procedure CreateUserInterface(); override;
|
||||
@ -27,6 +26,7 @@ type
|
||||
procedure FreeUserInterface(); override;
|
||||
procedure PrepareForGame(); override;
|
||||
procedure HandleOnMove(AFrom, ATo: TPoint); override;
|
||||
procedure HandleOnTimer(); override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -78,9 +78,16 @@ var
|
||||
CompMove: moveInCoord;
|
||||
begin
|
||||
moveStr:=vwinboardConn.coordToString(AFrom,ATo,vChessGame.PreviousMove.PieceMoved,vChessGame.PreviousMove.PieceEaten);
|
||||
|
||||
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]);
|
||||
end;
|
||||
|
||||
@ -101,5 +108,5 @@ end;
|
||||
initialization
|
||||
RegisterChessModule(TWinboardChessModule.Create);
|
||||
finalization
|
||||
vwinboardConn.stopEngine;
|
||||
vwinboardConn.stopEngine(True);
|
||||
end.
|
||||
|
@ -11,15 +11,16 @@ unit winboardConn;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Forms, Process, StdCtrls, chessgame;
|
||||
Classes, SysUtils, Forms, Process, StdCtrls, SorokinRegExpr, chessgame;
|
||||
|
||||
type
|
||||
moveInCoord = array[1..2] of TPoint;
|
||||
|
||||
TwinboardConn = class
|
||||
TWinboardConn = class
|
||||
public
|
||||
procedure startEngine(path : String);
|
||||
procedure stopEngine;
|
||||
procedure stopEngine(freeProcess : boolean);
|
||||
destructor Destroy; override;
|
||||
procedure tellMove(move : String);
|
||||
function engineMove() : moveInCoord;
|
||||
function coordToString(AFrom, ATo : TPoint; pieceFrom, pieceTo : TChessTile) : String;
|
||||
@ -29,99 +30,85 @@ type
|
||||
function extractMove : string;
|
||||
function letterToNumber(num:String) : Integer;
|
||||
function numberToLetter(n : integer) : String;
|
||||
procedure detectEngine(path : String);
|
||||
//procedure detectEngine(path : String);
|
||||
end;
|
||||
|
||||
var
|
||||
engineProcess : TProcess;
|
||||
outputText : String;
|
||||
vwinboardConn : TwinboardConn;
|
||||
vwinboardConn : TWinboardConn;
|
||||
algebraicInput: boolean;
|
||||
engineMoveComIndex : integer;
|
||||
engineMoveCommand : array[1..4,1..2] of String;
|
||||
engineRegExpression: TRegExpr;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TwinboardConn.startEngine(path : String);
|
||||
destructor TWinboardConn.Destroy;
|
||||
begin
|
||||
engineMoveCommand[1,1]:='gnuchess 5.07';
|
||||
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 : ';
|
||||
stopEngine(True);
|
||||
|
||||
if engineProcess<>nil then
|
||||
if engineProcess.Running then
|
||||
stopEngine;
|
||||
Inherited Destroy;
|
||||
end;
|
||||
|
||||
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);
|
||||
engineRegExpression:= TRegExpr.Create;
|
||||
engineProcess.CommandLine := path;
|
||||
|
||||
engineProcess.Options := engineProcess.Options + [poUsePipes];
|
||||
engineProcess.Execute;
|
||||
|
||||
detectEngine(path);
|
||||
end;
|
||||
|
||||
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);
|
||||
extraCommands:='xboard'+#13+#10;
|
||||
EngineProcess.Input.Write(extraCommands[1], length(extraCommands));
|
||||
extraCommands:='level 60 0.5 3'+#13+#10;
|
||||
EngineProcess.Input.Write(extraCommands[1], length(extraCommands));
|
||||
outputText:='';
|
||||
|
||||
end;
|
||||
|
||||
procedure TwinboardConn.stopEngine;
|
||||
procedure TWinboardConn.stopEngine(freeProcess : boolean);
|
||||
begin
|
||||
if engineProcess<>nil then
|
||||
if engineProcess.Running then
|
||||
begin
|
||||
engineProcess.Input.WriteAnsiString('quit'+#13+#10);
|
||||
engineProcess.Terminate(0);
|
||||
end;
|
||||
if freeProcess then
|
||||
begin
|
||||
engineProcess.free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TwinboardConn.tellMove(move : String);
|
||||
procedure TWinboardConn.tellMove(move : String);
|
||||
begin
|
||||
move := move+#13+#10;
|
||||
EngineProcess.Input.Write(move[1], length(move));
|
||||
end;
|
||||
|
||||
//return the engine move.
|
||||
function TwinboardConn.engineMove : moveInCoord;
|
||||
function TWinboardConn.engineMove : moveInCoord;
|
||||
var move : String;
|
||||
points: moveInCoord;
|
||||
begin
|
||||
sleep(500);
|
||||
repeat
|
||||
Application.processMessages;
|
||||
engineRegExpression.Expression:='(?m)^(My move|my move|move)( is|)(: | : | )';
|
||||
readFromPipe;
|
||||
until pos(engineMoveCommand[engineMoveComIndex][2],outputText)>0;
|
||||
if engineRegExpression.Exec(outputText) then
|
||||
begin
|
||||
move := extractMove;
|
||||
points := stringToCoord(move);
|
||||
result:=points;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TwinboardConn.coordToString(AFrom, ATo : TPoint; pieceFrom, pieceTo : TChessTile) : String;
|
||||
function TWinboardConn.coordToString(AFrom, ATo : TPoint; pieceFrom, pieceTo : TChessTile) : String;
|
||||
var
|
||||
move : String;
|
||||
begin
|
||||
//still need to verify castle an en passant
|
||||
|
||||
move:= move + numberToLetter(AFrom.X);
|
||||
move:= move + intToStr(AFrom.Y);
|
||||
@ -132,7 +119,7 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
function TwinboardConn.numberToLetter(n : integer) : String;
|
||||
function TWinboardConn.numberToLetter(n : integer) : String;
|
||||
begin
|
||||
case n of
|
||||
1 : result := 'a';
|
||||
@ -146,10 +133,9 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TwinboardConn.stringToCoord(moveStr : String) : moveInCoord;
|
||||
function TWinboardConn.stringToCoord(moveStr : String) : moveInCoord;
|
||||
var move : moveInCoord;
|
||||
begin
|
||||
//need to verify castle here
|
||||
if moveStr[1] in ['P','R','N','B','Q','K'] then
|
||||
Delete(moveStr,1,1);
|
||||
move[1].X:=letterToNumber(moveStr[1]);
|
||||
@ -163,7 +149,7 @@ begin
|
||||
result:=move;
|
||||
end;
|
||||
//Transform collum letter to number
|
||||
function TwinboardConn.letterToNumber(num:String) : Integer;
|
||||
function TWinboardConn.letterToNumber(num:String) : Integer;
|
||||
begin
|
||||
case num[1] of
|
||||
'a' : result:=1;
|
||||
@ -178,8 +164,9 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
//read all the output text from the TProcess pipe
|
||||
procedure TwinboardConn.readFromPipe;
|
||||
//read all the output text from the TProcess pipe (basically copy/pasted from the
|
||||
//TProcess example)
|
||||
procedure TWinboardConn.readFromPipe;
|
||||
var
|
||||
NoMoreOutput: boolean;
|
||||
|
||||
@ -211,22 +198,27 @@ begin
|
||||
until noMoreOutput;
|
||||
end;
|
||||
|
||||
function TwinboardConn.extractMove : string;
|
||||
var move : String;
|
||||
i,p : integer;
|
||||
function TWinboardConn.extractMove : string;
|
||||
var
|
||||
initialPos : integer;
|
||||
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
|
||||
p := p+length(engineMoveCommand[engineMoveComIndex][2]);
|
||||
while outputText[p]<>#10 do
|
||||
begin
|
||||
move:= move+outputText[p];
|
||||
inc(p);
|
||||
initialPos := pos(engineRegExpression.Match[0],outputText);
|
||||
Delete(outputText,initialPos,Length(engineRegExpression.Match[0]));
|
||||
end;
|
||||
end;
|
||||
result:=move;
|
||||
|
||||
result:= outputText;
|
||||
|
||||
outputText:='';
|
||||
end;
|
||||
|
||||
|
Reference in New Issue
Block a user