v18i014: notation - Chess text converter, Part03/03
Henry Thomas
hthomas at irisa.fr
Fri Apr 12 13:29:57 AEST 1991
Submitted-by: Henry Thomas <hthomas at irisa.fr>
Posting-number: Volume 18, Issue 14
Archive-name: notation/part03
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 3)."
# Contents: notation.c
# Wrapped by hthomas at illico on Thu Apr 11 14:44:55 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'notation.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'notation.c'\"
else
echo shar: Extracting \"'notation.c'\" \(31006 characters\)
sed "s/^X//" >'notation.c' <<'END_OF_FILE'
X/* Programme d'analyse de notation echiquienne
X Copyright (C) 1990 Henry Thomas
X Nom: notation.c
X Auteur: Henry Thomas
X Date: 27/11/90
X */
X/* @(#)notation.c 2.1 4/11/91 (C) Henry Thomas */
X/*
XThis file is part of NOTATION program.
X
XNOTATION is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation; either version 1, or (at your option)
Xany later version.
X
XNOTATION is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with NOTATION; see the file COPYING. If not, write to
Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X/* --------------------- data part ---------------------- */
X
X/* les tableaux suivants sont les tables de transcription de notation
X selon les langages
X */
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X
X#include "chesstype.h"
X#include "drivers.h"
X#include "notation.h"
X#include "lexer.h"
X
Xextern void close_files();
X
X
Xchar * version_string =
X "@(#)notation.c 2.1 (C) Henry Thomas\tVersion 2.1\tDated 4/11/91";
X
Xstatic char * keywords[]= {
X "@startplay" , "@clearboard" , "@showboard" ,
X "@whitesmove", "@blacksmove", "@configwhite", "@configblack" ,
X "@default" , "@special", "@null"
X };
X
Xint configuring = FALSE ;
Xint configside = 0 ;
X
X
Xstatic char * t_language[] = {
X "french", "english", "italian", "spanish", "german", "dutch" };
X
Xstatic int in_language = DEFAULT_INPUT_LANGUAGE ;
Xstatic int out_language = DEFAULT_OUTPUT_LANGUAGE ;
X
Xstatic char c_french[] = { '@' ,'R' , 'D' , 'T' , 'F' , 'C' , 'P' } ;
Xstatic char c_english[] = { '@' ,'K' , 'Q' , 'R' , 'B' , 'N' , 'P' } ;
Xstatic char c_italian[] = { '@' ,'R' , 'D' , 'T' , 'A' , 'C' , 'P' } ;
Xstatic char c_spanish[] = { '@' ,'R' , 'D' , 'T' , 'A' , 'C' , 'P' } ;
Xstatic char c_german[] = { '@' ,'K' , 'D' , 'T' , 'L' , 'S' , 'B' } ;
Xstatic char c_dutch[] = { '@' ,'K' , 'D' , 'T' , 'L' , 'P' , 'O' } ;
Xstatic char c_russian[] = { '@' ,'K' , 'F' , 'D' , 'C' , 'K' , 'P' } ;
X
X
X/* translation tables */
Xchar *in_table;
X
X
Xchar * c_roque[] = { "O-O" , "O-O-O" , "o-o" , "o-o-o" , "0-0" , "0-0-0" };
X
X/* various notations for en passant */
X#define N_EP 2
Xchar * c_en_passant[] = { "ep" , "e.p." } ;
X
X
X/* notation for catch */
Xchar c_prise ='x';
X
X/* various comments */
Xchar * c_comments[] = { "+" , "++" ,
X "?" , "??", "!", "!!", "!?", "?!",
X "mate", "draw" };
X
X/* movement tables */
X/* move only */
X/* white pawn, move */
X#define NB_M_PAWN_MOVE_WD 2
Xstatic int m_pawn_move_wd [][2] = {
X { 1, 0}, {2, 0}
X};
X
X/* black pawn, move */
X#define NB_M_PAWN_MOVE_BD 2
Xstatic int m_pawn_move_bd [][2] = {
X {-1, 0}, {-2, 0}
X};
X
X/* TRICK = we have added the catching move at the end of
X the non catching ones; so in check_depl, we try first
X the non catching one and then the catching one.
X So, even if catching (x) is non indicated in the input,
X we succeed in guessing the move
X */
X/* white pawn, move */
X/*#define NB_M_PAWN_WD 2*/
X#define NB_M_PAWN_WD 4
Xstatic int m_pawn_wd [][2] = {
X { 1, 0}, {2, 0},
X/* catch... */
X { 1, 1}, { 1,-1}
X};
X
X/* white pawn, catch */
X#define NB_M_PAWN_WX 2
Xstatic int m_pawn_wx [][2] = {
X { 1, 1}, { 1,-1}
X};
X
X/* black pawn, move */
X/*#define NB_M_PAWN_BD 2*/
X#define NB_M_PAWN_BD 4
Xstatic int m_pawn_bd [][2] = {
X {-1, 0}, {-2, 0},
X/* catch... */
X {-1, 1}, {-1,-1}
X};
X
X/* black pawn, catch */
X#define NB_M_PAWN_BX 2
Xstatic int m_pawn_bx [][2] = {
X {-1, 1}, {-1,-1}
X};
X
X
X#define NB_M_KNIGHT 8
Xstatic int m_knight[][2] = {
X { 2, 1}, { 2,-1}, {-2, 1}, {-2,-1},
X { 1, 2}, { 1,-2}, {-1, 2}, {-1,-2}
X};
X
X#define NB_M_BISHOP 28
Xstatic int m_bishop[][2] = {
X { 7, 7}, {6, 6}, { 5, 5}, { 4, 4}, { 3, 3}, { 2, 2}, { 1, 1},
X { 7,-7}, { 6,-6}, { 5,-5}, { 4,-4}, { 3,-3}, { 2,-2}, { 1,-1},
X {-7,-7}, {-6,-6}, {-5,-5}, {-4,-4}, {-3,-3}, {-2,-2}, {-1,-1},
X {-7, 7}, {-6, 6}, {-5, 5}, {-4, 4}, {-3, 3}, {-2, 2}, {-1, 1}
X};
X
X#define NB_M_ROOK 28
Xstatic int m_rook[][2] = {
X { 7, 0}, { 6, 0}, { 5, 0}, { 4, 0}, { 3, 0}, { 2, 0}, { 1, 0},
X {-7, 0}, {-6, 0}, {-5, 0}, {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0},
X { 0, 7}, { 0, 6}, { 0, 5}, { 0, 4}, { 0, 3}, { 0, 2}, { 0, 1},
X { 0,-7}, { 0,-6}, { 0,-5}, { 0,-4}, { 0,-3}, { 0,-2}, { 0,-1}
X};
X
X#define NB_M_QUEEN 56
Xstatic int m_queen[][2] = {
X { 7, 7}, {6, 6}, { 5, 5}, { 4, 4}, { 3, 3}, { 2, 2}, { 1, 1},
X { 7,-7}, { 6,-6}, { 5,-5}, { 4,-4}, { 3,-3}, { 2,-2}, { 1,-1},
X {-7,-7}, {-6,-6}, {-5,-5}, {-4,-4}, {-3,-3}, {-2,-2}, {-1,-1},
X {-7, 7}, {-6, 6}, {-5, 5}, {-4, 4}, {-3, 3}, {-2, 2}, {-1, 1},
X { 7, 0}, { 6, 0}, { 5, 0}, { 4, 0}, { 3, 0}, { 2, 0}, { 1, 0},
X {-7, 0}, {-6, 0}, {-5, 0}, {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0},
X { 0, 7}, { 0, 6}, { 0, 5}, { 0, 4}, { 0, 3}, { 0, 2}, { 0, 1},
X { 0,-7}, { 0,-6}, { 0,-5}, { 0,-4}, { 0,-3}, { 0,-2}, { 0,-1}
X};
X
X#define NB_M_KING 8
Xstatic int m_king[][2] = {
X { 1, 1}, { 1, 0}, { 1,-1},
X {-1, 1}, {-1, 0}, {-1,-1},
X { 0, 1}, { 0, -1}
X};
X
X
X/* I/O */
XFILE * infile ;
XFILE * fhelp;
X
Xstatic char * t_output[] =
X{ "ascii", "postscript", "tex", "roff", "xchess", "gnu" };
X
X
X/* ---------- automata definitions --------- */
X/* table for syntaxic analysis of move */
X
X#define FINAL 10
X#define TML FINAL /* terminal state */
X#define NBETAT 11
X#define NBCLAS 8
X
X/* successor of state */
Xstatic int transit[NBETAT][NBCLAS] = {
X/* P a-h 1-8 - x = \0 ? */
X/*( 0 1 2 3 4 5 6 7)*/
X { 1, 2, -1, -1, -1, -1, -1, -1 }, /* etat 0 */
X { -1, 2, -1, -1, 4, -1, -1, -1 }, /* etat 1 */
X { -1, 6, 3, 4, 4, 8,TML,TML }, /* etat 2 */
X { -1, 6, -1, 4, 4, 8,TML,TML }, /* etat 3 */
X { 5, 6, -1, -1, -1, -1, -1, -1 }, /* etat 4 */
X { -1, 6, -1, -1, -1, -1, -1, -1 }, /* etat 5 */
X { -1, -1, 7, -1, -1, -1, -1, -1 }, /* etat 6 */
X { -1, -1, -1, -1, -1, 8,TML,TML }, /* etat 7 */
X { 9, -1, -1, -1, -1, -1, -1, -1 }, /* etat 8 */
X { -1, -1, -1, -1, -1, -1,TML,TML }, /* etat 9 */
X { -1, -1, -1, -1, -1, -1, -1, -1 } /* etat 10 == terminal */
X};
X
X/* actions to do */
Xstatic int action[NBETAT][NBCLAS] = {
X/* P a-h 1-8 - x = \0 ? */
X { 1, 2, -1, -1, -1, -1, -1, -1 }, /* etat 0 */
X { -1, 2, -1, -1, 10, -1, -1, -1 }, /* etat 1 */
X { -1, 13, 3, 4, 5, 14, 6, 7 }, /* etat 2 */
X { -1, 13, -1, 4, 5, 14, 6, 7 }, /* etat 3 */
X { 1, 2, -1, -1, -1, -1, -1, -1 }, /* etat 4 */
X { -1, 2, -1, -1, -1, -1, -1, -1 }, /* etat 5 */
X { -1, -1, 3, -1, -1, -1, -1, -1 }, /* etat 6 */
X { -1, -1, -1, -1, -1, 14, 8, 9 }, /* etat 7 */
X { 15, -1, -1, -1, -1, -1, -1, -1 }, /* etat 8 */
X { -1, -1, -1, -1, -1, -1, 17, 17 }, /* etat 9 */
X { -1, -1, -1, -1, -1, -1, -1, -1 } /* etat 10 */
X};
X
X
X
X/* current game
X the name "tos" means "top of stack"
X */
Xstatic game * tos = GULL ;
X
X/* array to see the king is in check
X use in checkroque()
X */
X
X
X/* booleen d'erreur */
Xint error_flag = FALSE;
X
X
X/* move to display board */
Xstatic int count = 0 ;
X
X
Xstatic int move_to_display[NB_MOVE_TO_DISP] ;
Xstatic int nb_move_to_dsp = 0;
Xstatic int stop_at_display = FALSE;
X
X/* variable holding current move */
Xstatic depl * m = MULL ;
X
X/* current move, used by the parser */
Xstatic int curpiece, curcol, curlig ;
Xstatic int curdigit, curmove;
X
Xstatic format * dr;
X
Xstatic int driver; /* driver type, ie gnu, ascii ... */
X
X#define setboard(A,I,J,P,C) ({(A)->board[(I)][(J)] = (P) ; \
X (A)->color[(I)][(J)] = (C);})
X#define clsboard(A,I,J,P,C) ({(A)->board[(I)][(J)] = VOID ; \
X (A)->color[(I)][(J)] = VOID; }))
X
X/* --------------------------- code part --------------------- */
X
X
Xstatic int ispiece(c)
X char c;
X{
X register int i;
X
X for ( i = 0 ; (i < NUMPIECES) && (c != in_table[i]) ; i++ ) ;
X /*(void) fprintf(stdout, "piece %d %c\n" , i , c);*/
X return(i<NUMPIECES);
X}
X
X
Xstatic int piece(c)
X char c ;
X{
X register int i;
X
X for ( i = 0 ; (i < NUMPIECES) && (c != in_table[i]) ; i++ ) ;
X if ( i== NUMPIECES)
X i = PAWN ;
X return(i);
X}
X
X/* this function return yhe # entry of a keyword in a given table.
X if key is not present, it returns the default value
X */
Xstatic int find_keyword(tab, nbentry,defaut,key)
X char * tab[];
X int nbentry;
X int defaut;
X char *key;
X{
X int i ;
X
X for(i=0; (i< nbentry) ;i++)
X if (strcmp(tab[i],key)==0)
X return(i);
X
X /* we failed to find the keyword */
X (void) fprintf (stderr, "unknow keyword %s in this context\n",key);
X return(defaut);
X}
X
X/* ---------- board management function ------------- */
X
Xvoid clear_board(g)
X game *g;
X{
X register int i,j;
X
X for (i=0; i < 10; i++ )
X for (j=0 ; j< 10 ; j++) {
X g->board[i][j] = VOID;
X g->color[i][j] = VOID;
X }
X}
X
Xgame * new_board()
X{
X game * tmp;
X int i;
X
X tmp = (game *) malloc (sizeof(game));
X ALLOCP(tmp);
X /*for (i=0; i < ((sizeof (game))/ sizeof (int)) ; i++)
X ((int *) tmp)[i] = 0;*/
X return(tmp);
X}
X
Xvoid init_board(tgm)
X game * tgm;
X{
X register int i,j;
X
X clear_board(tgm);
X
X for (i=1; i< 9 ; i=i+7) {
X tgm->board[i][1]= tgm->board[i][8] = ROOK ;
X tgm->board[i][2]= tgm->board[i][7] = KNIGHT ;
X tgm->board[i][3]= tgm->board[i][6] = BISHOP ;
X tgm->board[i][4]= QUEEN;
X tgm->board[i][5]= KING;
X }
X for (i=2; i< 8 ; i=i+5)
X for (j=1; j <=8 ; j++)
X tgm->board[i][j] = PAWN;
X
X for (i=1; i <=2; i++)
X for (j=1; j <=8 ; j++) {
X tgm->color[i][j] = WHITE;
X tgm->color[i+6][j] = BLACK ;
X }
X}
X
Xdepl * new_move()
X{
X depl * tmp;
X int i;
X
X tmp = (depl *) malloc (sizeof(depl));
X ALLOCP(tmp);
X /*for (i=0; i < ((sizeof (depl))/ sizeof (int)) ; i++)
X ((int *) tmp)[i] = 0;*/
X return(tmp);
X}
X
X
Xvoid init_move(m)
X depl *m;
X{
X m->move= 1 ;
X m->whiteturn = TRUE ;
X}
X
X/* ----------- semantic evaluation of move ----------- */
X/* check if position lies within the board
X */
Xint in_board(l,c)
X int l,c;
X{
X return ((c >= 1) && (c <= 8) && (l >= 1) && (l <= 8));
X}
X
X/* check that the path from pos1 to pos2 is free
X */
Xint path_free(l1, c1, l2, c2)
Xint l1,c1, l2, c2;
X{
X int li = 1 ;
X int ci = 1 ;
X int lig, col;
X
X
X li = SIGN(l2-l1);
X ci = SIGN(c2-c1);
X
X
X if ( c1 == c2 ) {
X col = c1;
X for (lig = l1 +li; lig != l2 ; lig +=li)
X if (tos->board[lig][col] != VOID)
X return (FALSE);
X return(TRUE);
X }
X
X if ( l1 == l2) {
X lig = l1 ;
X for (col = c1 + ci; col != c2 ; col +=ci)
X if (tos->board[lig][col] != VOID)
X return (FALSE);
X return(TRUE);
X }
X
X for (lig = l1+li,col =c1+ci; (lig!=l2) && (col!=c2); lig+=li, col+= ci)
X if (tos->board[lig][col] != VOID) {
X return (FALSE);
X }
X return(TRUE);
X}
X
X/* check roque is possible */
Xint check_roque()
X{
X int lig, col ;
X
X if (m->whiteturn)
X lig = 1 ;
X else
X lig =8;
X if (m->type == GRANDROQUE)
X for (col = 2; col < 5 ; col++)
X if (tos->board[lig][col] != VOID)
X return(FALSE);
X if (m->type == PETITROQUE)
X for (col = 6; col < 7 ; col++)
X if (tos->board[lig][col] != VOID)
X return(FALSE);
X if (m->is_check[CURCOLOR(m)])
X return(FALSE);
X return(TRUE);
X}
X
X/* check -- or guess -- where a given piece come */
Xint guess_piece() {return(tos->board[m->fromlig][m->fromcol]); }
X
X/* try to guess the move -- low-level function */
Xint guess_depl(nb, tab, pl1, pc1, l2,c2,path)
X int nb;
X int tab[][2];
X int *pl1, *pc1;
X int l2,c2;
X int path;
X{
X int i;
X int c,l;
X
X for (i=0; i< nb; i++ ) {
X l = l2 - tab[i][0];
X c = c2 - tab[i][1];
X if (in_board(l,c))
X if ((tos->board[l][c] == m->piece) &&
X (tos->color[l][c] == CURCOLOR(m)) &&
X ( !path || (path && path_free(l,c, l2, c2))) &&
X ( ((*pl1) == 0) || ((*pl1) == l) ) &&
X ( ((*pc1) == 0) || ((*pc1) == c) ) )
X {
X *pl1 = l;
X *pc1 = c;
X return(TRUE);
X }
X }
X return(FALSE);
X}
X
X/* check for ambiguitey in a move
X used in ouptut function: the piece had beenm already moved and
X if we guess another move, there is an ambiguity
X */
Xint ambiguity(frompiece, l2, c2)
X int frompiece, l2, c2 ;
X{
X int l1 = 0 ;
X int c1 = 0 ;
X
X switch(frompiece) {
X case PAWN:
X if (m->type == PRISE) {
X if (m->whiteturn)
X return(guess_depl(NB_M_PAWN_WX, m_pawn_wx, &l1,&c1, l2,c2, FALSE));
X else
X return(guess_depl(NB_M_PAWN_BX, m_pawn_bx, &l1,&c1, l2,c2, FALSE));
X } else {
X if (m->whiteturn)
X return(guess_depl(NB_M_PAWN_MOVE_WD, m_pawn_move_wd,
X &l1,&c1, l2,c2, FALSE));
X else
X return(guess_depl(NB_M_PAWN_MOVE_BD, m_pawn_move_bd,
X &l1,&c1, l2,c2, FALSE));
X }
X /* break; */
X case KNIGHT:
X return(guess_depl(NB_M_KNIGHT, m_knight, &l1,&c1, l2,c2, FALSE));
X /* break; */
X case BISHOP:
X return(guess_depl(NB_M_BISHOP, m_bishop, &l1,&c1, l2,c2, TRUE));
X /* break; */
X case ROOK:
X return(guess_depl(NB_M_ROOK, m_rook, &l1,&c1, l2,c2, TRUE));
X /* break; */
X case QUEEN:
X return(guess_depl(NB_M_QUEEN, m_queen, &l1,&c1, l2,c2, TRUE));
X /* break; */
X case KING:
X return(guess_depl(NB_M_KING, m_king, &l1,&c1, l2,c2, TRUE));
X /* break; */
X default:
X break;
X }
X return(TRUE);
X}
X
Xint check_move(m)
X depl * m;
X{
X int l1,c1,l2,c2,l;
X int tmp; /* tmp boolean */
X
X l1 = m->fromlig;
X c1 = m->fromcol;
X l2 = m->tolig;
X c2 = m->tocol;
X
X if ((m->type == GRANDROQUE) || (m->type == PETITROQUE))
X return(check_roque());
X
X if ((tos->board[l1][c1] != m->piece)||
X (tos->color[l1][c1] != CURCOLOR(m))){
X printf("==%d\n",tos->board[l1][c1]);
X error ((stderr,"from position and piece not correct\n"));
X return(FALSE);
X }
X
X /* if prise === FALSE, we must not take a piece */
X if (tos->board[l2][c2] != VOID
X && (m->type != PRISE) && (m->type != PROM_ET_PRISE)) {
X (void) fprintf(stderr,"catching not indicated at move %d\n",m->move);
X return(FALSE);
X }
X
X /* prendre une de ses propres pieces */
X if (tos->color[l2][c2] == tos->color[l1][c1] && m->prise) {
X (void) fprintf(stderr,"attempt to catch same color piece at move %d\n",
X m->move);
X return(FALSE);
X }
X
X /* we check if the move is a possible one for the piece
X */
X
X switch(m->piece) {
X case PAWN:
X if (m->prise) {
X if (m->whiteturn)
X tmp = guess_depl(NB_M_PAWN_WX, m_pawn_wx, &l1,&c1, l2,c2, FALSE);
X else
X tmp = guess_depl(NB_M_PAWN_BX, m_pawn_bx, &l1,&c1, l2,c2, FALSE);
X } else {
X if (m->whiteturn)
X tmp = guess_depl(NB_M_PAWN_WD, m_pawn_wd, &l1,&c1, l2,c2, FALSE);
X else
X tmp = guess_depl(NB_M_PAWN_BD, m_pawn_bd, &l1,&c1, l2,c2, FALSE);
X }
X /* is it a "prise en passant " */
X if ((c1 != c2) && (tos->board[l2][c2] == VOID)
X && (tos->board[l1][c2] == PAWN)) {
X m->type = EN_PASSANT ;
X l = l1 + (l2 - l1)/2;
X /* we must perform here the "en passant" test */
X tos->board[l1][c2] = VOID ;
X tos->color[l1][c2] = VOID ;
X tmp = TRUE;
X }
X return(tmp);
X /* break; */
X case KNIGHT:
X return(guess_depl(NB_M_KNIGHT, m_knight, &l1,&c1, l2,c2, FALSE));
X /* break; */
X case BISHOP:
X return(guess_depl(NB_M_BISHOP, m_bishop, &l1,&c1, l2,c2, TRUE));
X /* break; */
X case ROOK:
X return(guess_depl(NB_M_ROOK, m_rook, &l1,&c1, l2,c2, TRUE));
X /* break; */
X case QUEEN:
X return(guess_depl(NB_M_QUEEN, m_queen, &l1,&c1, l2,c2, TRUE));
X /* break; */
X case KING:
X return(guess_depl(NB_M_KING, m_king, &l1,&c1, l2,c2, TRUE));
X /* break; */
X default:
X break;
X }
X
X return(TRUE);
X}
X
X/* try to guess the move -- used for shortened notation
X */
Xint guess_move()
X{
X int l1,c1,l2,c2;
X
X if ((m->type == GRANDROQUE) || (m->type == PETITROQUE))
X return(TRUE);
X
X l1 = m->fromlig ;
X c1 = m->fromcol ;
X l2 = m->tolig;
X c2 = m->tocol;
X
X switch(m->piece) {
X case PAWN:
X if (m->prise) {
X if (m->whiteturn)
X (void) guess_depl(NB_M_PAWN_WX, m_pawn_wx, &l1,&c1, l2,c2, FALSE);
X else
X (void) guess_depl(NB_M_PAWN_BX, m_pawn_bx, &l1,&c1, l2,c2, FALSE);
X } else {
X if (m->whiteturn)
X (void) guess_depl(NB_M_PAWN_WD, m_pawn_wd, &l1,&c1, l2,c2, FALSE);
X else
X (void) guess_depl(NB_M_PAWN_BD, m_pawn_bd, &l1,&c1, l2,c2, FALSE);
X }
X break;
X case KNIGHT:
X (void) guess_depl(NB_M_KNIGHT, m_knight, &l1,&c1, l2,c2, FALSE);
X break;
X case BISHOP:
X (void) guess_depl(NB_M_BISHOP, m_bishop, &l1,&c1, l2,c2, TRUE);
X break;
X case ROOK:
X (void) guess_depl(NB_M_ROOK, m_rook, &l1,&c1, l2,c2, TRUE);
X break;
X case QUEEN:
X (void) guess_depl(NB_M_QUEEN, m_queen, &l1,&c1, l2,c2, TRUE);
X break;
X case KING:
X (void) guess_depl(NB_M_KING, m_king, &l1,&c1, l2,c2, TRUE);
X break;
X default:
X break;
X }
X
X if ((l1 == 0) || (c1 == 0)) {
X if (m->whiteturn)
X error((stderr,"unable to guess move %d white (%d)\n",
X m->move,m->piece));
X else
X error((stderr,"unable to guess move %d black (%d)\n",
X m->move,m->piece));
X return(FALSE);
X } else {
X m->fromcol = c1;
X m->fromlig = l1;
X return(TRUE);
X }
X}
X
X/* --------------- execution of move ----------------- */
X
X/* clear a position */
Xint clear_pos(lig,col)
X int lig;
X int col;
X{
X tos->board[lig][col] = VOID ;
X tos->color[lig][col] = VOID ;
X return(TRUE);
X}
X
X/* configure the board */
Xint configure()
X{
X if (configuring) {
X if (m->piece == VOID)
X m->piece = PAWN ;
X tos->board[m->tolig][m->tocol] = m->piece ;
X tos->color[m->tolig][m->tocol] = configside ;
X }
X return(TRUE);
X}
X
X/* execute a move, no checking */
Xint execute_move()
X{
X register int i;
X
X if (m->piece == VOID )
X m->piece = PAWN;
X
X if ((m->fromlig == 0) || (m->fromcol == 0))
X (void) guess_move();
X
X /* supply to the -- maybe -- deficiency of input notation
X */
X if ((m->fromlig !=0) || (m->fromcol != 0))
X m->piece = tos->board[m->fromlig][m->fromcol];
X
X if (tos->board[m->tolig][m->tocol] != VOID) {
X m->type = PRISE;
X m->prise = tos->board[m->tolig][m->tocol] ;
X }
X
X if (!check_move(m)) {
X if (m->whiteturn)
X error((stderr,"white move %d illegal\n",m->move));
X else
X error((stderr,"black move %d illegal\n",m->move));
X }
X
X if (m->type == PETITROQUE) {
X if (m->whiteturn)
X curlig = 1 ;
X else
X curlig = 8 ;
X tos->board[curlig][7] = KING;
X tos->board[curlig][6] = ROOK;
X tos->color[curlig][7] = tos->color[curlig][5] ;
X tos->color[curlig][6] = tos->color[curlig][5] ;
X (void) clear_pos(curlig, 5);
X (void) clear_pos(curlig, 8);
X }
X if (m->type == GRANDROQUE) {
X if (m->whiteturn)
X curlig = 1 ;
X else
X curlig = 8 ;
X tos->board[curlig][3] = KING;
X tos->board[curlig][4] = ROOK;
X tos->color[curlig][3] = tos->color[curlig][5] ;
X tos->color[curlig][4] = tos->color[curlig][5] ;
X (void) clear_pos(curlig, 5);
X (void) clear_pos(curlig, 1);
X }
X
X
X if (!(m->type == GRANDROQUE) || (m->type == PETITROQUE)) {
X if (m->piece == VOID)
X m->piece = tos->board[m->fromlig][m->fromcol];
X /*if (m->topiece == VOID)
X m->topiece = tos->board[m->fromlig][m->fromcol];*/
X tos->board[m->tolig][m->tocol] = tos->board[m->fromlig][m->fromcol];
X tos->color[m->tolig][m->tocol] = tos->color[m->fromlig][m->fromcol];
X (void) clear_pos(m->fromlig,m->fromcol);
X }
X
X if ((m->type == PROMOTION) || (m->type == PROM_ET_PRISE))
X tos->board[m->tolig][m->tocol] = m->promotion ;
X
X output_move(dr,m);
X
X if (error_flag) {
X (void) fprintf(dr->outfile, "\nlast position encountered:\n");
X output_board(dr,tos);
X close_files();
X exit(0);
X }
X
X /* do we need to display the move ? */
X if (nb_move_to_dsp > 0) {
X for (i=0; i < nb_move_to_dsp; i++)
X if (m->move == (move_to_display[i] ) && !m->whiteturn ) {
X output_board(dr,tos);
X if (stop_at_display) {
X output_end(dr);
X close_files();
X exit(0);
X }
X }
X }
X
X return(TRUE);
X}
X
X/* ------------------ automata ----------------------- */
X
X/* categorise the input for the automata */
Xint typechar(c)
X char c;
X{
X if (ispiece(c))
X return(0);
X if ((c >= 'a') && ( c <= 'h'))
X return(1);
X if ((c >= '1') && ( c <= '8'))
X return(2);
X if ( c== '-' )
X return(3);
X if ((c == 'x') || (c == 'X' ))
X return(4);
X if (c == '=' )
X return(5);
X if (c == '\0' )
X return(6);
X return(7);
X}
X
X
X/* execute the actions decided by the automata */
Xint execute(num,c)
X int num;
X char c;
X{
X switch (num) {
X case 1: /* set cur piece */
X curpiece = piece(c);
X break;
X case 2: /* set cur col */
X curcol = lettertocol(c);
X break;
X case 3: /* set cur lig */
X curlig = lettertolig(c);
X break;
X case 4: /* from = cur ; prise = false */
X m->piece = curpiece ;
X m->fromcol = curcol ;
X m->fromlig = curlig;
X /*m->topiece = curpiece;*/
X break;
X case 5: /* from = cur ; prise = true */
X m->piece = curpiece ;
X m->fromcol = curcol ;
X m->fromlig = curlig;
X m->type = PRISE ;
X m->prise = curpiece;
X break;
X case 6: /* to = cur ; guess from */
X case 7: /* to = cur ; guess from ; parse remaining token */
X m->piece = curpiece ;
X m->tocol = curcol;
X m->tolig = curlig ;
X
X /*m->topiece = curpiece ; /* ? */
X
X if (configuring)
X (void) configure();
X else {
X (void) execute_move();
X m->whiteturn = !m->whiteturn ;
X if (m->whiteturn) m->move++ ;
X }
X break;
X case 8: /* to = cur */
X case 9: /* to = cur */
X m->tocol = curcol;
X m->tolig = curlig ;
X /*m->topiece = curpiece ;*/
X
X if (configuring)
X (void) configure();
X else {
X (void) execute_move();
X m->whiteturn = !m->whiteturn ;
X if (m->whiteturn) m->move++ ;
X }
X break;
X case 10: /* piece = cur piece ; prise = true */
X /* later : guess from position */
X m->piece = curpiece ;
X m->type = PRISE ;
X break;
X case 11: /* grand roque */
X case 12: /* petit roque */
X
X (void) execute_move();
X
X m->whiteturn = !m->whiteturn ;
X if (m->whiteturn) m->move++ ;
X break;
X case 13: /* case of simpliest algebraic notation ;
X only e2e4 : this is the transition from e2 to e4
X also the case of move such as Nge2
X from =cur; prise = FALSE;
X also:
X curcol = ...
X */
X m->piece = curpiece ;
X m->fromcol = curcol ;
X m->fromlig = curlig;
X /*m->topiece = curpiece;*/
X m->type = MOVE;
X curcol = lettertocol(c);
X case 14: /* promotion, the "=" */
X break;
X case 15: /* promotion, the piece name */
X /* to = cur ; guess from */
X case 16:
X /* to = cur */
X
X m->tocol = curcol;
X m->tolig = curlig ;
X /*m->topiece = curpiece ;*/
X
X if (m->type == PRISE )
X m->type = PROM_ET_PRISE ;
X else
X m->type = PROMOTION ;
X m->promotion = curpiece = piece(c) ;
X
X break;
X case 17: /* execute move for promotion */
X (void) execute_move();
X
X m->whiteturn = !m->whiteturn ;
X if (m->whiteturn) m->move++ ;
X break;
X case -1:
X break;
X default:
X break;
X }
X return(TRUE);
X}
X
Xint parse_number(token)
X char *token;
X{
X int curmove = 0 ;
X int i;
X
X /* check coherency with internal numbering */
X i = 0;
X while (isdigit(token[i])) {
X curmove = curmove * 10 + ((int) token[i++] - (int) '0' );
X }
X if (curmove != m->move)
X (void) fprintf(stderr,"problem in move numbering: %d vs %d\n",
X m->move, curmove);
X return(TRUE);
X}
X
Xint parse_keyword(token)
X char *token;
X{
X char c;
X
X switch (find_keyword(keywords, NBKEYWORD, KNULL, token)) {
X case START:
X configuring = FALSE;
X m->move = 1;
X m->whiteturn = TRUE;
X break;
X case CLEAR:
X clear_board(tos);
X break;
X case SHOWBOARD:
X output_board(dr,tos);
X break;
X case TOWHITE:
X m->move = 1;
X m->whiteturn = TRUE;
X break;
X case TOBLACK:
X m->move = 1;
X m->whiteturn = FALSE;
X break;
X case CONFIGWH:
X configuring = TRUE ;
X configside = WHITE;
X break;
X case CONFIGBL:
X configuring = TRUE ;
X configside = BLACK;
X break;
X case DEFAULTP:
X init_board(tos);
X break;
X case SPECIAL: /* all input, up to \n is copied to output */
X while ((( c = getc(infile)) != EOF) && (c != '\n'))
X (void) putc (c,dr->outfile);
X putc ('\n', dr->outfile);
X break;
X case KNULL:
X default:
X break;
X }
X return(TRUE);
X}
X
Xint parse_roque(token)
X char * token;
X{
X int i;
X
X for (i=0; i < NBROQUE && (strcmp(c_roque[i],token)!=0); i++) ;
X if ( i < NBROQUE ) {
X if (strlen(token) == 3) {
X m->type = PETITROQUE ;
X (void) execute(12,DUMMYCHAR);
X } else {
X m->type = GRANDROQUE ;
X (void) execute(11,DUMMYCHAR);
X }
X /*(void) fprintf(stderr,"ROQUE\n");*/
X return(TRUE);
X }
X
X return(FALSE);
X}
X
Xint parse_move(token)
X char *token;
X{
X register int i;
X int correcte = FALSE ;
X int erreursyntaxe = FALSE ;
X int etat =0;
X int code;
X
X i=0;
X while ( !correcte && !erreursyntaxe ) {
X code = typechar(token[i]);
X (void) execute(action[etat][code],token[i]);
X etat = transit[etat][code] ;
X if (etat == -1)
X erreursyntaxe = TRUE;
X if (etat == FINAL)
X correcte = TRUE ;
X i++;
X }
X if (erreursyntaxe) {
X (void) fprintf(stderr, "no comprende, senor: %s\n",token);
X return(FALSE);
X }
X if (correcte) {
X /*(void) fprintf(stderr, "ia panimaiou, davai\n");*/
X }
X return(TRUE);
X}
X
Xvoid init_parse(m)
X depl * m ;
X{
X int i;
X
X /* global position and piece variable initialised to 0
X */
X /* move and whiteturn unchanged */
X
X m->type = MOVE ;
X
X curpiece = m->piece = VOID ;
X curcol = m->tocol = m->fromcol = 0;
X curlig = m->tolig = m->fromlig = 0;
X
X m->promotion = VOID;
X m->prise = VOID;
X
X for (i=0; i< 3; i++)
X m->is_check[i] = FALSE ;
X curdigit = curmove = 0;
X}
X
X/* ------------------- top routines -------------------- */
X
X/* cette fonction analyse les arguments de la ligne de commande
X */
Xint parse_options(argc,argv)
X int argc;
X char * argv[];
X{
X int narg =1 ;
X int i;
X register int c;
X char cp[132];
X char chaine[MAXTOKLEN];
X
X infile = stdin;
X dr->outfile = stdout;
X nb_move_to_dsp = 0;
X
X while (narg < argc ) {
X (void) strcpy (cp,argv[narg]);
X switch (cp[0]) {
X case '-' :
X switch (cp[1]) {
X case 'f' : /* from langage */
X if ((narg+1) >= argc )
X fatal((stderr,"missing argument to %s option",cp));
X narg++ ;
X in_language = find_keyword (t_language, NBLANGUAGE,
X DEFAULT_INPUT_LANGUAGE,
X argv[narg]);
X break;
X case 't' : /* to langage */
X if ((narg+1) >= argc )
X fatal((stderr,"missing argument to %s option",cp));
X narg++ ;
X out_language = find_keyword (t_language, NBLANGUAGE,
X DEFAULT_OUTPUT_LANGUAGE,
X argv[narg]);
X break;
X case 'o' : /* next arg is output file */
X narg++ ;
X if ((dr->outfile = fopen (argv[narg],"w+")) == NULL) {
X (void) fprintf (stderr,"can't open %s output file\n",argv[narg]);
X (void) fprintf (stderr,"assume stdout for output\n");
X }
X break;
X case 'e':
X if ((narg+1) >= argc )
X fatal((stderr,"missing argument to %s option",cp));
X narg++ ;
X
X i=0;
X nb_move_to_dsp = 0;
X move_to_display[nb_move_to_dsp] = 0;
X while (isdigit(argv[narg][i])) {
X move_to_display[nb_move_to_dsp] =
X ((int) argv[narg][i] - (int) '0')
X + move_to_display[nb_move_to_dsp] * 10;
X i++;
X }
X nb_move_to_dsp++;
X stop_at_display = TRUE;
X break;
X case 'c':
X if ((narg+1) >= argc )
X fatal((stderr,"missing argument to %s option",cp));
X narg++ ;
X
X i=0;
X while (isdigit(argv[narg][i])) {
X move_to_display[nb_move_to_dsp] = 0;
X while (isdigit(argv[narg][i])) {
X move_to_display[nb_move_to_dsp] =
X ((int) argv[narg][i] - (int) '0')
X + move_to_display[nb_move_to_dsp] * 10;
X i++;
X }
X nb_move_to_dsp++;
X
X if (nb_move_to_dsp > NB_MOVE_TO_DISP)
X fatal((stderr,"max. number of move to display exceeded"));
X
X /* process next number */
X if (argv[narg][i] == ',')
X i++;
X }
X break;
X case 'a': /* algebraic output */
X dr->output_move_format = ALGEBRAIC;
X break;
X case 's': /* shortened output */
X dr->output_move_format = SHORTENED;
X break;
X case 'b': /* display only the board, no move */
X dr->only_board = TRUE;
X break;
X case 'd': /* output driver */
X if ((narg+1) >= argc )
X fatal((stderr,"missing argument to %s option",cp));
X narg++ ;
X driver = find_keyword(t_output, NB_DRIVER, DEFAULT_DRIVER,
X argv[narg]);
X break;
X case 'h': /* help file */
X (void) strcpy(chaine,LIB_DIR);
X if ((fhelp = fopen(strcat(chaine,HELP_FILE),"r")) == NULL)
X fatal((stderr,"Can't find help file.\n"));
X else {
X while ((c = getc(fhelp)) != EOF)
X (void) fputc(c,stderr);
X (void) fclose(fhelp);
X exit(0);
X }
X break;
X default:
X error((stderr,"unknown command line options %s\n",cp));
X break;
X }
X break;
X default: /* assume this is the input file */
X if ((infile = fopen (cp,"r")) == NULL)
X fatal((stderr,"can't open %s input file\n",cp));
X }
X narg++;
X } /* process next arg */
X return(argc);
X}
X
Xvoid close_files()
X{
X if (infile != stdin )
X (void) fclose(infile);
X if (dr->outfile != stdout )
X (void) fclose(dr->outfile);
X}
X
Xint associe_traduction (table, langage)
Xchar ** table;
Xint langage ;
X{
X switch (langage) {
X case FRENCH :
X *table = c_french ;
X break;
X case ENGLISH:
X *table = c_english ;
X break;
X case ITALIAN:
X *table = c_italian ;
X break;
X case SPANISH:
X *table = c_spanish ;
X break;
X case GERMAN:
X *table = c_german ;
X break;
X case DUTCH:
X *table = c_dutch ;
X break;
X case RUSSIAN:
X (void) fprintf(stderr,"russian not yet implemented\n");
X *table = c_russian ;
X break;
X default:
X error((stderr,"unknown langage\n"));
X }
X return(langage);
X}
X
X/* ------------- main --------------------- */
X
Xmain(argc,argv)
X int argc;
X char * argv[];
X{
X (void) fprintf(stderr,"%s\n",version_string);
X
X /* allocation of driver descriptor */
X dr = new_driver();
X
X /* default configuration */
X init_driver(dr,DEFAULT_DRIVER);
X (void) associe_traduction(&in_table, DEFAULT_INPUT_LANGUAGE );
X (void) associe_traduction(&(dr->out_table), DEFAULT_OUTPUT_LANGUAGE);
X
X (void) parse_options(argc,argv);
X
X (void) associe_traduction (&in_table, in_language);
X (void) associe_traduction (&(dr->out_table), out_language);
X
X /* assoc driver */
X init_driver(dr,driver);
X
X configuring = FALSE;
X configside = VOID;
X
X /* initialise output file */
X output_init(dr);
X
X if (error_flag)
X fatal((stderr,"too many errors"));
X
X /* allocation of move descriptor */
X m = new_move();
X init_move(m);
X
X /* allocation of board descriptor */
X tos = new_board();
X init_board(tos);
X
X /*output_board(dr,tos);*/
X
X while (nexttoken()) {
X /*(void) fprintf(stdout,"%s%\n", curtok);*/
X init_parse(m);
X (void) parsetoken();
X }
X if ((count == 0) && !error_flag)
X output_board(dr,tos);
X
X if (error_flag) {
X error((stderr,"last valid position:\n"));
X output_board(dr,tos);
X fatal((stderr,"too many errors"));
X }
X
X /* terminates output files */
X output_end(dr);
X
X /* close files */
X close_files();
X
X /* exit properly */
X#ifdef TURBOC
X return(TRUE);
X#else
X exit(0);
X#endif
X}
END_OF_FILE
if test 31006 -ne `wc -c <'notation.c'`; then
echo shar: \"'notation.c'\" unpacked with wrong size!
fi
# end of 'notation.c'
fi
echo shar: End of archive 3 \(of 3\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 3 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Henry Thomas - IRISA - E-mail: Henry.Thomas at irisa.fr
Campus Universitaire de Beaulieu - Phone: (+33)99 36 20 00 +549
35042 RENNES CEDEX FRANCE - Fax: (+33)99 38 38 32 Telex: UNIRISA 950473F
Telex Atlas X400: /X121=842950473/@atlas.fr, Fax:/X121=200099383832/@atlas.fr
--
... Words, and the words of men, flicker and flutter and beat
Warning, sorrow and gain, salutations and mirth... R. Kipling
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent at sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent at uunet.uu.net.
More information about the Comp.sources.misc
mailing list