On-line: guests 0. In total there are: 0 [information..]
AuthorTopic
bankuss
Black King


Guest
Joined: 01.01.70
Rank: 0

Awards: За плодотворную работу над оптимизацией и доводкой до ума Ипполитов!!!
link post  Posted: 23.03.06 14:15. Post subject: Протокол UCI-1 команды от GUI движку


UCI (универсальный шахматный интерфейс)
Описание UCI:
* Движок – exe файл, консольное или обычное приложение windows.
* Связь осуществляется через стандартный ввод/вывод простыми текстовыми командами.
* Загруженный движок должен ждать команду от GUI - "isready" или команду "setoption", чтобы инициализировать свои параметры. Процесс начальной загрузки должен быть максимально быстр.
* Движок должен уметь обрабатывать входящие данные от stdin, даже при размышлении.
* Все команды, которые получает движок, заканчиваются '\n '. Также все команды, которые GUI получает от движка, должны заканчиваться '\n '.
* Движок не должен начинать играть или рассчитывать без команды “go”.
* Движок не должен совершать ход на внутренней шахматной доске без запроса от GUI, т.е. движок не должен выполнять лучший ход после поиска.
* Прежде, чем движок начнет поиск в позиции, он должен принять текущую позицию.
* Все дебютные библиотеки сделаны через GUI,
Но имеется опция для движка для использования собственной ДБ (опция "OwnBook", см. ниже)

Формат хода:
Формат хода использует длинную алгебраическою нотацию:
Примеры: e2e4, e7e5, e1g1 (короткая рокировка), e7e8q (превращение пешки)

Команды от GUI к движку:
* UCI
Сообщить движку об использовании протокола uci.
После команды “uci” движок посылает команды о себе и настройках.
Т.е. передает команду "option" с параметрами.
После этого движок должен послать "uciok".
Если uciok не послан в пределах некоторого периода времени, то движок будет выгружен!
* DEBUG [on | off]
Переключить способ отладки движка вкл. и выкл.
По умолчанию этот параметр должен быть выключенным!
В этом режиме движок может посылать дополнительную информации оболочке.
* ISREADY
Команда используется для синхронизации движка и оболочки.
После ее посылки оболочка ждет готовность движка.
Этой команде нужно всегда отвечать "readyok".
* SETIPTION NAME <id> [value <x>]
Передается движку, когда пользователь хочет изменить внутренние настройки движка. Пример:
setoption name Hash value 12
setoption name NalimovCache value 4
setoption name OwnBook value true
setoption name NalimovPath value C:\Tbase
setoption name Ponder value false
setoption name book_during_analysis value true
setoption name book_learning value false
* POSITION [fen <fenstring> | startpos ] moves <move1> .... <movei>
Передать позицию.
* GO
Дать команду на вычисление текущей позиции.
Имеется множество команд, которые могут следовать за этой командой.
* wtime <x>
Белые x мсек на часах
* btime <x>
Черные x мсек на часах
* winc <x>
приращение на ход в мсек, если x> 0
* binc <x>
приращение на ход в мсек, если x> 0
* movestogo <x>
Имеются ходы x к следующему контролю,
Послано если x> 0.
* depth <x>
Искать на x глубину.
* nodes <x>
Искать x узлов.
* mate <x>
Искать мат.
* movetime <x>
Искать точно x мсек.
* infinite
Поиск до команды "stop". Не выходите из поиска без выключения этого режима!
* STOP
Остановка поиска.
Не забывайте команду "bestmove" по окончании поиска!
* PONDERHIT
Пользователь делает ожидаемый ход.
* QUIT
Выйти из программы.

Вольный перевод by bankuss 2004

Say thanks!: 0 
Profile Reply
Replys - 29 , page: 1 2 All [new only]


NS_Serg



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 04.04.06 08:01. Post subject: Re:


Про ponder вроде не до конца перевёл...

Say thanks!: 0 
Profile Reply
bankuss
Black King


Guest
Joined: 01.01.70
Rank: 0

Awards: За плодотворную работу над оптимизацией и доводкой до ума Ипполитов!!!
link post  Posted: 04.04.06 11:41. Post subject: Re:


NS_Serg
может... я кратко и самое нужное :)

Say thanks!: 0 
Profile Reply
Freeman



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 06.04.06 16:08. Post subject: Re:



 quote:
* Движок должен уметь обрабатывать входящие данные от stdin, даже при размышлении.


Как замутить такое на делфи?

Say thanks!: 0 
Profile Reply
bankuss
Black King


Guest
Joined: 01.01.70
Rank: 0

Awards: За плодотворную работу над оптимизацией и доводкой до ума Ипполитов!!!
link post  Posted: 06.04.06 18:57. Post subject: Re:


Freeman
при игре движков это не особо важно. скорее всего здесь имеется ввиду обработка команды STOP (или FORCE в xboard), чтоб движок прервал вычисления и выдал ход до которого додумался. ну и QUIT естественно...

Say thanks!: 0 
Profile Reply
NS_Serg



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 06.04.06 18:58. Post subject: Re:


