?? epd.c
字號(hào):
/* GNU Chess 5.0 - epd.c - EPD position definition code
Copyright (c) 1999-2002 Free Software Foundation, Inc.
GNU Chess is based on the two research programs
Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
GNU Chess is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Chess is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Chess; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Contact Info:
bug-gnu-chess@gnu.org
*/
/*
*
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "common.h"
#define EPDCLOSE 1
short ReadEPDFile (const char *file, short op)
/****************************************************************************
*
* Reads in an EPD file. The first call will read the first EPD line,
* the second call will read the 2nd line and so on. To improve
* performance, the file is never closed. Closing of the file happens
* only on 2 conditions: (i) A ReadEPDFile failed because there is no
* more lines to read. (ii) A called to ReadEPDFile to explicitly
* request that the file is closed (op = EPDCLOSE);
* If op == 2, then we work silently.
*
****************************************************************************/
{
static FILE *fp = NULL;
char line[MAXSTR];
/* If first time through, must open file */
if (fp == NULL)
{
fp = fopen (file, "r");
if (fp == NULL)
{
printf ("Error opening file %s\n", file);
return (false);
}
}
/* Is this a close request? */
if (op == EPDCLOSE)
{
fclose (fp);
fp = NULL;
return (false);
}
next_line:
/* Okay, we read in an EPD entry */
fgets (line, MAXSTR-1, fp);
if (!feof(fp))
{
int ret = ParseEPD (line);
/* For now just ignore malformed lines */
if (ret != EPD_SUCCESS) goto next_line;
if (op != 2)
printf ("\n%s : Best move = %s\n", id, solution);
return (true);
}
/* finished, must close file */
else
{
fclose (fp);
fp = NULL;
return (false);
}
}
/*
* Returns EPD_SUCCESS on success, EPD_ERROR on error. We try to be
* quite tough on the format. However, as of yet no legality checking
* is done and the board is not reset on error, this should be done by
* the caller.
*/
int ParseEPD (char *p)
/**************************************************************************
*
* Parses an EPD input line. A few global variables are updated e.g.
* current board, side to move, en passant, castling status, etc.
*
**************************************************************************/
{
int r, c, sq;
char *str_p;
r = 56;
c = 0;
memset (&board, 0, sizeof (board));
while (p && *p != ' ')
{
sq = r + c;
switch (*p)
{
case 'P' : SETBIT (board.b[white][pawn], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[white] += ValueP;
break;
case 'N' : SETBIT (board.b[white][knight], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[white] += ValueN;
break;
case 'B' : SETBIT (board.b[white][bishop], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[white] += ValueB;
break;
case 'R' : SETBIT (board.b[white][rook], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[white] += ValueR;
break;
case 'Q' : SETBIT (board.b[white][queen], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[white] += ValueQ;
break;
case 'K' : SETBIT (board.b[white][king], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
break;
case 'p' : SETBIT (board.b[black][pawn], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[black] += ValueP;
break;
case 'n' : SETBIT (board.b[black][knight], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[black] += ValueN;
break;
case 'b' : SETBIT (board.b[black][bishop], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[black] += ValueB;
break;
case 'r' : SETBIT (board.b[black][rook], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[black] += ValueR;
break;
case 'q' : SETBIT (board.b[black][queen], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
board.material[black] += ValueQ;
break;
case 'k' : SETBIT (board.b[black][king], sq);
SETBIT (board.blockerr90, r90[sq]);
SETBIT (board.blockerr45, r45[sq]);
SETBIT (board.blockerr315, r315[sq]);
break;
case '/' : r -= 8;
c = -1;
break;
default : break;
}
if (isdigit (*p))
c += (*p - '0');
else
c++;
/*
* Special case, a trailing "/" is accepted on the
* end of the board settings.
*/
if (r == -8 && p[1] == ' ')
r = 0;
if (r < 0 || c > 8) return EPD_ERROR;
if (c == 8 && p[1] != '/' && p[1] != ' ') return EPD_ERROR;
p++;
}
board.pmaterial[white] = board.material[white] -
nbits(board.b[white][pawn]) * ValueP;
board.pmaterial[black] = board.material[black] -
nbits(board.b[black][pawn]) * ValueP;
board.king[white] = leadz (board.b[white][king]);
board.king[black] = leadz (board.b[black][king]);
UpdateFriends ();
UpdateCBoard ();
UpdateMvboard ();
/* Get side to move */
if (!++p) return EPD_ERROR;
if (*p == 'w') board.side = white;
else if (*p == 'b') board.side = black;
else return EPD_ERROR;
/* Isn't this one cute? */
if (!++p || *p != ' ' || !++p) return EPD_ERROR;
/* Castling status */
while (p && *p != ' ') {
if (*p == 'K') board.flag |= WKINGCASTLE;
else if (*p == 'Q') board.flag |= WQUEENCASTLE;
else if (*p == 'k') board.flag |= BKINGCASTLE;
else if (*p == 'q') board.flag |= BQUEENCASTLE;
else if (*p == '-') { p++; break; }
else return EPD_ERROR;
p++;
}
if (!p || *p != ' ' || !++p) return EPD_ERROR;
/*
* En passant square, can only be '-' or [a-h][36]
* In fact, one could add more sanity checks here.
*/
if (*p != '-') {
if (!p[1] || *p < 'a' || *p > 'h' ||
!(p[1] == '3' || p[1] == '6')) return EPD_ERROR;
board.ep = (*p - 'a') + (p[1] - '1')*8;
p++;
} else {
board.ep = -1;
}
solution[0] = '\0';
id[0] = '\0';
if (!++p) return EPD_SUCCESS;
/* The opcodes are optional, so we should not generate errors here */
/* Read in best move; "bm" operator */
str_p = strstr(p, "bm");
if (str_p) sscanf (str_p, "bm %63[^;];", solution);
/* Read in the description; "id" operator */
str_p = strstr(p, "id");
if (str_p) sscanf (p, "id %31[^;];", id);
CalcHashKey ();
phase = PHASE;
return EPD_SUCCESS;
}
void LoadEPD (char *p)
/**************************************************************************
*
* This routine reads in the next or the Nth position in the file.
*
**************************************************************************/
{
char file[MAXSTR];
int N = 1;
sscanf (p, "%31s %d ", file, &N);
if (strcmp (file, "next") == 0)
{
ReadEPDFile (file, 0);
}
else
{
ReadEPDFile (file, 1);
while (--N)
{
if (ReadEPDFile (file, 2) == false)
{
printf ("File position exceeded\n");
return;
}
}
ReadEPDFile (file, 0);
}
ShowBoard ();
NewPosition ();
}
void SaveEPD (char *p)
/**************************************************************************
*
* This routine appends the current position in EPD format into a file.
*
**************************************************************************/
{
char file[MAXSTR];
FILE *fp;
int r, c, sq, k;
char c1;
sscanf (p, "%s ", file);
fp = fopen (file, "a");
for (r = A8; r >= A1; r -= 8)
{
k = 0;
for (c = 0; c < 8; c++)
{
sq = r + c;
if (cboard[sq] == empty)
k++;
else
{
if (k)
fprintf (fp, "%1d", k);
k = 0;
c1 = notation[cboard[sq]];
if (BitPosArray[sq] & board.friends[black])
c1 = tolower (c1);
fprintf (fp, "%c", c1);
}
}
if (k)
fprintf (fp, "%1d", k);
if (r > A1)
fprintf (fp, "/");
}
/* Print other stuff */
fprintf (fp, (board.side == white ? " w " : " b "));
if (board.flag & WKINGCASTLE)
fprintf (fp, "K");
if (board.flag & WQUEENCASTLE)
fprintf (fp, "Q");
if (board.flag & BKINGCASTLE)
fprintf (fp, "k");
if (board.flag & BQUEENCASTLE)
fprintf (fp, "q");
if (!(board.flag & (WCASTLE | BCASTLE)))
fprintf (fp, "-");
fprintf (fp, " %s", (board.ep > -1 ? algbr[board.ep] : "-"));
fprintf (fp, " bm 1; id 1;");
fprintf (fp, "\n");
fclose (fp);
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -