/*
Notation program
@(#)notation.c3.9 (C) Henry Thomas Release 3 Dated 12/10/91
*/
/* Programme danalyse de notation echiquienne
Copyright (C) 1990 Henry Thomas
Nom: notation
Auteur: Henry Thomas
Date: 27/11/90
/*
This file is part of NOTATION program.
NOTATION 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 1, or (at your option)
any later version.
NOTATION 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 NOTATION; see the file COPYING.If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.*/
/* data part – */
/* les tableaux suivants sont les tables de transcription de notation
selon les langages
*/
#ifdef __STDC__
#include
#endif
#include
#include
#include
#include chesstype.h
#include notation.h
#include drivers.h
#include lexer.h
extern void close_files();
char * version_string =
@(#)notation.c3.9 (C) Henry Thomas. Release 3 Dated 12/10/91;
static char * keywords[]= {
@startplay , @clearboard , @showboard ,
@whitesmove, @blacksmove, @configwhite, @configblack ,
@default ,
/* these are keywords with arguments */
@title, @subtitle, @score, @language,
/* special keyword */
@special,
/* null and final keyword */
@null
};
int configuring = FALSE ;
int configside = 0 ;
static char * t_language[] = {
french, english, italian, spanish, german, dutch,
czech,hungarian,polish, romanian, FIDE
};
static int in_language = DEFAULT_INPUT_LANGUAGE ;
static int out_language = DEFAULT_OUTPUT_LANGUAGE ;
static char c_language[NBLANGUAGES][7] = {
/* french*/{ @ ,R , D , T , F , C , P },
/* english */{ @ ,K , Q , R , B , N , P },
/* italian */{ @ ,R , D , T , A , C , P },
/* spanish */{ @ ,R , D , T , A , C , P },
/* german*/{ @ ,K , D , T , L , S , B },
/* dutch */{ @ ,K , D , T , L , P , O },
/* czech */{ @ ,K , D , V , S , J , P },
/* hungarian */{ @ ,K , V , B , F , H , G },
/* polish*/{ @ ,K , H , W , G , S , P },
/* romanian*/{ @ ,R , D , T , N , C , P },
/* FIDE*/{ @ ,K , D , T , S , N , P }
/* UNIMPLEMENTED */
/* user_def*//*{ @ ,X , X , X , X , X , X }*/
/* russian not implemented : ASCII russian is an oxymoron */
/* russian *//*{ @ ,K , F , D , C , K , P }*/
};
/* input translation table */
char *in_table;
char *c_roque[] = { O-O , O-O-O , o-o , o-o-o , 0-0 , 0-0-0 };
/* various notations for en passant */
#define N_EP 2
char * c_en_passant[] = { ep , e.p. } ;
/* notation for catch */
char c_prise =x;
/* various comments */
char * c_comments[] = { + , ++ ,
? , ??, !, !!, !?, ?!,
mate, draw };
/* movement tables */
/* move only */
/* white pawn, move */
#define NB_M_PAWN_MOVE_WD 2
static int m_pawn_move_wd [][2] = {
{ 1, 0}, {2, 0}
};
/* black pawn, move */
#define NB_M_PAWN_MOVE_BD 2
static int m_pawn_move_bd [][2] = {
{-1, 0}, {-2, 0}
};
/* TRICK = we have added the catching move at the end of
the non catching ones; so in check_depl, we try first
the non catching one and then the catching one.
So, even if catching (x) is non indicated in the input,
we succeed in guessing the move
*/
/* white pawn, move */
/*#define NB_M_PAWN_WD 2*/
#define NB_M_PAWN_WD 4
static int m_pawn_wd [][2] = {
{ 1, 0}, {2, 0},
/* catch */
{ 1, 1}, { 1,-1}
};
/* white pawn, catch */
#define NB_M_PAWN_WX 2
static int m_pawn_wx [][2] = {
{ 1, 1}, { 1,-1}
};
/* black pawn, move */
/*#define NB_M_PAWN_BD 2*/
#define NB_M_PAWN_BD 4
static int m_pawn_bd [][2] = {
{-1, 0}, {-2, 0},
/* catch */
{-1, 1}, {-1,-1}
};
/* black pawn, catch */
#define NB_M_PAWN_BX 2
static int m_pawn_bx [][2] = {
{-1, 1}, {-1,-1}
};
#define NB_M_KNIGHT8
static int m_knight[][2] = {
{ 2, 1}, { 2,-1}, {-2, 1}, {-2,-1},
{ 1, 2}, { 1,-2}, {-1, 2}, {-1,-2}
};
#define NB_M_BISHOP 28
static int m_bishop[][2] = {
{ 7, 7},{6, 6}, { 5, 5}, { 4, 4}, { 3, 3}, { 2, 2}, { 1, 1},
{ 7,-7}, { 6,-6}, { 5,-5}, { 4,-4}, { 3,-3}, { 2,-2}, { 1,-1},
{-7,-7}, {-6,-6}, {-5,-5}, {-4,-4}, {-3,-3}, {-2,-2}, {-1,-1},
{-7, 7}, {-6, 6}, {-5, 5}, {-4, 4}, {-3, 3}, {-2, 2}, {-1, 1}
};
#define NB_M_ROOK 28
static int m_rook[][2] = {
{ 7, 0}, { 6, 0}, { 5, 0}, { 4, 0}, { 3, 0}, { 2, 0}, { 1, 0},
{-7, 0}, {-6, 0}, {-5, 0}, {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0},
{ 0, 7}, { 0, 6}, { 0, 5}, { 0, 4}, { 0, 3}, { 0, 2}, { 0, 1},
{ 0,-7}, { 0,-6}, { 0,-5}, { 0,-4}, { 0,-3}, { 0,-2}, { 0,-1}
};
#define NB_M_QUEEN 56
static int m_queen[][2] = {
{ 7, 7},{6, 6}, { 5, 5}, { 4, 4}, { 3, 3}, { 2, 2}, { 1, 1},
{ 7,-7}, { 6,-6}, { 5,-5}, { 4,-4}, { 3,-3}, { 2,-2}, { 1,-1},
{-7,-7}, {-6,-6}, {-5,-5}, {-4,-4}, {-3,-3}, {-2,-2}, {-1,-1},
{-7, 7}, {-6, 6}, {-5, 5}, {-4, 4}, {-3, 3}, {-2, 2}, {-1, 1},
{ 7, 0}, { 6, 0}, { 5, 0}, { 4, 0}, { 3, 0}, { 2, 0}, { 1, 0},
{-7, 0}, {-6, 0}, {-5, 0}, {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0},
{ 0, 7}, { 0, 6}, { 0, 5}, { 0, 4}, { 0, 3}, { 0, 2}, { 0, 1},
{ 0,-7}, { 0,-6}, { 0,-5}, { 0,-4}, { 0,-3}, { 0,-2}, { 0,-1}
};
#define NB_M_KING 8
static int m_king[][2] = {
{ 1, 1}, { 1, 0}, { 1,-1},
{-1, 1}, {-1, 0}, {-1,-1},
{ 0, 1}, { 0, -1}
};
/* I/O */
FILE * infile ;
FILE * fhelp;
static char * t_output[] =
{ ascii, postscript, tex, roff, xchess, gnu };
/* stack used for variation */
/* stack element */
typedef struct {
depl * d;
game * b;
/* we dont stack drivers, but only to variables */
int d1,d2; /* iswhiteturn and interrupt */
} stack_elt ;
/* size of the stack
0 = ordinary play
1 = level 1 variation
2 = level 2 variation
3 = level 3 variation
*/
#define VARIATION_MAX 3
/* the stack itself */
static stack_elt stack[VARIATION_MAX];
/* top of the stack */
/* > explicit in dr->variation */
/* – automata definitions */
/* table for syntaxic analysis of move */
#define FINAL10
#define TML FINAL /* terminal state */
#define NBETAT 11
#define NBCLAS 8
/* successor of state */
static int transit[NBETAT][NBCLAS] = {
/* P a-h 1-8 x = ? */
/*(0 1 2 3 4 5 6 7)*/
{1,2, -1, -1, -1, -1, -1, -1 }, /* etat0 */
{ -1,2, -1, -1,4, -1, -1, -1 }, /* etat1 */
{ -1,6,3,4,4,8,TML,TML }, /* etat2 */
{ -1,6, -1,4,4,8,TML,TML }, /* etat3 */
{5,6, -1, -1, -1, -1, -1, -1 }, /* etat4 */
{ -1,6, -1, -1, -1, -1, -1, -1 }, /* etat5 */
{ -1, -1,7, -1, -1, -1, -1, -1 }, /* etat6 */
{ -1, -1, -1, -1, -1,8,TML,TML }, /* etat7 */
{9, -1, -1, -1, -1, -1,TML, -1 }, /* etat8 */
{ -1, -1, -1, -1, -1, -1,TML,TML }, /* etat9 */
{ -1, -1, -1, -1, -1, -1, -1, -1 }/* etat 10 == terminal */
};
/* actions to do */
static int action[NBETAT][NBCLAS] = {
/* P a-h 1-8 x = ? */
{1,2, -1, -1, -1, -1, -1, -1 }, /* etat0 */
{ -1,2, -1, -1, 10, -1, -1, -1 }, /* etat1 */
{ -1, 13,3,4,5, 14,6,7 }, /* etat2 */
{ -1, 13, -1,4,5, 14,6,7 }, /* etat3 */
{1,2, -1, -1, -1, -1, -1, -1 }, /* etat4 */
{ -1,2, -1, -1, -1, -1, -1, -1 }, /* etat5 */
{ -1, -1,3, -1, -1, -1, -1, -1 }, /* etat6 */
{ -1, -1, -1, -1, -1, 14,8,9 }, /* etat7 */
{ 15, -1, -1, -1, -1, -1, 17, -1 }, /* etat8 */
{ -1, -1, -1, -1, -1, -1, 17, 17 }, /* etat9 */
{ -1, -1, -1, -1, -1, -1, -1, -1 }/* etat 10 */
};
/* the complete play */
play * theplay ;
/* current game
the name tos means top of stack
*/
static game * tos = GULL ;
/* variable holding current move */
static depl * m = MULL ;
int alternate_moves[10][2]; /* table of alternate moves, guessed by
the move generator: guess depl
*/
/* the output driver */
static format * dr;
static int driver; /* driver type, ie gnu, ascii */
static int movecount;
/* current move, used by the parser */
static int curpiece,curcol,curlig ;
static int curdigit, curmove;
/* booleen derreur */
int error_flag = FALSE;
/* move to display board */
static int count = 0 ;
static int move_to_display[NB_MOVE_TO_DISP] ;
static int nb_move_to_dsp = 0;
static int stop_at_display = FALSE;
/* short and long form comment table */
char * com_short[] = {
#define CHESSSYMB(LET,LASC,SASC,TEX,PS,ENG,FRA) SASC,
#include chesssymb.def
};
#undef CHESSSYMB
char * com_long[] = {
#define CHESSSYMB(LET,LASC,SASC,TEX,PS,ENG,FRA) LASC,
#include chesssymb.def
};
#undef CHESSSYMB
#define setboard(A,I,J,P,C){ (A)->board[(I)][(J)] = (P) ;
(A)->color[(I)][(J)] = (C); }
#define clsboard(A,I,J) { (A)->board[(I)][(J)] = VOID ;
(A)->color[(I)][(J)] = VOID ;}
/* code part */
#ifdef __STDC__
static int ispiece(char c)
#else
static int ispiece(c)
char c;
#endif
{
register int i;
for ( i = 0 ; (i < NUMPIECES) && (c != in_table[i]) ; i++ ) ;/*(void) fprintf(stdout, “piece %d %c
” , i , c);*/return(i
g->color[i][j] = VOID;
}
}
#ifdef __STDC__
game * new_board(void)
#else
game * new_board()
#endif
{
game * tmp;
int i;
tmp = (game *) malloc (sizeof(game));
ALLOCP(tmp);
for (i=0; i < ((sizeof (game))/ sizeof (int)) ; i++)((int *) tmp)[i] = 0;return(tmp);}#ifdef __STDC__game * copy_board(game *from, game *to)#elsegame * copy_board(from, to) game * from; game * to;#endif{int i; for (i=0; i < ((sizeof (game))/ sizeof (int)) ; i++)((int *) to)[i] =((int *) from)[i] ;return(to);}#ifdef __STDC__void init_board(game *tgm)#elsevoid init_board(tgm)game * tgm;#endif{register int i,j;clear_board(tgm);for (i=1; i< 9 ; i=i+7) {tgm->board[i][1]= tgm->board[i][8] = ROOK ;
tgm->board[i][2]= tgm->board[i][7] = KNIGHT ;
tgm->board[i][3]= tgm->board[i][6] = BISHOP ;
tgm->board[i][4]= QUEEN;
tgm->board[i][5]= KING;
}
for (i=2; i< 8 ; i=i+5) for (j=1; j <=8 ; j++)tgm->board[i][j] = PAWN;
for (i=1; i <=2; i++)for (j=1; j <=8 ; j++) {tgm->color[i][j] = WHITE;
tgm->color[i+6][j] = BLACK ;
}
}
#ifdef __STDC__
depl * new_move(void)
#else
depl * new_move()
#endif
{
depl * tmp;
int i;
static int counter = 0;
tmp = (depl *) malloc (sizeof(depl *));
ALLOCP(tmp);
for (i=0; i < ((sizeof (depl))/ sizeof (int)) ; i++)((int *) tmp)[i] = 0;tmp->uid = ++counter;
tmp->whiteturn = FALSE;
tmp->move = 0;
return(tmp);
}
#ifdef __STDC__
void init_move(depl *m)
#else
void init_move(m)
depl *m;
#endif
{
m->move= 1 ;
m->whiteturn = TRUE ;
}
#ifdef __STDC__
depl * copy_move(depl *from,depl *to)
#else
depl * copy_move(from,to)
depl * from;
depl * to ;
#endif
{
int i;
for (i=0; i < ((sizeof (depl))/ sizeof (int)) ; i++)((int *) to)[i] = ((int *) from)[i];return(to);}/* add a new move as successor to the move m */#ifdef __STDC__depl * add_trailing_move(depl *mo)#elsedepl * add_trailing_move(mo) depl * mo;#endif{mo->next = new_move();
mo->next->prev = mo;
mo->next->next = (depl *) NULL;
mo->next->sub= (depl *) NULL;
mo->next->whiteturn = !( m->whiteturn ) ;
mo->next->move = mo->move;
if ( mo->next->whiteturn) {
mo->next->move++;
}
return(mo->next);
}
#ifdef __STDC__
static depl * add_variation(depl *mo)
#else
static depl * add_variation(mo)
depl * mo;
#endif
{
depl *ip ; /* insertion point */
ip = mo ;
while (ip->sub != (depl *) NULL )
ip = ip->sub ;
ip->sub = new_move();
ip->sub->prev = mo;
ip->sub->next = (depl *) NULL;
ip->sub->sub= (depl *) NULL;
/* as we have a fictif element heading our list,
( generated by add_trailing_move() )
we have to go back in the numbering */
ip->sub->whiteturn =mo->prev->whiteturn;
ip->sub->move = mo->prev->move ;
return(ip->sub);
}
#ifdef __STDC__
static void free_move_list(depl *d)
#else
static void free_move_list(d)
depl * d;
#endif
{
if (d->next != (depl *) NULL) {
free_move_list(d->next);
free(d->next);
d->next = (depl *) NULL;
}
if (d->sub != (depl *) NULL) {
free_move_list(d->sub);
free(d->sub);
d->sub = (depl *) NULL;
}
}
/* procedure upadate borad g with move m */
#ifdef __STDC__
void do_move(game *g,depl *m)
#else
void do_move(g,m)
game *g;
depl *m;
#endif
{
switch (m->type) {
case MOVE:
setboard(g,m->tolig,m->tocol,m->piece,CURCOLOR(m)) ;
clsboard(g,m->fromlig,m->fromcol) ;
break;
case PRISE:
setboard(g,m->tolig,m->tocol,m->piece,CURCOLOR(m)) ;
clsboard(g,m->fromlig,m->fromcol);
break;
case GRANDROQUE:
if (m->whiteturn)
m->fromlig = 1;
else
m->fromlig = 8;
setboard(g,m->fromlig,3,KING,CURCOLOR(m)) ;
setboard(g,m->fromlig,4,ROOK,CURCOLOR(m)) ;
clsboard(g,m->fromlig,1) ;
clsboard(g,m->fromlig,5) ;
break;
case PETITROQUE:
if (m->whiteturn)
m->fromlig = 1;
else
m->fromlig = 8;
setboard(g,m->fromlig,7,KING,CURCOLOR(m)) ;
setboard(g,m->fromlig,6,ROOK,CURCOLOR(m)) ;
clsboard(g,m->fromlig,5) ;
clsboard(g,m->fromlig,8) ;
break;
case EN_PASSANT:
setboard(g,m->tolig,m->tocol,m->piece,CURCOLOR(m)) ;
clsboard(g,m->tolig,m->fromcol) ;
clsboard(g,m->fromlig,m->fromcol) ;
break;
case PROMOTION:
setboard(g,m->tolig,m->tocol,m->piece,CURCOLOR(m)) ;
clsboard(g,m->fromlig,m->fromcol);
break;
case PROM_ET_PRISE:
setboard(g,m->tolig,m->tocol,m->piece,CURCOLOR(m)) ;
clsboard(g,m->fromlig,m->fromcol);
break;
default:
fprintf(stderr,
Unable to do move: unknown move type
);
break;
}
}
/* this procedure undo the effect of move m on the board g */
#ifdef __STDC__
void undo_move(game *g,depl *m)
#else
void undo_move(g,m)
game *g;
depl *m;
#endif
{
switch (m->type) {
case MOVE:
clsboard(g,m->tolig,m->tocol) ;
setboard(g,m->fromlig,m->fromcol,m->piece,CURCOLOR(m)) ;
break;
case PRISE:
setboard(g,m->tolig,m->tocol,m->prise,OPPCOLOR(m)) ;
setboard(g,m->fromlig,m->fromcol,m->piece,CURCOLOR(m)) ;
break;
case GRANDROQUE:
if (m->whiteturn)
m->fromlig = 1;
else
m->fromlig = 8;
clsboard(g,m->fromlig,3) ;
clsboard(g,m->fromlig,4) ;
setboard(g,m->fromlig,5,KING,CURCOLOR(m)) ;
setboard(g,m->fromlig,1,ROOK,CURCOLOR(m)) ;
break;
case PETITROQUE:
if (m->whiteturn)
m->fromlig = 1;
else
m->fromlig = 8;
clsboard(g,m->fromlig,6) ;
clsboard(g,m->fromlig,7) ;
setboard(g,m->fromlig,5,KING,CURCOLOR(m)) ;
setboard(g,m->fromlig,8,ROOK,CURCOLOR(m)) ;
break;
case EN_PASSANT:
clsboard(g,m->tolig,m->tocol) ;
setboard(g,m->tolig,m->fromcol,PAWN,OPPCOLOR(m)) ;
setboard(g,m->fromlig,m->fromcol,m->piece,CURCOLOR(m)) ;
break;
case PROMOTION:
clsboard(g,m->tolig,m->tocol);
setboard(g,m->fromlig,m->fromcol,PAWN,CURCOLOR(m)) ;
break;
case PROM_ET_PRISE:
setboard(g,m->tolig,m->tocol,m->prise,OPPCOLOR(m)) ;
setboard(g,m->fromlig,m->fromcol,PAWN,CURCOLOR(m)) ;
break;
default:
fprintf(stderr,
Unable to undo move: unknown move type
);
break;
}
}
/* variation procedures == stack manipulation */
#ifdef __STDC__
void enter_variation(void)
#else
void enter_variation()
#endif
{
int l;
l = dr->variation ;
if (l >= VARIATION_MAX) {
error((stderr,
Maximum imbricated variation is %d
,VARIATION_MAX));
} else {
/* save current line/variation */
stack[l].d = m;
stack[l].b = tos;
stack[l].d1 = dr->iswhiteturn;
stack[l].d2 = dr->interrupt = TRUE ;
/* create new */
tos = new_board();
(void) copy_board(stack[l].b, tos);
/* A variation FOLLOWS the main line
so we need to backtrack one move
*/
m = add_variation(stack[l].d);
undo_move(tos,stack[l].d);
/* set variables */
l++;
dr->variation = l;
output_variation(dr,VARIATION_IN);
}
}
#ifdef __STDC__
void exit_variation(void)
#else
void exit_variation()
#endif
{
int l ;
l = dr->variation ;
if (l == 0) {
error((stderr,
You cannot exit from the main line (a variation level error?)
));
} else {
output_variation(dr,VARIATION_OUT);
l;
free(m);
m = stack[l].d ;
tos = stack[l].b ;
dr->iswhiteturn = stack[l].d1 ;
dr->interrupt = stack[l].d2 ;
dr->variation = l;
}
}
/* semantic evaluation of move */
/* check ifposition lies within the board
*/
#ifdef __STDC__
int in_board(int l,int c)
#else
int in_board(l,c)
int l,c;
#endif
{
return ((c >= 1) && (c <= 8) && (l >= 1) && (l <= 8));}/* check that the path from pos1 to pos2 is free */#ifdef __STDC__int path_free(int l1,int c1,int l2,int c2)#elseint path_free(l1, c1, l2, c2)int l1,c1, l2, c2;#endif{int li = 1 ;int ci = 1 ;int lig, col;li = SIGN(l2-l1);ci = SIGN(c2-c1);if ( c1 == c2 ) {col = c1;for (lig = l1 +li; lig != l2 ; lig +=li)if (tos->board[lig][col] != VOID)
return (FALSE);
return(TRUE);
}
if ( l1 == l2) {
lig = l1 ;
for (col = c1 + ci; col != c2 ; col +=ci)
if (tos->board[lig][col] != VOID)
return (FALSE);
return(TRUE);
}
for (lig = l1+li,col =c1+ci; (lig!=l2) && (col!=c2); lig+=li, col+= ci)
if (tos->board[lig][col] != VOID) {
return (FALSE);
}
return(TRUE);
}
/* check roque is possible */
#ifdef __STDC__
int check_roque(void)
#else
int check_roque()
#endif
{
int lig, col ;
if (m->whiteturn)
lig = 1 ;
else
lig =8;
if (m->type == GRANDROQUE)
for (col = 2; col < 5 ; col++)if (tos->board[lig][col] != VOID)
return(FALSE);
if (m->type == PETITROQUE)
for (col = 6; col < 7 ; col++)if (tos->board[lig][col] != VOID)
return(FALSE);
return(TRUE);
}
/* check or guess where a given piece come */
#ifdef __STDC__
int guess_piece(void)
#else
int guess_piece()
#endif
{
return(tos->board[m->fromlig][m->fromcol]);
}
/* try to guess the move low-level function
it returns in the parms the coordinates of a possible move
it returns as value the number of possible move
*/
#ifdef __STDC__
int guess_depl(int nb, int tab[][2],
int * pl1, int * pc1, int l2, int c2, int path)
#else
int guess_depl(nb, tab, pl1, pc1, l2,c2,path)
int nb;
int tab[10][2];
int *pl1, *pc1;
int l2,c2;
int path; /* tell if we have to check for a free path
used for en passant */
#endif
{
int i, c, l;
int count = 0;
for (i=0; i< nb; i++ ) {l = l2 – tab[i][0];c = c2 – tab[i][1];if (in_board(l,c))if ((tos->board[l][c] == m->piece) &&
(tos->color[l][c] == CURCOLOR(m)) &&
( !path || (path && path_free(l,c, l2, c2))) &&
( ((*pl1) == 0) || ((*pl1) == l) ) &&
( ((*pc1) == 0) || ((*pc1) == c) ) )
{
alternate_moves[count][0] = l;
alternate_moves[count][1] = c;
count++;
}
}
alternate_moves[count][0] = alternate_moves[count][1] = 0;
if (count > 0) {
/* we return the first entry because the last entry, in the case of pawn,
movement, might be a catching move, even it a non-catching, more
probable, is present
*/
*pl1 = alternate_moves[0][0];
*pc1 = alternate_moves[0][1];
}
return(count);
}
/* check for ambiguity in a move
used in output function: the piece had been already moved and
if we guess another move, there is an ambiguity
*/
#ifdef __STDC__
int ambiguity(depl *d, int *amline, int *amcols)
#else
int ambiguity(d, amline, amcols )
depl *d ;
int * amline;
int *amcols;
#endif
{
int l1 = 0 ;
int c1 = 0 ;
int r = 0;
int frompiece = d->piece;
int l2 = d->tolig;
int c2 = d->tocol ;
int i;
undo_move(tos,m);
switch(frompiece) {
case PAWN:
if (m->type == PRISE) {
if (m->whiteturn)
r = guess_depl(NB_M_PAWN_WX, m_pawn_wx, &l1,&c1, l2,c2, FALSE);
else
r = guess_depl(NB_M_PAWN_BX, m_pawn_bx, &l1,&c1, l2,c2, FALSE);
} else {
if (m->whiteturn)
r = guess_depl(NB_M_PAWN_MOVE_WD,m_pawn_move_wd,&l1,&c1, l2,c2, FALSE);
else
r = guess_depl(NB_M_PAWN_MOVE_BD,m_pawn_move_bd,&l1,&c1,l2,c2, FALSE);
}
break;
case KNIGHT:
r = guess_depl(NB_M_KNIGHT, m_knight, &l1,&c1, l2,c2, FALSE);
break;
case BISHOP:
r = guess_depl(NB_M_BISHOP, m_bishop, &l1,&c1, l2,c2, TRUE);
break;
case ROOK:
r = guess_depl(NB_M_ROOK, m_rook, &l1,&c1, l2,c2, TRUE);
break;
case QUEEN:
r = guess_depl(NB_M_QUEEN,m_queen,&l1,&c1, l2,c2, TRUE);
break;
case KING:
r = guess_depl(NB_M_KING, m_king, &l1,&c1, l2,c2, TRUE);
break;
default:
break;
}
do_move(tos,m);
if (r > 1) {
/* we have an ambiguity, we use alternate_moves to resolve it:
we look through that table to find identical lines: if so,
we signal that the column determines move;
we then do the same with columns
*/
*amline = TRUE ;
*amcols = TRUE ;
for (i= 1; i < r ; i++) {if (alternate_moves[i][0] != alternate_moves[0][0])*amline = FALSE;if (alternate_moves[i][1] != alternate_moves[0][1])*amcols = FALSE;}}return( (r > 1) );
}
#ifdef __STDC__
int check_move(depl *m)
#else
int check_move(m)
depl * m;
#endif
{
int l1,c1,l2,c2;
int tmp; /* tmp boolean */
l1 = m->fromlig;
c1 = m->fromcol;
l2 = m->tolig;
c2 = m->tocol;
if ((m->type == GRANDROQUE) || (m->type == PETITROQUE))
return(check_roque());
if ((tos->board[l1][c1] != m->piece)||
(tos->color[l1][c1] != CURCOLOR(m))){
fprintf(stderr,Problem: piece should be %c
,in_table[tos->board[l1][c1]]);
if (m->whiteturn)
error ((stderr,
Originating position and piece not coherent for White move %d
,m->move));
else
error ((stderr,
Originating position and piece not coherent for Black move %d
,m->move));
return(FALSE);
}
/* if prise === FALSE, we must not take a piece */
if (tos->board[l2][c2] != VOID
&& (m->type != PRISE) && (m->type != PROM_ET_PRISE)) {
(void) fprintf(stderr,catching not indicated at move %d.
,m->move);
return(FALSE);
}
/* prendre une de ses propres pieces */
if (tos->color[l2][c2] == tos->color[l1][c1] && m->prise) {
(void) fprintf(stderr,attempt to catch same color piece at move %d.
,
m->move);
return(FALSE);
}
/* we check if the move is a possible one for the piece
*/
switch(m->piece) {
case PAWN:
if (m->prise) {
if (m->whiteturn)
tmp = guess_depl(NB_M_PAWN_WX, m_pawn_wx, &l1,&c1, l2,c2, FALSE);
else
tmp = guess_depl(NB_M_PAWN_BX, m_pawn_bx, &l1,&c1, l2,c2, FALSE);
} else {
if (m->whiteturn)
tmp = guess_depl(NB_M_PAWN_WD, m_pawn_wd, &l1,&c1, l2,c2, FALSE);
else
tmp = guess_depl(NB_M_PAWN_BD, m_pawn_bd, &l1,&c1, l2,c2, FALSE);
}
/* is it a prise en passant */
if ((c1 != c2) && (tos->board[l2][c2] == VOID)
&& (tos->board[l1][c2] == PAWN)) {
m->type = EN_PASSANT ;
/* we must perform here the en passant test */
tos->board[l1][c2] = VOID ;
tos->color[l1][c2] = VOID ;
tmp = TRUE;
}
return(tmp);
break;
case KNIGHT:
return(guess_depl(NB_M_KNIGHT, m_knight, &l1,&c1, l2,c2, FALSE));
break;
case BISHOP:
return(guess_depl(NB_M_BISHOP, m_bishop, &l1,&c1, l2,c2, TRUE));
break;
case ROOK:
return(guess_depl(NB_M_ROOK, m_rook, &l1,&c1, l2,c2, TRUE));
break;
case QUEEN:
return(guess_depl(NB_M_QUEEN,m_queen,&l1,&c1, l2,c2, TRUE));
break;
case KING:
return(guess_depl(NB_M_KING, m_king, &l1,&c1, l2,c2, TRUE));
break;
default:
break;
}
return(TRUE);
}
/* try to guess the move used for shortened notation
*/
#ifdef __STDC__
int guess_move(void)
#else
int guess_move()
#endif
{
int l1,c1,l2,c2;
if ((m->type == GRANDROQUE) || (m->type == PETITROQUE))
return(TRUE);
l1 = m->fromlig ;
c1 = m->fromcol ;
l2 = m->tolig;
c2 = m->tocol;
switch(m->piece) {
case PAWN:
if (m->prise) {
if (m->whiteturn)
(void) guess_depl(NB_M_PAWN_WX, m_pawn_wx, &l1,&c1, l2,c2, FALSE);
else
(void) guess_depl(NB_M_PAWN_BX, m_pawn_bx, &l1,&c1, l2,c2, FALSE);
} else {
if (m->whiteturn)
(void) guess_depl(NB_M_PAWN_WD, m_pawn_wd, &l1,&c1, l2,c2, FALSE);
else
(void) guess_depl(NB_M_PAWN_BD, m_pawn_bd, &l1,&c1, l2,c2, FALSE);
}
break;
case KNIGHT:
(void) guess_depl(NB_M_KNIGHT, m_knight, &l1,&c1, l2,c2, FALSE);
break;
case BISHOP:
(void) guess_depl(NB_M_BISHOP, m_bishop, &l1,&c1, l2,c2, TRUE);
break;
case ROOK:
(void) guess_depl(NB_M_ROOK, m_rook, &l1,&c1, l2,c2, TRUE);
break;
case QUEEN:
(void) guess_depl(NB_M_QUEEN, m_queen, &l1,&c1, l2,c2, TRUE);
break;
case KING:
(void) guess_depl(NB_M_KING, m_king, &l1,&c1, l2,c2, TRUE);
break;
default:
break;
}
if ((l1 == 0) || (c1 == 0)) {
if (m->whiteturn)
error((stderr,
Unable to guess white move %d, with piece %c
,
m->move,in_table[m->piece]));
else
error((stderr,
Unable to guess black move %d, with piece %c
,
m->move,in_table[m->piece]));
return(FALSE);
} else {
m->fromcol = c1;
m->fromlig = l1;
return(TRUE);
}
}
/* execution of move */
/* clear a position */
#ifdef __STDC__
int clear_pos(int lig, int col)
#else
int clear_pos(lig,col)
int lig;
int col;
#endif
{
tos->board[lig][col] = VOID ;
tos->color[lig][col] = VOID ;
return(TRUE);
}
/* configure the board */
#ifdef __STDC__
int configure(void)
#else
int configure()
#endif
{
if (configuring) {
if (m->piece == VOID)
m->piece = PAWN ;
tos->board[m->tolig][m->tocol] = m->piece ;
tos->color[m->tolig][m->tocol] = configside ;
}
return(TRUE);
}
/* execute a move, no checking */
#ifdef __STDC__
int execute_move(void)
#else
int execute_move()
#endif
{
register int i;
if (m->piece == VOID )
m->piece = PAWN;
if ((m->fromlig == 0) || (m->fromcol == 0))
(void) guess_move();
/* supply to the maybe deficiency of input notation
*/
if ((m->fromlig !=0) || (m->fromcol != 0))
m->piece = tos->board[m->fromlig][m->fromcol];
if (tos->board[m->tolig][m->tocol] != VOID) {
m->type = PRISE;
m->prise = tos->board[m->tolig][m->tocol] ;
}
if (!check_move(m)) {
if (m->whiteturn)
error((stderr,
White move %d illegal
,m->move));
else
error((stderr,
Black move %d illegal
,m->move));
}
do_move(tos, m);
output_move(dr,m);
if (error_flag) {
(void) fprintf(dr->outfile,
Last position encountered:
);
output_board(dr,tos);
close_files();
exit(0);
}
/* do we need to display the move ? */
if (nb_move_to_dsp > 0) {
for (i=0; i < nb_move_to_dsp; i++)if (m->move == (move_to_display[i] ) && !m->whiteturn ) {
output_board(dr,tos);
if (stop_at_display) {
output_end(dr);
close_files();
exit(0);
}
}
}
return(TRUE);
}
/* automata */
/* categorise the input for the automata */
#ifdef __STDC__
int typechar(char c)
#else
int typechar(c)
char c;
#endif
{
if (ispiece(c))
return(0);
if ((c >=a) && ( c <= ‘h’))return(1);if ((c >=1) && ( c <= ‘8’))return(2);if ( c== ‘-‘ )return(3);if ((c == ‘x’) || (c == ‘X’ ))return(4);if (c == ‘=’ )return(5);if (c == ‘