Раз в 10000 nodes, если прошло определенное время с предыдущей проверки (например 10мс) вызываешь функцию PeekNamedPipe, и если что-то есть, и это что-то - stop - то аварийно выходишь из перебора.
В принципе - для турнира это не нужно. Если poner-а нет.

Say thanks!: 0 
Profile Reply
NS_Serg



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 06.04.06 18:59. Post subject: Re:


bankuss пишет:

 quote:
при игре движков это не особо важно. скорее всего здесь имеется ввиду обработка команды STOP (или FORCE в xboard), чтоб движок прервал вычисления и выдал ход до которого додумался. ну и QUIT естественно...


команды маленькими буквами ;-)
А тут мной была написана глупость ;-)))
Кроме stop-a ничего больше не надо, при ponder всё равно сначала stop шлет.
У меня самого ponder не сделан - для чемпионата СНГ он не нужен. Однопроцессорные машины будут. Без пондера будем играть. ;-))

Say thanks!: 0 
Profile Reply
Freeman



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 06.04.06 21:27. Post subject: Re:


я так делал.

procedure LPrint(msgs:string);
var x1:Pchar;
len:Cardinal;
begin
assignfile(f,'iolog.txt');
Append(f);
writeln(f,'--> ',msgs);
closefile(f);
len:=length(msgs);
x1:=pchar(msgs + #10);
_lwrite(gHandleout,x1,len+1);
end;

function Input:string;
var res:string;
begin
Input:='';
readln(res);
if res='' then exit;
assignfile(f,'iolog.txt');
Append(f);
writeln(f,'<-- ',res);
closefile(f);
Input:=res;
end;

где и с какими параметрами юзать PeekNamedPipe ?

Say thanks!: 0 
Profile Reply
NS_Serg



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 06.04.06 21:32. Post subject: Re:


var StdInPipeWrite,StdOutPipeRead:THandle;
StdInPipeWrite:= GetStdHandle(STD_Output_HANDLE);
StdOutPipeRead:=GetStdHandle(STD_INPUT_HANDLE);
Это инициализация, один раз при запуске, остальные две процедуры в безобразном виде, даже стыдно выкладывать ;-))) (кривой текст) но это же не книга ;-))
function ReadNS:AnsiString;
Var
chBuf: Char; BufSize,i: DWORD; res:boolean; s:AnsiString;
begin
chbuf:=chr(0);
BufSize:=0;
Res:=PeekNamedPipe(StdOutPipeRead, nil, 0, nil, @BufSize, nil);
Res:=Res and (BufSize > 0);
If Res Then
// Это нормально переписать надо - очень торопился, хотел посмотреть, как играет.
while (chbuf>chr(13))or(chbuf=chr(0)) do
begin
s:='';
for I := 1 to Bufsize do
Begin
chBuf:=chr(0);
ReadFile(StdOutPipeRead, chBuf, 1, BufSize, Nil);
if chBuf>chr(13) then s:=s+chBuf;
if chBuf=Chr(10) then break;
end;
Result:=s;
end
Else
Result:='';
end;
procedure WriteNS(Data: AnsiString);
Var
chBuf: PChar; BufSize,i: DWORD;
begin

chBuf:=PChar(Data+Chr($0D)+Chr($0A));
BufSize:=Length(chBuf);
WriteFile(StdInPipeWrite, chBuf^, BufSize, i, Nil);
end;
// по MSDN-у писал ;-)) ни одного примера не нашел по форумам... Заодно написал для оболочки - для наоборот - ловить движок, и перехватывать его ввод/вывод - интересно?

Say thanks!: 0 
Profile Reply
Freeman



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 06.04.06 22:05. Post subject: Re:


я из http://www.tim-mann.org/winboard/delphi.txt взял (из справки к винборду).
Кинь для оболочки еще =)) может че-нить потом сделаю

Say thanks!: 0 
Profile Reply
NS_Serg



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 06.04.06 22:16. Post subject: Re:


Freeman пишет:

 quote:
я из http://www.tim-mann.org/winboard/delphi.txt взял (из справки к винборду).
Кинь для оболочки еще =)) может че-нить потом сделаю


Там я как-то наткнулся - лажа конечно.
Там поток дополнительный организуется, а у меня всё на одном потоке.
Для оболочки:
var
sa: TSecurityAttributes;
pi: TProcessInformation;
si: TStartupInfo;
StdOutPipeRead, StdOutPipeWrite,
StdInPipeRead, StdInPipeWrite : THandle;

procedure TForm1.Button1Click(Sender: TObject);
begin
sa.nLength := sizeof(sa);
sa.bInheritHandle := TRUE;
sa.lpSecurityDescriptor := nil;

CreatePipe(StdOutPipeRead,StdOutPipeWrite,@SA,0);
CreatePipe(StdInPipeRead,StdInPipeWrite,@SA,0);

ZeroMemory(@SI, SizeOf(SI));
SI.cb := sizeof(SI);
SI.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
SI.wShowWindow := SW_HIDE;
SI.hStdInput := StdInPipeRead;
SI.hStdOutput := StdOutPipeWrite;

