home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume18
/
notation
/
part03
/
notation.c
Wrap
C/C++ Source or Header
|
1991-04-13
|
31KB
|
1,315 lines
/* Programme d'analyse de notation echiquienne
Copyright (C) 1990 Henry Thomas
Nom: notation.c
Auteur: Henry Thomas
Date: 27/11/90
*/
/* @(#)notation.c 2.1 4/11/91 (C) Henry Thomas */
/*
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
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "chesstype.h"
#include "drivers.h"
#include "notation.h"
#include "lexer.h"
extern void close_files();
char * version_string =
"@(#)notation.c 2.1 (C) Henry Thomas\tVersion 2.1\tDated 4/11/91";
static char * keywords[]= {
"@startplay" , "@clearboard" , "@showboard" ,
"@whitesmove", "@blacksmove", "@configwhite", "@configblack" ,
"@default" , "@special", "@null"
};
int configuring = FALSE ;
int configside = 0 ;
static char * t_language[] = {
"french", "english", "italian", "spanish", "german", "dutch" };
static int in_language = DEFAULT_INPUT_LANGUAGE ;
static int out_language = DEFAULT_OUTPUT_LANGUAGE ;
static char c_french[] = { '@' ,'R' , 'D' , 'T' , 'F' , 'C' , 'P' } ;
static char c_english[] = { '@' ,'K' , 'Q' , 'R' , 'B' , 'N' , 'P' } ;
static char c_italian[] = { '@' ,'R' , 'D' , 'T' , 'A' , 'C' , 'P' } ;
static char c_spanish[] = { '@' ,'R' , 'D' , 'T' , 'A' , 'C' , 'P' } ;
static char c_german[] = { '@' ,'K' , 'D' , 'T' , 'L' , 'S' , 'B' } ;
static char c_dutch[] = { '@' ,'K' , 'D' , 'T' , 'L' , 'P' , 'O' } ;
static char c_russian[] = { '@' ,'K' , 'F' , 'D' , 'C' , 'K' , 'P' } ;
/* translation tables */
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_KNIGHT 8
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" };
/* ---------- automata definitions --------- */
/* table for syntaxic analysis of move */
#define FINAL 10
#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 ? */
/*( 0 1 2 3 4 5 6 7)*/
{ 1, 2, -1, -1, -1, -1, -1, -1 }, /* etat 0 */
{ -1, 2, -1, -1, 4, -1, -1, -1 }, /* etat 1 */
{ -1, 6, 3, 4, 4, 8,TML,TML }, /* etat 2 */
{ -1, 6, -1, 4, 4, 8,TML,TML }, /* etat 3 */
{ 5, 6, -1, -1, -1, -1, -1, -1 }, /* etat 4 */
{ -1, 6, -1, -1, -1, -1, -1, -1 }, /* etat 5 */
{ -1, -1, 7, -1, -1, -1, -1, -1 }, /* etat 6 */
{ -1, -1, -1, -1, -1, 8,TML,TML }, /* etat 7 */
{ 9, -1, -1, -1, -1, -1, -1, -1 }, /* etat 8 */
{ -1, -1, -1, -1, -1, -1,TML,TML }, /* etat 9 */
{ -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 = \0 ? */
{ 1, 2, -1, -1, -1, -1, -1, -1 }, /* etat 0 */
{ -1, 2, -1, -1, 10, -1, -1, -1 }, /* etat 1 */
{ -1, 13, 3, 4, 5, 14, 6, 7 }, /* etat 2 */
{ -1, 13, -1, 4, 5, 14, 6, 7 }, /* etat 3 */
{ 1, 2, -1, -1, -1, -1, -1, -1 }, /* etat 4 */
{ -1, 2, -1, -1, -1, -1, -1, -1 }, /* etat 5 */
{ -1, -1, 3, -1, -1, -1, -1, -1 }, /* etat 6 */
{ -1, -1, -1, -1, -1, 14, 8, 9 }, /* etat 7 */
{ 15, -1, -1, -1, -1, -1, -1, -1 }, /* etat 8 */
{ -1, -1, -1, -1, -1, -1, 17, 17 }, /* etat 9 */
{ -1, -1, -1, -1, -1, -1, -1, -1 } /* etat 10 */
};
/* current game
the name "tos" means "top of stack"
*/
static game * tos = GULL ;
/* array to see the king is in check
use in checkroque()
*/
/* booleen d'erreur */
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;
/* variable holding current move */
static depl * m = MULL ;
/* current move, used by the parser */
static int curpiece, curcol, curlig ;
static int curdigit, curmove;
static format * dr;
static int driver; /* driver type, ie gnu, ascii ... */
#define setboard(A,I,J,P,C) ({(A)->board[(I)][(J)] = (P) ; \
(A)->color[(I)][(J)] = (C);})
#define clsboard(A,I,J,P,C) ({(A)->board[(I)][(J)] = VOID ; \
(A)->color[(I)][(J)] = VOID; }))
/* --------------------------- code part --------------------- */
static int ispiece(c)
char c;
{
register int i;
for ( i = 0 ; (i < NUMPIECES) && (c != in_table[i]) ; i++ ) ;
/*(void) fprintf(stdout, "piece %d %c\n" , i , c);*/
return(i<NUMPIECES);
}
static int piece(c)
char c ;
{
register int i;
for ( i = 0 ; (i < NUMPIECES) && (c != in_table[i]) ; i++ ) ;
if ( i== NUMPIECES)
i = PAWN ;
return(i);
}
/* this function return yhe # entry of a keyword in a given table.
if key is not present, it returns the default value
*/
static int find_keyword(tab, nbentry,defaut,key)
char * tab[];
int nbentry;
int defaut;
char *key;
{
int i ;
for(i=0; (i< nbentry) ;i++)
if (strcmp(tab[i],key)==0)
return(i);
/* we failed to find the keyword */
(void) fprintf (stderr, "unknow keyword %s in this context\n",key);
return(defaut);
}
/* ---------- board management function ------------- */
void clear_board(g)
game *g;
{
register int i,j;
for (i=0; i < 10; i++ )
for (j=0 ; j< 10 ; j++) {
g->board[i][j] = VOID;
g->color[i][j] = VOID;
}
}
game * new_board()
{
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);
}
void init_board(tgm)
game * tgm;
{
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 ;
}
}
depl * new_move()
{
depl * tmp;
int i;
tmp = (depl *) malloc (sizeof(depl));
ALLOCP(tmp);
/*for (i=0; i < ((sizeof (depl))/ sizeof (int)) ; i++)
((int *) tmp)[i] = 0;*/
return(tmp);
}
void init_move(m)
depl *m;
{
m->move= 1 ;
m->whiteturn = TRUE ;
}
/* ----------- semantic evaluation of move ----------- */
/* check if position lies within the board
*/
int in_board(l,c)
int l,c;
{
return ((c >= 1) && (c <= 8) && (l >= 1) && (l <= 8));
}
/* check that the path from pos1 to pos2 is free
*/
int path_free(l1, c1, l2, c2)
int l1,c1, l2, c2;
{
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 */
int check_roque()
{
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);
if (m->is_check[CURCOLOR(m)])
return(FALSE);
return(TRUE);
}
/* check -- or guess -- where a given piece come */
int guess_piece() {return(tos->board[m->fromlig][m->fromcol]); }
/* try to guess the move -- low-level function */
int guess_depl(nb, tab, pl1, pc1, l2,c2,path)
int nb;
int tab[][2];
int *pl1, *pc1;
int l2,c2;
int path;
{
int i;
int c,l;
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) ) )
{
*pl1 = l;
*pc1 = c;
return(TRUE);
}
}
return(FALSE);
}
/* check for ambiguitey in a move
used in ouptut function: the piece had beenm already moved and
if we guess another move, there is an ambiguity
*/
int ambiguity(frompiece, l2, c2)
int frompiece, l2, c2 ;
{
int l1 = 0 ;
int c1 = 0 ;
switch(frompiece) {
case PAWN:
if (m->type == PRISE) {
if (m->whiteturn)
return(guess_depl(NB_M_PAWN_WX, m_pawn_wx, &l1,&c1, l2,c2, FALSE));
else
return(guess_depl(NB_M_PAWN_BX, m_pawn_bx, &l1,&c1, l2,c2, FALSE));
} else {
if (m->whiteturn)
return(guess_depl(NB_M_PAWN_MOVE_WD, m_pawn_move_wd,
&l1,&c1, l2,c2, FALSE));
else
return(guess_depl(NB_M_PAWN_MOVE_BD, m_pawn_move_bd,
&l1,&c1, l2,c2, FALSE));
}
/* 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);
}
int check_move(m)
depl * m;
{
int l1,c1,l2,c2,l;
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))){
printf("==%d\n",tos->board[l1][c1]);
error ((stderr,"from position and piece not correct\n"));
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\n",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\n",
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 ;
l = l1 + (l2 - l1)/2;
/* 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
*/
int guess_move()
{
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 move %d white (%d)\n",
m->move,m->piece));
else
error((stderr,"unable to guess move %d black (%d)\n",
m->move,m->piece));
return(FALSE);
} else {
m->fromcol = c1;
m->fromlig = l1;
return(TRUE);
}
}
/* --------------- execution of move ----------------- */
/* clear a position */
int clear_pos(lig,col)
int lig;
int col;
{
tos->board[lig][col] = VOID ;
tos->color[lig][col] = VOID ;
return(TRUE);
}
/* configure the board */
int configure()
{
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 */
int execute_move()
{
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\n",m->move));
else
error((stderr,"black move %d illegal\n",m->move));
}
if (m->type == PETITROQUE) {
if (m->whiteturn)
curlig = 1 ;
else
curlig = 8 ;
tos->board[curlig][7] = KING;
tos->board[curlig][6] = ROOK;
tos->color[curlig][7] = tos->color[curlig][5] ;
tos->color[curlig][6] = tos->color[curlig][5] ;
(void) clear_pos(curlig, 5);
(void) clear_pos(curlig, 8);
}
if (m->type == GRANDROQUE) {
if (m->whiteturn)
curlig = 1 ;
else
curlig = 8 ;
tos->board[curlig][3] = KING;
tos->board[curlig][4] = ROOK;
tos->color[curlig][3] = tos->color[curlig][5] ;
tos->color[curlig][4] = tos->color[curlig][5] ;
(void) clear_pos(curlig, 5);
(void) clear_pos(curlig, 1);
}
if (!(m->type == GRANDROQUE) || (m->type == PETITROQUE)) {
if (m->piece == VOID)
m->piece = tos->board[m->fromlig][m->fromcol];
/*if (m->topiece == VOID)
m->topiece = tos->board[m->fromlig][m->fromcol];*/
tos->board[m->tolig][m->tocol] = tos->board[m->fromlig][m->fromcol];
tos->color[m->tolig][m->tocol] = tos->color[m->fromlig][m->fromcol];
(void) clear_pos(m->fromlig,m->fromcol);
}
if ((m->type == PROMOTION) || (m->type == PROM_ET_PRISE))
tos->board[m->tolig][m->tocol] = m->promotion ;
output_move(dr,m);
if (error_flag) {
(void) fprintf(dr->outfile, "\nlast position encountered:\n");
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 */
int typechar(c)
char c;
{
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 == '\0' )
return(6);
return(7);
}
/* execute the actions decided by the automata */
int execute(num,c)
int num;
char c;
{
switch (num) {
case 1: /* set cur piece */
curpiece = piece(c);
break;
case 2: /* set cur col */
curcol = lettertocol(c);
break;
case 3: /* set cur lig */
curlig = lettertolig(c);
break;
case 4: /* from = cur ; prise = false */
m->piece = curpiece ;
m->fromcol = curcol ;
m->fromlig = curlig;
/*m->topiece = curpiece;*/
break;
case 5: /* from = cur ; prise = true */
m->piece = curpiece ;
m->fromcol = curcol ;
m->fromlig = curlig;
m->type = PRISE ;
m->prise = curpiece;
break;
case 6: /* to = cur ; guess from */
case 7: /* to = cur ; guess from ; parse remaining token */
m->piece = curpiece ;
m->tocol = curcol;
m->tolig = curlig ;
/*m->topiece = curpiece ; /* ? */
if (configuring)
(void) configure();
else {
(void) execute_move();
m->whiteturn = !m->whiteturn ;
if (m->whiteturn) m->move++ ;
}
break;
case 8: /* to = cur */
case 9: /* to = cur */
m->tocol = curcol;
m->tolig = curlig ;
/*m->topiece = curpiece ;*/
if (configuring)
(void) configure();
else {
(void) execute_move();
m->whiteturn = !m->whiteturn ;
if (m->whiteturn) m->move++ ;
}
break;
case 10: /* piece = cur piece ; prise = true */
/* later : guess from position */
m->piece = curpiece ;
m->type = PRISE ;
break;
case 11: /* grand roque */
case 12: /* petit roque */
(void) execute_move();
m->whiteturn = !m->whiteturn ;
if (m->whiteturn) m->move++ ;
break;
case 13: /* case of simpliest algebraic notation ;
only e2e4 : this is the transition from e2 to e4
also the case of move such as Nge2
from =cur; prise = FALSE;
also:
curcol = ...
*/
m->piece = curpiece ;
m->fromcol = curcol ;
m->fromlig = curlig;
/*m->topiece = curpiece;*/
m->type = MOVE;
curcol = lettertocol(c);
case 14: /* promotion, the "=" */
break;
case 15: /* promotion, the piece name */
/* to = cur ; guess from */
case 16:
/* to = cur */
m->tocol = curcol;
m->tolig = curlig ;
/*m->topiece = curpiece ;*/
if (m->type == PRISE )
m->type = PROM_ET_PRISE ;
else
m->type = PROMOTION ;
m->promotion = curpiece = piece(c) ;
break;
case 17: /* execute move for promotion */
(void) execute_move();
m->whiteturn = !m->whiteturn ;
if (m->whiteturn) m->move++ ;
break;
case -1:
break;
default:
break;
}
return(TRUE);
}
int parse_number(token)
char *token;
{
int curmove = 0 ;
int i;
/* check coherency with internal numbering */
i = 0;
while (isdigit(token[i])) {
curmove = curmove * 10 + ((int) token[i++] - (int) '0' );
}
if (curmove != m->move)
(void) fprintf(stderr,"problem in move numbering: %d vs %d\n",
m->move, curmove);
return(TRUE);
}
int parse_keyword(token)
char *token;
{
char c;
switch (find_keyword(keywords, NBKEYWORD, KNULL, token)) {
case START:
configuring = FALSE;
m->move = 1;
m->whiteturn = TRUE;
break;
case CLEAR:
clear_board(tos);
break;
case SHOWBOARD:
output_board(dr,tos);
break;
case TOWHITE:
m->move = 1;
m->whiteturn = TRUE;
break;
case TOBLACK:
m->move = 1;
m->whiteturn = FALSE;
break;
case CONFIGWH:
configuring = TRUE ;
configside = WHITE;
break;
case CONFIGBL:
configuring = TRUE ;
configside = BLACK;
break;
case DEFAULTP:
init_board(tos);
break;
case SPECIAL: /* all input, up to \n is copied to output */
while ((( c = getc(infile)) != EOF) && (c != '\n'))
(void) putc (c,dr->outfile);
putc ('\n', dr->outfile);
break;
case KNULL:
default:
break;
}
return(TRUE);
}
int parse_roque(token)
char * token;
{
int i;
for (i=0; i < NBROQUE && (strcmp(c_roque[i],token)!=0); i++) ;
if ( i < NBROQUE ) {
if (strlen(token) == 3) {
m->type = PETITROQUE ;
(void) execute(12,DUMMYCHAR);
} else {
m->type = GRANDROQUE ;
(void) execute(11,DUMMYCHAR);
}
/*(void) fprintf(stderr,"ROQUE\n");*/
return(TRUE);
}
return(FALSE);
}
int parse_move(token)
char *token;
{
register int i;
int correcte = FALSE ;
int erreursyntaxe = FALSE ;
int etat =0;
int code;
i=0;
while ( !correcte && !erreursyntaxe ) {
code = typechar(token[i]);
(void) execute(action[etat][code],token[i]);
etat = transit[etat][code] ;
if (etat == -1)
erreursyntaxe = TRUE;
if (etat == FINAL)
correcte = TRUE ;
i++;
}
if (erreursyntaxe) {
(void) fprintf(stderr, "no comprende, senor: %s\n",token);
return(FALSE);
}
if (correcte) {
/*(void) fprintf(stderr, "ia panimaiou, davai\n");*/
}
return(TRUE);
}
void init_parse(m)
depl * m ;
{
int i;
/* global position and piece variable initialised to 0
*/
/* move and whiteturn unchanged */
m->type = MOVE ;
curpiece = m->piece = VOID ;
curcol = m->tocol = m->fromcol = 0;
curlig = m->tolig = m->fromlig = 0;
m->promotion = VOID;
m->prise = VOID;
for (i=0; i< 3; i++)
m->is_check[i] = FALSE ;
curdigit = curmove = 0;
}
/* ------------------- top routines -------------------- */
/* cette fonction analyse les arguments de la ligne de commande
*/
int parse_options(argc,argv)
int argc;
char * argv[];
{
int narg =1 ;
int i;
register int c;
char cp[132];
char chaine[MAXTOKLEN];
infile = stdin;
dr->outfile = stdout;
nb_move_to_dsp = 0;
while (narg < argc ) {
(void) strcpy (cp,argv[narg]);
switch (cp[0]) {
case '-' :
switch (cp[1]) {
case 'f' : /* from langage */
if ((narg+1) >= argc )
fatal((stderr,"missing argument to %s option",cp));
narg++ ;
in_language = find_keyword (t_language, NBLANGUAGE,
DEFAULT_INPUT_LANGUAGE,
argv[narg]);
break;
case 't' : /* to langage */
if ((narg+1) >= argc )
fatal((stderr,"missing argument to %s option",cp));
narg++ ;
out_language = find_keyword (t_language, NBLANGUAGE,
DEFAULT_OUTPUT_LANGUAGE,
argv[narg]);
break;
case 'o' : /* next arg is output file */
narg++ ;
if ((dr->outfile = fopen (argv[narg],"w+")) == NULL) {
(void) fprintf (stderr,"can't open %s output file\n",argv[narg]);
(void) fprintf (stderr,"assume stdout for output\n");
}
break;
case 'e':
if ((narg+1) >= argc )
fatal((stderr,"missing argument to %s option",cp));
narg++ ;
i=0;
nb_move_to_dsp = 0;
move_to_display[nb_move_to_dsp] = 0;
while (isdigit(argv[narg][i])) {
move_to_display[nb_move_to_dsp] =
((int) argv[narg][i] - (int) '0')
+ move_to_display[nb_move_to_dsp] * 10;
i++;
}
nb_move_to_dsp++;
stop_at_display = TRUE;
break;
case 'c':
if ((narg+1) >= argc )
fatal((stderr,"missing argument to %s option",cp));
narg++ ;
i=0;
while (isdigit(argv[narg][i])) {
move_to_display[nb_move_to_dsp] = 0;
while (isdigit(argv[narg][i])) {
move_to_display[nb_move_to_dsp] =
((int) argv[narg][i] - (int) '0')
+ move_to_display[nb_move_to_dsp] * 10;
i++;
}
nb_move_to_dsp++;
if (nb_move_to_dsp > NB_MOVE_TO_DISP)
fatal((stderr,"max. number of move to display exceeded"));
/* process next number */
if (argv[narg][i] == ',')
i++;
}
break;
case 'a': /* algebraic output */
dr->output_move_format = ALGEBRAIC;
break;
case 's': /* shortened output */
dr->output_move_format = SHORTENED;
break;
case 'b': /* display only the board, no move */
dr->only_board = TRUE;
break;
case 'd': /* output driver */
if ((narg+1) >= argc )
fatal((stderr,"missing argument to %s option",cp));
narg++ ;
driver = find_keyword(t_output, NB_DRIVER, DEFAULT_DRIVER,
argv[narg]);
break;
case 'h': /* help file */
(void) strcpy(chaine,LIB_DIR);
if ((fhelp = fopen(strcat(chaine,HELP_FILE),"r")) == NULL)
fatal((stderr,"Can't find help file.\n"));
else {
while ((c = getc(fhelp)) != EOF)
(void) fputc(c,stderr);
(void) fclose(fhelp);
exit(0);
}
break;
default:
error((stderr,"unknown command line options %s\n",cp));
break;
}
break;
default: /* assume this is the input file */
if ((infile = fopen (cp,"r")) == NULL)
fatal((stderr,"can't open %s input file\n",cp));
}
narg++;
} /* process next arg */
return(argc);
}
void close_files()
{
if (infile != stdin )
(void) fclose(infile);
if (dr->outfile != stdout )
(void) fclose(dr->outfile);
}
int associe_traduction (table, langage)
char ** table;
int langage ;
{
switch (langage) {
case FRENCH :
*table = c_french ;
break;
case ENGLISH:
*table = c_english ;
break;
case ITALIAN:
*table = c_italian ;
break;
case SPANISH:
*table = c_spanish ;
break;
case GERMAN:
*table = c_german ;
break;
case DUTCH:
*table = c_dutch ;
break;
case RUSSIAN:
(void) fprintf(stderr,"russian not yet implemented\n");
*table = c_russian ;
break;
default:
error((stderr,"unknown langage\n"));
}
return(langage);
}
/* ------------- main --------------------- */
main(argc,argv)
int argc;
char * argv[];
{
(void) fprintf(stderr,"%s\n",version_string);
/* allocation of driver descriptor */
dr = new_driver();
/* default configuration */
init_driver(dr,DEFAULT_DRIVER);
(void) associe_traduction(&in_table, DEFAULT_INPUT_LANGUAGE );
(void) associe_traduction(&(dr->out_table), DEFAULT_OUTPUT_LANGUAGE);
(void) parse_options(argc,argv);
(void) associe_traduction (&in_table, in_language);
(void) associe_traduction (&(dr->out_table), out_language);
/* assoc driver */
init_driver(dr,driver);
configuring = FALSE;
configside = VOID;
/* initialise output file */
output_init(dr);
if (error_flag)
fatal((stderr,"too many errors"));
/* allocation of move descriptor */
m = new_move();
init_move(m);
/* allocation of board descriptor */
tos = new_board();
init_board(tos);
/*output_board(dr,tos);*/
while (nexttoken()) {
/*(void) fprintf(stdout,"%s%\n", curtok);*/
init_parse(m);
(void) parsetoken();
}
if ((count == 0) && !error_flag)
output_board(dr,tos);
if (error_flag) {
error((stderr,"last valid position:\n"));
output_board(dr,tos);
fatal((stderr,"too many errors"));
}
/* terminates output files */
output_end(dr);
/* close files */
close_files();
/* exit properly */
#ifdef TURBOC
return(TRUE);
#else
exit(0);
#endif
}