CreateProcess(nil,
'E:\crafty_1917_DC\crafty_1917_DC\Crafty-1917.exe',
nil,
nil,
TRUE,
0,
nil,
nil,
si,
pi);
а дальше - как я привел выше, только Handle полученные используешь.


Say thanks!: 0 
Profile Reply
NS_Serg



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 06.04.06 22:29. Post subject: Re:


Для движка делаю в цикле -
while true do
begin
sleep(1);
s:=readNS();
if s='uci' then
begin
writeNS('id name Anechka 0.01');
writeNS('id author Sergei V. Nefedov');
writeNS('uciok');
end
else
if s='isready' then
begin
writeNS('readyok');
end
else
if s='stop' then writeNS('bestmove 0000')
else
if s='quit' then begin
readNS();
CloseHandle(StdOutPipeRead);
CloseHandle(StdInPipeWrite);
exit;
....
// на stop такой странный вывод
// потому что ничего в это время не считаем...
// readNS() - если движек нам ничего не посылал - выдает пустую строку
// не задерживая выполнение программы

В момент перебора - я уже описывал выше...

Say thanks!: 0 
Profile Reply
bankuss
Black King


Guest
Joined: 01.01.70
Rank: 0

Awards: За плодотворную работу над оптимизацией и доводкой до ума Ипполитов!!!
link post  Posted: 07.04.06 06:50. Post subject: Re:


NS_Serg
Ты через winAPI делаешь, я тоже так делал. А когда под dotNET работал, то через класс system.console реализовал. Очень даже удобно вышло. Кстати тоже в одном потоке все организовал, неохота было с tread возится :)
Единственное отличие парсинга команд от твоего - я через select case делал, и только 3-4 команды через if.

Say thanks!: 0 
Profile Reply
NS_Serg



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 07.04.06 15:19. Post subject: Re:


Два потока всяко хуже, так как в турнирах может возникнуть подозрение, что программа просто откровенно жулит... Особенно при включенном Ponder.

Say thanks!: 0 
Profile Reply
boriz



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 18.05.06 19:55. Post subject: Re:


А ссылки есть какие-нибудь на спецификации или популярные описания UCI в более подробном варианте? Вы, bankuss, где брали английскую версию?

Say thanks!: 0 
Profile Reply
NS_Serg



Guest
Joined: 01.01.70
Rank: 0
link post  Posted: 19.05.06 00:47. Post subject: Re:

Say thanks!: 0 
Profile Reply
Igrok88



Guest
Joined: 01.01.70
link post  Posted: 31.03.07 07:28. Post subject: Re:


Эксперты очень вас прошу приписать uci код к следующему работающему коду:

/*
FirstChess - Freeware, by Pham Hong Nguyen
Version: beta
*/
/*
* BASIC PARTS: *
* Some definitions *
* Board representation and main varians *
* Move generator *
* Evaluation for current position *
* Make and Take back a move, IsInCheck *
* Search function - a typical alphabeta *
* Utility *
* Main program *
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
/*
****************************************************************************
* Some definitions *
****************************************************************************
*/
#define PAWN 0
#define KNIGHT 1
#define BISHOP 2
#define ROOK 3
#define QUEEN 4
#define KING 5
#define EMPTY 6
#define WHITE 0
#define BLACK 1

#define VALUE_PAWN 100
#define VALUE_KNIGHT 300
#define VALUE_BISHOP 300
#define VALUE_ROOK 500
#define VALUE_QUEEN 900
#define VALUE_KING 10000

#define MATE 10000 /* equal value of King, losing King==mate */

#define COL(pos) ((pos)&7)
#define ROW(pos) (((unsigned)pos)>>3)
/*
****************************************************************************
* Board representation and main varians *
****************************************************************************
*/
/* Board representation */
int piece[64] = {
ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK,
PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN,
ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK
};

int color[64] = {
BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK,
BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE,
WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE
};

int side; /* side to move, value = BLACK or WHITE */

/* For move generation */
#define MOVE_TYPE_NONE 0
#define MOVE_TYPE_NORMAL 1
#define MOVE_TYPE_CASTLE 2
#define MOVE_TYPE_ENPASANT 3
#define MOVE_TYPE_PROMOTION_TO_QUEEN 4
#define MOVE_TYPE_PROMOTION_TO_ROOK 5
#define MOVE_TYPE_PROMOTION_TO_BISHOP 6
#define MOVE_TYPE_PROMOTION_TO_KNIGHT 7


typedef struct tag_MOVE {
int from,
dest,
type;
} MOVE;
/* For storing all moves of game */
typedef struct tag_HIST {
MOVE m;
int cap;
} HIST;

HIST hist[6000]; /* Game length < 6000 */

int hdp; /* Current move order */

/* For searching */
int nodes; /* Count all visited nodes when searching */
int ply; /* ply of search */

/*
****************************************************************************
* Move generator *
* Lack: no enpassant, no castle *
****************************************************************************
*/
void Gen_Push(int from, int dest, int type, MOVE * pBuf, int *pMCount)
{
MOVE move;
move.from = from;
move.dest = dest;
move.type = type;
pBuf[*pMCount] = move;
*pMCount = *pMCount + 1;
}

void Gen_PushNormal(int from, int dest, MOVE * pBuf, int *pMCount)
{
Gen_Push(from, dest, MOVE_TYPE_NORMAL, pBuf, pMCount);
}

/* Pawn can promote */
void Gen_PushPawn(int from, int dest, MOVE * pBuf, int *pMCount)
{
if (dest > 7 && dest < 56)
Gen_Push(from, dest, MOVE_TYPE_NORMAL, pBuf, pMCount);
else {
Gen_Push(from, dest, MOVE_TYPE_PROMOTION_TO_QUEEN, pBuf, pMCount);
Gen_Push(from, dest, MOVE_TYPE_PROMOTION_TO_ROOK, pBuf, pMCount);
Gen_Push(from, dest, MOVE_TYPE_PROMOTION_TO_BISHOP, pBuf, pMCount);
Gen_Push(from, dest, MOVE_TYPE_PROMOTION_TO_KNIGHT, pBuf, pMCount);
}
}

/* Gen all moves of current_side to move and push them to pBuf, return number of moves */
int Gen(int current_side, MOVE * pBuf)
{
int i,
k,
y,
row,
col,
movecount;
movecount = 0;

for (i = 0; i < 64; i++) /* Scan all board */
if (color[i] == current_side) {
switch (piece[i]) {
case PAWN:
col = COL(i);
row = ROW(i);
if (current_side == BLACK) {
if (color[i + 8] == EMPTY)
Gen_PushPawn(i, i + 8, pBuf, &movecount);
if (row == 1 && color[i + 8] == EMPTY && color[i + 16] == EMPTY)
Gen_PushNormal(i, i + 16, pBuf, &movecount);
if (col && color[i + 7] == WHITE)
Gen_PushNormal(i, i + 7, pBuf, &movecount);
if (col < 7 && color[i + 9] == WHITE)
Gen_PushNormal(i, i + 9, pBuf, &movecount);
} else {
if (color[i - 8] == EMPTY)
Gen_PushPawn(i, i - 8, pBuf, &movecount);
if (row == 6 && color[i - 8] == EMPTY && color[i - 16] == EMPTY)
Gen_PushNormal(i, i - 16, pBuf, &movecount);
if (col && color[i - 9] == BLACK)
Gen_PushNormal(i, i - 9, pBuf, &movecount);
if (col < 7 && color[i - 7] == BLACK)
Gen_PushNormal(i, i - 7, pBuf, &movecount);
}
break;

case QUEEN: /* == BISHOP+ROOK */
case BISHOP:
for (y = i - 9; y >= 0 && COL(y) != 7; y -= 9) { /* go left up */
if (color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
if (color[y] != EMPTY)
break;

}
for (y = i - 7; y >= 0 && COL(y) != 0; y -= 7) { /* go right up */
if (color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
if (color[y] != EMPTY)
break;

}
for (y = i + 9; y < 64 && COL(y) != 0; y += 9) { /* go right down */
if (color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
if (color[y] != EMPTY)
break;

}
for (y = i + 7; y < 64 && COL(y) != 7; y += 7) { /* go right down */
if (color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
if (color[y] != EMPTY)
break;

}
if (piece[i] == BISHOP)
break;

/* FALL THROUGH FOR QUEEN {I meant to do that!} ;-) */
case ROOK:
col = COL(i);
for (k = i - col, y = i - 1; y >= k; y--) { /* go left */
if (color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
if (color[y] != EMPTY)
break;

}
for (k = i - col + 7, y = i + 1; y <= k; y++) { /* go right */
if (color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
if (color[y] != EMPTY)
break;

}
for (y = i - 8; y >= 0; y -= 8) { /* go up */
if (color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
if (color[y] != EMPTY)
break;

}
for (y = i + 8; y < 64; y += 8) { /* go down */
if (color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
if (color[y] != EMPTY)
break;

}
break;

case KNIGHT:
col = COL(i);
y = i - 6;
if (y >= 0 && col < 6 && color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
y = i - 10;
if (y >= 0 && col > 1 && color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
y = i - 15;
if (y >= 0 && col < 7 && color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
y = i - 17;
if (y >= 0 && col > 0 && color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
y = i + 6;
if (y < 64 && col > 1 && color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
y = i + 10;
if (y < 64 && col < 6 && color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
y = i + 15;
if (y < 64 && col > 0 && color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
y = i + 17;
if (y < 64 && col < 7 && color[y] != current_side)
Gen_PushNormal(i, y, pBuf, &movecount);
break;

case KING:
col = COL(i);
if (col && color[i - 1] != current_side)
Gen_PushNormal(i, i - 1, pBuf, &movecount); /* left */
if (col < 7 && color[i + 1] != current_side)
Gen_PushNormal(i, i + 1, pBuf, &movecount); /* right */
if (i > 7 && color[i - 8] != current_side)
Gen_PushNormal(i, i - 8, pBuf, &movecount); /* up */
if (i < 56 && color[i + 8] != current_side)
Gen_PushNormal(i, i + 8, pBuf, &movecount); /* down */
if (col && i > 7 && color[i - 9] != current_side)
Gen_PushNormal(i, i - 9, pBuf, &movecount); /* left up */
if (col < 7 && i > 7 && color[i - 7] != current_side)
Gen_PushNormal(i, i - 7, pBuf, &movecount); /* right up */
if (col && i < 56 && color[i + 7] != current_side)
Gen_PushNormal(i, i + 7, pBuf, &movecount); /* left down */
if (col < 7 && i < 56 && color[i + 9] != current_side)
Gen_PushNormal(i, i + 9, pBuf, &movecount); /* right down */
break;
default:
puts("piece type unknown");
assert(false);
}
}
return movecount;
}

/*
****************************************************************************
* Evaluation for current position - main "brain" function *
* Lack: almost no knowlegde *
****************************************************************************
*/
int Eval()
{
int value_piece[6] = {VALUE_PAWN, VALUE_KNIGHT, VALUE_BISHOP, VALUE_ROOK, VALUE_QUEEN, VALUE_KING};
int i,
score = 0;
for (i = 0; i < 64; i++) {
if (color[i] == WHITE)
score += value_piece[piece[i]];
else if (color[i] == BLACK)
score -= value_piece[piece[i]];
}
if (side == WHITE)
return -score;
return score;
}

/*
****************************************************************************
* Make and Take back a move, IsInCheck *
****************************************************************************
*/
/* Check and return 1 if side is in check */
int IsInCheck(int current_side)
{
int k,
h,
y,
row,
col,
xside;
xside = (WHITE + BLACK) - current_side; /* opposite current_side, who may be checking */
/* Find King */
for (k = 0; k < 64; k++)
if (piece[k] == KING && color[k] == current_side)
break;

row = ROW(k), col = COL(k);
/* Check attacking of Knight */
if (col > 0 && row > 1 && color[k - 17] == xside && piece[k - 17] == KNIGHT)
return 1;
if (col < 7 && row > 1 && color[k - 15] == xside && piece[k - 15] == KNIGHT)
return 1;
if (col > 1 && row > 0 && color[k - 10] == xside && piece[k - 10] == KNIGHT)
return 1;
if (col < 6 && row > 0 && color[k - 6] == xside && piece[k - 6] == KNIGHT)
return 1;
if (col > 1 && row < 7 && color[k + 6] == xside && piece[k + 6] == KNIGHT)
return 1;
if (col < 6 && row < 7 && color[k + 10] == xside && piece[k + 10] == KNIGHT)
return 1;
if (col > 0 && row < 6 && color[k + 15] == xside && piece[k + 15] == KNIGHT)
return 1;
if (col < 7 && row < 6 && color[k + 17] == xside && piece[k + 17] == KNIGHT)
return 1;
/* Check horizontal and vertical lines for attacking of Queen, Rook, King */
/* go down */
y = k + 8;
if (y < 64) {
if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN || piece[y] == ROOK))
return 1;
if (piece[y] == EMPTY)
for (y += 8; y < 64; y += 8) {
if (color[y] == xside && (piece[y] == QUEEN || piece[y] == ROOK))
return 1;
if (piece[y] != EMPTY)
break;

}
}
/* go left */
y = k - 1;
h = k - col;
if (y >= h) {
if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN || piece[y] == ROOK))
return 1;
if (piece[y] == EMPTY)
for (y--; y >= h; y--) {
if (color[y] == xside && (piece[y] == QUEEN || piece[y] == ROOK))
return 1;
if (piece[y] != EMPTY)
break;
}
}
/* go right */
y = k + 1;
h = k - col + 7;
if (y <= h) {
if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN || piece[y] == ROOK))
return 1;
if (piece[y] == EMPTY)
for (y++; y <= h; y++) {
if (color[y] == xside && (piece[y] == QUEEN || piece[y] == ROOK))
return 1;
if (piece[y] != EMPTY)
break;
}
}
/* go up */
y = k - 8;
if (y >= 0) {
if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN || piece[y] == ROOK))
return 1;
if (piece[y] == EMPTY)
for (y -= 8; y >= 0; y -= 8) {
if (color[y] == xside && (piece[y] == QUEEN || piece[y] == ROOK))
return 1;
if (piece[y] != EMPTY)
break;
}
}
/* Check diagonal lines for attacking of Queen, Bishop, King, Pawn */
/* go right down */
y = k + 9;
if (y < 64 && COL(y) != 0) {
if (color[y] == xside) {
if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
return 1;
if (current_side == BLACK && piece[y] == PAWN)
return 1;
}
if (piece[y] == EMPTY)
for (y += 9; y < 64 && COL(y) != 0; y += 9) {
if (color[y] == xside && (piece[y] == QUEEN || piece[y] == BISHOP))
return 1;
if (piece[y] != EMPTY)
break;
}
}
/* go left down */
y = k + 7;
if (y < 64 && COL(y) != 7) {
if (color[y] == xside) {
if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
return 1;
if (current_side == BLACK && piece[y] == PAWN)
return 1;
}
if (piece[y] == EMPTY)
for (y += 7; y < 64 && COL(y) != 7; y += 7) {
if (color[y] == xside && (piece[y] == QUEEN || piece[y] == BISHOP))
return 1;
if (piece[y] != EMPTY)
break;

}
}
/* go left up */
y = k - 9;
if (y >= 0 && COL(y) != 7) {
if (color[y] == xside) {
if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
return 1;
if (current_side == WHITE && piece[y] == PAWN)
return 1;
}
if (piece[y] == EMPTY)
for (y -= 9; y >= 0 && COL(y) != 7; y -= 9) {
if (color[y] == xside && (piece[y] == QUEEN || piece[y] == BISHOP))
return 1;
if (piece[y] != EMPTY)
break;

}
}
/* go right up */
y = k - 7;
if (y >= 0 && COL(y) != 0) {
if (color[y] == xside) {
if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
return 1;
if (current_side == WHITE && piece[y] == PAWN)
return 1;
}
if (piece[y] == EMPTY)
for (y -= 7; y >= 0 && COL(y) != 0; y -= 7) {
if (color[y] == xside && (piece[y] == QUEEN || piece[y] == BISHOP))
return 1;
if (piece[y] != EMPTY)
break;
}
}
return 0;
}

int MakeMove(MOVE m)
{
int r;
hist[hdp].m = m;
hist[hdp].cap = piece[m.dest];
piece[m.dest] = piece[m.from];
piece[m.from] = EMPTY;
color[m.dest] = color[m.from];
color[m.from] = EMPTY;
if (m.type >= MOVE_TYPE_PROMOTION_TO_QUEEN) { /* Promotion */
switch (m.type) {
case MOVE_TYPE_PROMOTION_TO_QUEEN:
piece[m.dest] = QUEEN;
break;

case MOVE_TYPE_PROMOTION_TO_ROOK:
piece[m.dest] = ROOK;
break;

case MOVE_TYPE_PROMOTION_TO_BISHOP:
piece[m.dest] = BISHOP;
break;

case MOVE_TYPE_PROMOTION_TO_KNIGHT:
piece[m.dest] = KNIGHT;
break;

default:
puts("impossible to get here...");
assert(false);
}
}
ply++;
hdp++;
r = !IsInCheck(side);
side = (WHITE + BLACK) - side; /* After making move, give turn to
* opponent */
return r;
}

void TakeBack() /* undo what MakeMove did */
{
side = (WHITE + BLACK) - side;
hdp--;
ply--;
piece[hist[hdp].m.from] = piece[hist[hdp].m.dest];
piece[hist[hdp].m.dest] = hist[hdp].cap;
color[hist[hdp].m.from] = side;
if (hist[hdp].cap != EMPTY)
color[hist[hdp].m.dest] = (WHITE + BLACK) - side;
else
color[hist[hdp].m.dest] = EMPTY;
if (hist[hdp].m.type >= MOVE_TYPE_PROMOTION_TO_QUEEN) /* Promotion */
piece[hist[hdp].m.from] = PAWN;
}

/*
****************************************************************************
* Search function - a typical alphabeta, main search function *
* Lack: no any technique for move ordering *
****************************************************************************
*/

int Search(int alpha, int beta, int depth, MOVE * pBestMove)
{
int i,
value,
havemove,
movecnt;
MOVE moveBuf[200],
tmpMove;

nodes++; /* visiting a node, count it */
havemove = 0;
pBestMove->type = MOVE_TYPE_NONE;
movecnt = Gen(side, moveBuf); /* generate all moves for current position */
/* loop through the moves */
for (i = 0; i < movecnt; ++i) {
if (!MakeMove(moveBuf[i])) {
TakeBack();
continue;
}
havemove = 1;
if (depth - 1 > 0) /* If depth is still, continue to search deeper */
value = -Search(-beta, -alpha, depth - 1, &tmpMove);
else /* If no depth left (leaf node), go to evalute that position */
value = Eval();
TakeBack();
if (value > alpha) {
/* This move is so good and caused a cutoff */
if (value >= beta)
return beta;
alpha = value;
*pBestMove = moveBuf[i]; /* so far, current move is the best reaction
* for current position */
}
}
if (!havemove) { /* If no legal moves, that is checkmate or
* stalemate */
if (IsInCheck(side))
return -MATE + ply; /* add ply to find the longest path to lose or shortest path to win */
else
return 0;
}
return alpha;
}

MOVE ComputerThink(int max_depth)
{
MOVE m;
int score;
/* reset some values before searching */
ply = 0;
nodes = 0;
/* search now */
score = Search(-MATE, MATE, max_depth, &m);
/* after searching, print results */
printf("Search result: move = %c%d%c%d; nodes = %d, score = %d\n",
'a' + COL(m.from),
8 - ROW(m.from),
'a' + COL(m.dest),
8 - ROW(m.dest),
nodes,
score
);
return m;
}

/*
****************************************************************************
* Utilities *
****************************************************************************
*/
void PrintBoard()
{
char pieceName[] = "PNBRQKpnbrqk";
int i;
for (i = 0; i < 64; i++) {
if ((i & 7) == 0) {
printf(" +---+---+---+---+---+---+---+---+\n");
if (i <= 56) {
printf(" %d |", 8 - (((unsigned)i) >> 3));
}
}
if (piece[i] == EMPTY)
printf(" |");
else {
printf(" %c |", pieceName[piece[i] + (color[i] == WHITE ? 0 : 6)]);
}
if ((i & 7) == 7)
printf("\n");
}
printf(" +---+---+---+---+---+---+---+---+\n a b c d e f g h\n");
}

/*
****************************************************************************
* Main program *
****************************************************************************
*/
void main()
{
char s[256];
int from,
dest,
i;
int computer_side;
int max_depth; /* max depth to search */
MOVE moveBuf[200];
int movecnt;
printf("First Chess, by Pham Hong Nguyen\n");
printf("Help\n d: display board\n MOVE: make a move (e.g. b1c3, a7a8q)\n quit: exit\n\n");
side = WHITE;
computer_side = BLACK; /* Human is white side */
max_depth = 7;
hdp = 0;
for (;;) {
if (side == computer_side) { /* computer's turn */
/* Find out the best move to react the current position */
MOVE bestMove = ComputerThink(max_depth);
MakeMove(bestMove);
continue;
}
/* get user input */
printf("fc> ");
if (scanf("%s", s) == EOF) /* close program */
return;
if (!strcmp(s, "d")) {
PrintBoard();
continue;
}
if (!strcmp(s, "quit")) {
printf("Good bye!\n");
return;
}
/* maybe the user entered a move? */
from = s[0] - 'a';
from += 8 * (8 - (s[1] - '0'));
dest = s[2] - 'a';
dest += 8 * (8 - (s[3] - '0'));
ply = 0;
movecnt = Gen(side, moveBuf);
/* loop through the moves to see if it's legal */
for (i = 0; i < movecnt; i++)
if (moveBuf[i].from == from && moveBuf[i].dest == dest) {
if (piece[from] == PAWN && (dest < 8 || dest > 55)) { /* Promotion move? */
switch (s[4]) {
case 'q':
moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_QUEEN;
break;

case 'r':
moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_ROOK;
break;

case 'b':
moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_BISHOP;
break;

case 'n':
moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_KNIGHT;
break;

default:

puts("promoting to a McGuffin..., I'll give you a queen");
moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_QUEEN;
}
}
if (!MakeMove(moveBuf[i])) {
TakeBack();
printf("Illegal move.\n");
}
break;

}
}
}

Это поможет мне понять как uci работает в условиях обдумывания хода.

Say thanks!: 0 
Reply
bankuss
Black King


Post №: 382
Joined: 26.02.06
Rank: 3

Awards: За плодотворную работу над оптимизацией и доводкой до ума Ипполитов!!!
link post  Posted: 31.03.07 07:35. Post subject: Re:


при обдумывании хода надо постоянно проверять входной поток, если появилась команда "stop" или "quit" или пондер, то прервать вычисления.
я в своих первых версиях этого не делал - поэтому при остановке движок продолжает думать :)
хорошо известную подпрограмму проверки можно взять из кода глаурунга (который взял ее из кода OliThink)
называется bioskey()

Say thanks!: 0 
Profile Reply
Igrok88



Post №: 2
Joined: 29.04.07
Rank: 0
link post  Posted: 29.04.07 11:13. Post subject: Re:


Ребят ну не пожалейте 10 минут, припишите UCI к выложенному коду.

Say thanks!: 0 
Profile Reply
Granite116



Post №: 96
Joined: 15.07.07
Rank: 0
link post  Posted: 06.03.10 20:07. Post subject: Помогите разобраться..


Помогите разобраться. Как вообще происходит подключение движка? Какие команды движок должен понимать?
Начнем сначала:
Нажимаем добавить дживок и выбираем движок. Какая команда в этот момент посылается от GUI к движку? Как я понял GUI посылает сообщение uci. Как должен ответить движок? Движок должен передать свои параметры(здесь опишите подробно какие именно параметры) и вконце движок должен послать сообщение uciok. Дальше GUI отсылает команду isready? Движок должен послать команду readyok.

Вобщем на данный момент задача минимум:
Подключить движок к GUI(чтоб параметры определялись и т.д). Что должен уметь делать движок, чтоб сделать хоть 1ход без анализа(предположим за белых e2e4)? Анализ потом прикручу, на данный момент нужно разобраться как это все работает.

Там где мои рассуждения неверны - поправте. И ответе на вопросы.
Спасибо.

Say thanks!: 0 
Profile Reply
neutrino



Post №: 13
Joined: 23.01.10
Rank: -1
link post  Posted: 07.03.10 11:12. Post subject: Granite116 пишет: П..


Granite116 пишет:

 quote:
Помогите разобраться ... И ответе на вопросы.


На сайте Кветки есть как раз нужное описания протокола на русском. И все сразу будет понятно
если понаблюдать как Арена обращается с движками. В ней есть "Окно отладки движка" по F4

Say thanks!: 0 
Profile Reply
ChessTerminator75



Post №: 59
Joined: 17.09.07
Rank: 1
link post  Posted: 08.03.10 07:24. Post subject: Если я правильно пон..


Если я правильно понял это зарождение нового движка.

Тогда после того как посмотрите живое общение в Арене
еще посмотрите код Fruit_21
http://en.wikipedia.org/wiki/Fruit_(chess_engine)


Там в модуле protocol.cpp отличная реализация UCI протокола.
Начальная реализация этого протокола сложностей не вызывает.

Гораздо сложнее разобраться с fen – строкой.
Посредством этой строки оболочка передает движку позицию
Во Фрукте это реализовано в модуле fen.cpp ( кто бы мог подумать :):))

Фен строка это строка вида
StartFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";

Так что на самом деле вам надо разобраться не столько с UCI сколько с FEN.

Say thanks!: 0 
Profile Reply
Granite116



Post №: 97
Joined: 15.07.07
Rank: 0
link post  Posted: 08.03.10 10:58. Post subject: Жму Движок -> До..


Жму Движок -> Добавить движок UCI -> Выбираю свой движок и оболочка зависает на минуту, потом говорит, Engine: could not load
Ну я решил проверить какую команду движок не может выполнить, приписал код, который сохраняет все команды от GUI к движку и оказывается, что GUI ничего не отправляет движку. Движок сам должен вначале что-то отправить? В чем может быть проблема?

Say thanks!: 0 
Profile Reply
ThinkingALot
VIP


Post №: 212
Joined: 05.09.08
Rank: 4
link post  Posted: 08.03.10 13:20. Post subject: Granite116 пишет: Ж..


Granite116 пишет:

 quote:
Жму Движок -> Добавить движок UCI -> Выбираю свой движок и оболочка зависает на минуту, потом говорит, Engine: could not load
Ну я решил проверить какую команду движок не может выполнить, приписал код, который сохраняет все команды от GUI к движку и оказывается, что GUI ничего не отправляет движку. Движок сам должен вначале что-то отправить? В чем может быть проблема?


При добавлении движка оболочка просто шлет команду uci. Скорее всего движок не поддерживает UCI протокол.

Say thanks!: 0 
Profile Reply
Granite116



Post №: 98
Joined: 15.07.07
Rank: 0
link post  Posted: 08.03.10 14:09. Post subject: Дело в том, что обол..


Дело в том, что оболочка не посылает команду uci(если бы посылала, то в файле эта команда сохранилась).
Да и прикрутил я к движку команду uci
Такого сообщения достаточно после uci?
id name Granite
id author Granite116
uciok


Say thanks!: 0 
Profile Reply
bankuss
Black King


Post №: 2704
Joined: 15.07.07
Rank: 32

Awards: За плодотворную работу над оптимизацией и доводкой до ума Ипполитов!!!
link post  Posted: 08.03.10 19:04. Post subject: может движок не види..


может движок не видит, что ему послали uci ?

Say thanks!: 0 
Profile Reply
ThinkingALot
VIP


Post №: 213
Joined: 05.09.08
Rank: 4
link post  Posted: 09.03.10 19:21. Post subject: Для тестирования раб..


Для тестирования работы ввода/вывода UCI движка не обязательно использовать GUI. Если движок написан корректно, то после запуска exe-шника из explorer'a вылезет консолька. Когда движок добавляется через GUI этого не происходит, так как ввод/вывод перенаправляется с помощью CreatePipe(). Если написать в консольке "uci" движок должен выдать "uciok".

Granite116 пишет:

 quote:
Такого сообщения достаточно после uci?
id name Granite
id author Granite116
uciok


Да.

P.S. Каждая отправляемая оболочке строка должна заканчиваться "\n".

Say thanks!: 0 
Profile Reply
kvetka



Post №: 15
Joined: 13.09.08
Rank: 0
link post  Posted: 12.03.10 02:29. Post subject: Вот здесь лежит мой ..


Вот здесь лежит мой перевод спецификации UCI.

Say thanks!: 0 
Profile Reply
Granite116



Post №: 100
Joined: 15.07.07
Rank: 0
link post  Posted: 12.03.10 08:08. Post subject: ThinkingALot пишет: ..


ThinkingALot пишет:

 quote:
Если движок написан корректно, то после запуска exe-шника из explorer'a вылезет консолька


Конечно вылезет)) И у меня вылазиет
ThinkingALot пишет:

 quote:
Когда движок добавляется через GUI этого не происходит, так как ввод/вывод перенаправляется с помощью CreatePipe()


Хм, а тут у меня тоже консолька вылазиет(правда команды в нее нельзя вводить)
ThinkingALot пишет:

 quote:
Если написать в консольке "uci" движок должен выдать "uciok".


Если запускать через explorer, и ввести uci, то выдает ответ:

 quote:
id name Granite
id author Granite116
uciok




Say thanks!: 0 
Profile Reply
ThinkingALot
VIP


Post №: 214
Joined: 05.09.08
Rank: 4
link post  Posted: 12.03.10 14:58. Post subject: fflush(stdout) после..


fflush(stdout) после fprintf(stdout,"uciok\n") есть?

Say thanks!: 0 
Profile Reply
Replys - 29 , page: 1 2 All [new only]
Тему читают:
- user online
- user offline
All times are GMT  2 Hours. Hits today: 27
You can: smiles yes, images yes, types no, poll no
avatars yes, links on, premoderation on, edit new post no