home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR2
/
CBUFF09.ZIP
/
SRC.ZIP
/
GAME.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-16
|
31KB
|
998 lines
/* $Id: game.c,v 1.1.1.1 1993/06/21 11:11:59 anjo Exp $
*
* File game.c
* Part of ChessBase utilities file format (CBUFF)
* Author Anjo Anjewierden, anjo@swi.psy.uva.nl
* Purpose Representation of a chess game
* Works with GNU CC 2.4.5
*
* Notice Copyright (c) 1993 Anjo Anjewierden
*
* History 09/06/93 (Created)
* 03/11/93 (Last modified)
*/
/*------------------------------------------------------------
* Directives
*------------------------------------------------------------*/
#include "cbuff.h"
/*------------------------------------------------------------
* Definitions
*------------------------------------------------------------*/
static void requireHeaderGame(Game);
static void requireMovesGame(Game);
/*------------------------------------------------------------
* Initialisation
*------------------------------------------------------------*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node newGame
@deftypefun Game newGame ()
Returns a new instance of a (chess) game structure. The instance
returned is initialised.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
Game
newGame()
{ Game g;
g = alloc(sizeof(struct game));
g->cbGame = NULL;
g->firstMove = NULL;
g->position = NULL;
resetGame(g);
return g;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node freeGame
@deftypefun void freeGame (Game @var{g})
Unallocates the game.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void
freeGame(Game g)
{ resetGame(g);
unalloc(g);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node resetGame
@deftypefun void resetGame (Game @var{g})
Resets the game such that it may be used to load another.
@code{resetGame} is conceptually identical to:
@example
freeGame(g);
g = newGame();
@end example
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void
resetGame(Game g)
{ if (g->firstMove)
{ freeMove(g->firstMove);
g->firstMove = NULL;
}
if (g->cbGame)
{ freeCbGame(g->cbGame);
g->cbGame = NULL;
}
if (g->position)
{ freePosition(g->position);
g->position = NULL;
}
g->number = 0L;
g->database = NULL;
g->flags = 0;
g->players[0] = '\0';
g->source[0] = '\0';
g->year = 0;
g->result = 0;
g->eloWhite = 0;
g->eloBlack = 0;
g->eco[0] = '\0';
g->moves = 0;
g->plies = 0;
g->place = NullString;
g->event = NullString;
g->annotator = NullString;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node initialiseGame
@deftypefun bool initialiseGame (Game @var{g}, long @var{number}, CBase @var{database})
Initialises a game to be read from an existing ChessBase database. The
@var{number} is the game number relative to the @var{database}.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
bool
initialiseGame(Game g, long number, CBase database)
{ if (g->flags & GAME_INIT_OK)
resetGame(g);
if (number < 1 || number > database->noGames)
{ setError(ERR_GAME_NUMBER_OUT_OF_RANGE);
return FALSE;
}
g->number = number;
g->database = database;
g->flags |= GAME_INIT_OK;
return TRUE;
}
/*------------------------------------------------------------
* Accessing game properties
*------------------------------------------------------------*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node flags2Bit6GameP
@deftypefun bool flags2Bit6GameP (Game @var{g})
Succeeds if bit 6 of the flags2 field of the game header is set. This
bit apparently decides on the character set being used, but is still a
slightly mysterious. At the moment, only games that this bit set print
all comments correctly.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
bool
flags2Bit6GameP(Game g)
{ return (g->flags & GAME_FLAGS2_BIT6 ? TRUE : FALSE);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node fullGameP
@deftypefun bool fullGameP (Game @var{g})
Succeeds if the game is a complete game (starting from the initial position),
and fails if a starting position is provided with the game.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
bool
fullGameP(Game g)
{ requireHeaderGame(g);
return (g->flags & GAME_INITIAL_POSITION ? TRUE : FALSE);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node deletedGameP
@deftypefun bool deletedGameP (Game @var{g})
Succeeds if the game has been logically deleted from the database. A
game is fysically deleted by the @file{cbfresh} utility provided with
ChessBase.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
bool
deletedGameP(Game g)
{ requireHeaderGame(g);
return (g->flags & GAME_DELETED ? TRUE : FALSE);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node markedGameP
@deftypefun bool markedGameP (Game @var{g})
Succeeds if the game has been marked in the database. The meaning of a
marked game is up to the user. It presumably means the game is more
interesting than the unmarked games in the database.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
bool
markedGameP(Game g)
{ requireHeaderGame(g);
return (g->flags & GAME_MARKED ? TRUE : FALSE);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node containsCommentsGameP
@deftypefun bool containsCommentsGameP (Game @var{g})
Succeeds if the game contains comments for at least one of the moves.
Examples of comments are ``@code{!!}'', ``@code{+-}'' and ``This is
a great move''.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
bool
containsCommentsGameP(Game g)
{ requireHeaderGame(g);
if (g->cbGame->commentLength)
return TRUE;
return FALSE;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node containsVariationsGameP
@deftypefun bool containsVariationsGameP (Game @var{g})
Succeeds if the game contains at least one variation.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
bool
containsVariationsGameP(Game g)
{ requireHeaderGame(g);
if (g->plies < g->cbGame->movesLength)
return TRUE;
return FALSE;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getPlayersGame
@deftypefun {char *} getPlayersGame (Game @var{g})
Returns the names of the players of the game. When the application
wants to manipulate the players, a copy of the @w{@code{char *}}
returned should be made.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char *
getPlayersGame(Game g)
{ requireHeaderGame(g);
return g->players;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getSourceGame
@deftypefun {char *} getSourceGame (Game @var{g})
Returns the names of the source of the game. When the application
wants to manipulate the source, a copy of the @w{@code{char *}}
returned should be made.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char *
getSourceGame(Game g)
{ requireHeaderGame(g);
return g->source;
}
char *
getPlaceGame(Game g)
{ requireHeaderGame(g);
return normalisePlace(g->source);
}
char *
getAnnotatorGame(Game g)
{ requireHeaderGame(g);
return g->annotator;
}
char *
getEventGame(Game g)
{ requireHeaderGame(g);
return g->event;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node containsPlayerNamesGameP
@deftypefun bool containsPlayerNamesGameP (Game @var{g})
Succeeds if the game contains the names of the players. The heuristic
is to check whether the players field contains at least one hyphen.
Note that some games may actually be an overview of a certain opening,
where the players field is used to name the opening.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
bool
containsPlayerNamesGameP(Game g)
{ requireHeaderGame(g);
if (strchr(g->players, '-'))
return TRUE;
return FALSE;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getWhiteGame
@deftypefun {char *} getWhiteGame (Game @var{g})
Returns the name of the player with the white pieces. The @w{@code{char
*}} is allocated statically. A return value of @code{NULL} means that
the information could not be extracted.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static bool
substituteHyphen(char *s, char *pattern)
{ char *t;
for (t=s; *t; t++)
{ if (strhead(t, pattern))
{ int l = strlen(pattern);
while (l--)
{ if (*t == '-')
*t = ' ';
t++;
}
return TRUE;
}
}
return FALSE;
}
char *
getWhiteGame(Game g)
{ static char white[MAX_NAME_SIZE+1];
char *s;
requireHeaderGame(g);
again:
s = strchr(g->players, '-');
if (s && s == strrchr(g->players, '-'))
{ *s = '\0';
strcpy(white, g->players);
*s = '-';
return normalisePlayer(white);
}
if (s && strrchr(g->players, '-')) /* At least two hyphens */
{
if (substituteHyphen(g->players, "Al-Khateeb")) goto again;
if (substituteHyphen(g->players, "Al-Mansouri")) goto again;
if (substituteHyphen(g->players, "Al-Modiahki")) goto again;
if (substituteHyphen(g->players, "Ana-L")) goto again;
if (substituteHyphen(g->players, "Ana-Maria")) goto again;
if (substituteHyphen(g->players, "Anna-Maria")) goto again;
if (substituteHyphen(g->players, "Anne-Marie")) goto again;
if (substituteHyphen(g->players, "Armel-David")) goto again;
if (substituteHyphen(g->players, "Astolfi-Perez")) goto again;
if (substituteHyphen(g->players, "Badea-Takacs")) goto again;
if (substituteHyphen(g->players, "Bazaj-Bocka")) goto again;
if (substituteHyphen(g->players, "Bert-Steffen")) goto again;
if (substituteHyphen(g->players, "Bos-Swiecik")) goto again;
if (substituteHyphen(g->players, "Brilla-Banfalvi")) goto again;
if (substituteHyphen(g->players, "Brinck-Claussen")) goto again;
if (substituteHyphen(g->players, "Carl-Magnus")) goto again;
if (substituteHyphen(g->players, "Chekhova-Kostina")) goto again;
if (substituteHyphen(g->players, "Chin-Hoe")) goto again;
if (substituteHyphen(g->players, "Chong-Ghee")) goto again;
if (substituteHyphen(g->players, "Cruz-Lopez")) goto again;
if (substituteHyphen(g->players, "Cuevas-Rodriguez")) goto again;
if (substituteHyphen(g->players, "Dan-Robert")) goto again;
if (substituteHyphen(g->players, "Donaldson-Akhmilovskaya")) goto again;
if (substituteHyphen(g->players, "Dus-Chotimirski")) goto again;
if (substituteHyphen(g->players, "Erenska-Radzewska")) goto again;
if (substituteHyphen(g->players, "Eric-Andre")) goto again;
if (substituteHyphen(g->players, "Esko-Matti")) goto again;
if (substituteHyphen(g->players, "Fauland-Borek")) goto again;
if (substituteHyphen(g->players, "Flear-Leroy")) goto again;
if (substituteHyphen(g->players, "Foong-Yin")) goto again;
if (substituteHyphen(g->players, "Fries-Nielsen")) goto again;
if (substituteHyphen(g->players, "Frolich-Dill")) goto again;
if (substituteHyphen(g->players, "Garcia-Palermo")) goto again;
if (substituteHyphen(g->players, "Gerd-Peter")) goto again;
if (substituteHyphen(g->players, "Gerrit-Hans")) goto again;
if (substituteHyphen(g->players, "Gert-Jan")) goto again;
if (substituteHyphen(g->players, "Gian-Thier")) goto again;
if (substituteHyphen(g->players, "Gustav-Schutz")) goto again;
if (substituteHyphen(g->players, "Hajkova-Maskova")) goto again;
if (substituteHyphen(g->players, "Hans-Elmar")) goto again;
if (substituteHyphen(g->players, "Hans-Georg")) goto again;
if (substituteHyphen(g->players, "Hans-Gunther")) goto again;
if (substituteHyphen(g->players, "Hans-Hilmar")) goto again;
if (substituteHyphen(g->players, "Hans-Hubert")) goto again;
if (substituteHyphen(g->players, "Hans-J")) goto again;
if (substituteHyphen(g->players, "Hans-Otto")) goto again;
if (substituteHyphen(g->players, "Hans-Peter")) goto again;
if (substituteHyphen(g->players, "Hans-U")) goto again;
if (substituteHyphen(g->players, "Har-Zvi")) goto again;
if (substituteHyphen(g->players, "Hartung-Nielsen")) goto again;
if (substituteHyphen(g->players, "Heine-Nielsen")) goto again;
if (substituteHyphen(g->players, "Heinz-Dieter")) goto again;
if (substituteHyphen(g->players, "Heinz-Jurg")) goto again;
if (substituteHyphen(g->players, "Heinz-Wilhelm")) goto again;
if (substituteHyphen(g->players, "Hoon-Cheng")) goto again;
if (substituteHyphen(g->players, "Hoyos-Millan")) goto again;
if (substituteHyphen(g->players, "Ionescu-Ilie")) goto again;
if (substituteHyphen(g->players, "Ivanka-Budinsky")) goto again;
if (substituteHyphen(g->players, "Jan-Hein")) goto again;
if (substituteHyphen(g->players, "Jan-Michel")) goto again;
if (substituteHyphen(g->players, "Jan-Olav")) goto again;
if (substituteHyphen(g->players, "Jan-Olov")) goto again;
if (substituteHyphen(g->players, "Jan-Willem")) goto again;
if (substituteHyphen(g->players, "Jean-Alexis")) goto again;
if (substituteHyphen(g->players, "Jean-Claude")) goto again;
if (substituteHyphen(g->players, "Jean-Luc")) goto again;
if (substituteHyphen(g->players, "Jean-Marc")) goto again;
if (substituteHyphen(g->players, "Jean-Philip")) goto again;
if (substituteHyphen(g->players, "Jean-Pierre")) goto again;
if (substituteHyphen(g->players, "Jean-Rene")) goto again;
if (substituteHyphen(g->players, "Jean-Robert")) goto again;
if (substituteHyphen(g->players, "Jens-Euw")) goto again;
if (substituteHyphen(g->players, "Jens-Ove")) goto again;
if (substituteHyphen(g->players, "Jens-Peter")) goto again;
if (substituteHyphen(g->players, "Jens-Uwe")) goto again;
if (substituteHyphen(g->players, "John-Paul")) goto again;
if (substituteHyphen(g->players, "Juan-Pablo")) goto again;
if (substituteHyphen(g->players, "Jukka-Pekka")) goto again;
if (substituteHyphen(g->players, "Kai-Uwe")) goto again;
if (substituteHyphen(g->players, "Kaj-Erik")) goto again;
if (substituteHyphen(g->players, "Kari-Juhani")) goto again;
if (substituteHyphen(g->players, "Karl-Heinz")) goto again;
if (substituteHyphen(g->players, "Karl-Johan")) goto again;
if (substituteHyphen(g->players, "Karl-Josef")) goto again;
if (substituteHyphen(g->players, "Karl-Willi")) goto again;
if (substituteHyphen(g->players, "Kick-Worthmuller")) goto again;
if (substituteHyphen(g->players, "Kien-Hua")) goto again;
if (substituteHyphen(g->players, "Klaus-Dieter")) goto again;
if (substituteHyphen(g->players, "Klaus-Jurgen")) goto again;
if (substituteHyphen(g->players, "Klimova-Richtrova")) goto again;
if (substituteHyphen(g->players, "Kok-Siong")) goto again;
if (substituteHyphen(g->players, "Lars-Ake")) goto again;
if (substituteHyphen(g->players, "Lars-Bo")) goto again;
if (substituteHyphen(g->players, "Lars-Erik")) goto again;
if (substituteHyphen(g->players, "Lian-Ann")) goto again;
if (substituteHyphen(g->players, "Litinskaya-Shul")) goto again;
if (substituteHyphen(g->players, "Loheac-Amoun")) goto again;
if (substituteHyphen(g->players, "M-Viorel")) goto again;
if (substituteHyphen(g->players, "Macek-Kalchbrenner")) goto again;
if (substituteHyphen(g->players, "Mads-Smith")) goto again;
if (substituteHyphen(g->players, "Maki-Uuro")) goto again;
if (substituteHyphen(g->players, "Maskova-Hajkova")) goto again;
if (substituteHyphen(g->players, "Massoud-Amir")) goto again;
if (substituteHyphen(g->players, "Meng-Kong")) goto again;
if (substituteHyphen(g->players, "Mephisto-16")) goto again;
if (substituteHyphen(g->players, "Mihai-Viorel")) goto again;
if (substituteHyphen(g->players, "Mihail-Viorel")) goto again;
if (substituteHyphen(g->players, "Milligan-Scott")) goto again;
if (substituteHyphen(g->players, "Milner-Barry")) goto again;
if (substituteHyphen(g->players, "Mircea-Sergiu")) goto again;
if (substituteHyphen(g->players, "Mitaru-Serban")) goto again;
if (substituteHyphen(g->players, "Neeraj-Kumar")) goto again;
if (substituteHyphen(g->players, "Niels-Peter")) goto again;
if (substituteHyphen(g->players, "Nils-Gus")) goto again;
if (substituteHyphen(g->players, "Nils-Johan")) goto again;
if (substituteHyphen(g->players, "Nokso-Koivisto")) goto again;
if (substituteHyphen(g->players, "Nutu-Gajic")) goto again;
if (substituteHyphen(g->players, "Ole-Christian")) goto again;
if (substituteHyphen(g->players, "Peicheva-Hansen")) goto again;
if (substituteHyphen(g->players, "Peicheva-Jurgens")) goto again;
if (substituteHyphen(g->players, "Peitscheva-Hansen")) goto again;
if (substituteHyphen(g->players, "Peitscheva-Jurgens")) goto again;
if (substituteHyphen(g->players, "Per-Erik")) goto again;
if (substituteHyphen(g->players, "Plauth-Herr")) goto again;
if (substituteHyphen(g->players, "Popova-Lelchuk")) goto again;
if (substituteHyphen(g->players, "Ralf-Axel")) goto again;
if (substituteHyphen(g->players, "Renoy-Chevrier")) goto again;
if (substituteHyphen(g->players, "Richtrova-Klimova")) goto again;
if (substituteHyphen(g->players, "Rivas-Pastor")) goto again;
if (substituteHyphen(g->players, "Sathe-Thipsay")) goto again;
if (substituteHyphen(g->players, "Schmidt-Brauns")) goto again;
if (substituteHyphen(g->players, "Shi-Lan")) goto again;
if (substituteHyphen(g->players, "Sideif-Zade")) goto again;
if (substituteHyphen(g->players, "Sieiro-Gonzalez")) goto again;
if (substituteHyphen(g->players, "Sikora-Gizynska")) goto again;
if (substituteHyphen(g->players, "Sikora-Lerch")) goto again;
if (substituteHyphen(g->players, "Suan-Shiau")) goto again;
if (substituteHyphen(g->players, "Tri-Sa-Ard")) goto again;
if (substituteHyphen(g->players, "Tze-Meng")) goto again;
if (substituteHyphen(g->players, "Veroci-Petronic")) goto again;
if (substituteHyphen(g->players, "Victor-Angel")) goto again;
if (substituteHyphen(g->players, "Videla-Seminara")) goto again;
if (substituteHyphen(g->players, "Wagner-Michel")) goto again;
if (substituteHyphen(g->players, "Weiss-Nowak")) goto again;
if (substituteHyphen(g->players, "Wiese-Jozwiak")) goto again;
if (substituteHyphen(g->players, "Znosko-Borovsky")) goto again;
}
return NULL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getBlackGame
@deftypefun {char *} getBlackGame (Game @var{g})
Returns the name of the player with the black pieces. The @w{@code{char
*}} is allocated statically. A return value of @code{NULL} means that
the information could not be extracted.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char *
getBlackGame(Game g)
{ static char black[MAX_NAME_SIZE+1];
char *s;
requireHeaderGame(g);
s = strchr(g->players, '-');
if (s && s == strrchr(g->players, '-'))
{ strcpy(black, ++s);
return normalisePlayer(black);
}
return NULL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getNumberGame
@deftypefun long getNumberGame (Game @var{g})
Returns the number of the game (starting with 1) relative to the entire
database.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
long
getNumberGame(Game g)
{ requireHeaderGame(g);
return g->number;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getYearGame
@deftypefun short getYearGame (Game @var{g})
Returns the year the game was played. If the year is not known zero is
returned.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
short
getYearGame(Game g)
{ requireHeaderGame(g);
return g->year;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getEcoGame
@deftypefun {char *} getEcoGame (Game @var{g})
Returns the ECO (Encyclopedia of Chess Openings) code of the game.
@code{NULL} is returned when the ECO code is not known.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char *
getEcoGame(Game g)
{ requireHeaderGame(g);
if (g->eco[0])
return g->eco;
return NULL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getEcoMajorGame
@deftypefun {char *} getEcoMajorGame (Game @var{g})
Returns the ECO (Encyclopedia of Chess Openings) code of the game.
@code{NULL} is returned when the ECO code is not known.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char *
getEcoMajorGame(Game g)
{ static char eco[4];
requireHeaderGame(g);
if (g->eco[0])
{ strncpy(eco, g->eco, 3);
eco[3] = '\0';
return eco;
}
return NULL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getFirstMoveGame
@deftypefun Move getFirstMoveGame (Game @var{g})
Returns the first move of the game.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
Move
getFirstMoveGame(Game g)
{ requireMovesGame(g);
return g->firstMove;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getResultGame
@deftypefun Result getResultGame (Game @var{g})
Returns the result of game @var{g}. The result is @code{WHITE_WINS},
@code{DRAW}, @code{BLACK_WINS} or one of the position evaluation codes
(e.g. @code{WHITE_ADVANTAGE}). @code{NO_RESULT} is returned when the
result is not known.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
Result
getResultGame(Game g)
{ requireHeaderGame(g);
return g->result;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node getRoundGame
@deftypefun short getRoundGame (Game @var{g})
Returns the round in which game @var{g} was played. The round is
extracted from the source field using the heuristic that the round
is between brackets (e.g @code{(15)}). The constant @code{NO_ROUND}
is returned when the round could not be determined.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
short
getRoundGame(Game g)
{ char *source;
char *s;
int round;
requireHeaderGame(g);
source = getSourceGame(g);
for (s=source; *s; s++)
{ if (*s == '(' && isdigit(*(s+1)))
{ round = atoi(s+1);
if (round > 0 && round < 40)
return round;
}
}
return NO_ROUND;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node checkHeaderGame
@deftypefun bool checkHeaderGame (Game @var{g})
Returns @code{FALSE} when decoding the header of the game resulted
in an error and @code{TRUE} otherwise.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
bool
checkHeaderGame(Game g)
{ requireHeaderGame(g);
if (foundError())
return FALSE;
return TRUE;
}
short
getMovesGame(Game g)
{ return g->moves;
}
short
getEloWhiteGame(Game g)
{ return g->eloWhite;
}
short
getEloBlackGame(Game g)
{ return g->eloBlack;
}
void
printGame(Game g, FILE *fd)
{ TextBuffer tb;
Position pos;
tb = newTextBuffer(fd, 75);
stringTextBuffer(tb, "GAME");
formatSpaceTextBuffer(tb, "%ld", getNumberGame(g));
if (getEcoGame(g))
{ stringSpaceTextBuffer(tb, "\"");
stringTextBuffer(tb, getEcoGame(g));
stringTextBuffer(tb, "\"");
} else
stringSpaceTextBuffer(tb, "\"\"");
stringSpaceTextBuffer(tb, getPlayersGame(g));
stringSpaceTextBuffer(tb, getSourceGame(g));
if (getYearGame(g))
formatSpaceTextBuffer(tb, "%d", getYearGame(g));
stringNewlineTextBuffer(tb, "");
pos = newPosition();
if (!fullGameP(g))
{ copyPosition(pos, g->position);
diagramPosition(pos, tb);
}
printMovesGame(g, getFirstMoveGame(g), pos, 0, 0, TRUE, tb);
stringNewlineTextBuffer(tb, "SCORE ");
if (getResultGame(g) != NO_RESULT)
stringTextBuffer(tb, chessSymbol(getResultGame(g)));
stringNewlineTextBuffer(tb, "\n");
freeTextBuffer(tb);
}
void
printMovesGame(Game g, /* Game we are printing */
Move move, /* Move under consideration */
Position pos, /* Position before ``move'' */
int ply, /* Move number as a ply: 0.. */
int level, /* Depth of variations: 0.. */
int notation, /* SHORT/LONG_ALGEBRAIC */
TextBuffer tb) /* Output TextBuffer */
{ int startPly = ply;
bool printSpace = FALSE;
bool printDots = TRUE;
bool printNextDots = FALSE;
bool marked = (level == 0 && markedGameP(g));
int algebraic = (level == 0 ? SHORT_ALGEBRAIC : notation);
if (marked && ply == 0)
stringTextBuffer(tb, "\\begin{moves}");
for (; move; move=move->next, ply++)
{ Position nextPos;
bool comments = containsCommentsMoveP(move);
bool variations = containsVariationsMoveP(move);
if (printSpace)
stringSpaceTextBuffer(tb, "");
printSpace = TRUE;
if (pos->toMove == WHITE)
{ formatTextBuffer(tb, "%d", (ply/2+1));
stringTextBuffer(tb, chessSymbol(WHITE_MOVE_SYMBOL));
} else
{ if (ply == startPly || printDots == TRUE)
{ formatTextBuffer(tb, "%d", (ply/2+1));
stringTextBuffer(tb, chessSymbol(BLACK_MOVE_SYMBOL));
}
}
if (variations)
{ nextPos = newPosition();
copyPosition(nextPos, pos);
} else
{ nextPos = NULL;
}
if (comments || variations || diagramMoveP(move))
printNextDots = TRUE;
else
printNextDots = FALSE;
outputMove(move, tb, pos, algebraic);
if (marked && (comments || variations || diagramMoveP(move)))
stringTextBuffer(tb, "\\end{moves}");
if (comments || variations)
{ if (level == 0)
stringSpaceTextBuffer(tb, chessSymbol(START_MAJOR_ALTERNATIVE));
else
stringSpaceTextBuffer(tb, chessSymbol(START_ALTERNATIVE));
}
if (comments)
outputCommentsMove(move, tb, pos);
doMovePosition(pos, move);
if (variations)
{ if (comments)
stringSpaceTextBuffer(tb, "");
printMovesGame(g, move->alternative, nextPos, ply, level+1, algebraic, tb);
}
if (comments || variations)
{ if (level == 0)
stringTextBuffer(tb, chessSymbol(END_MAJOR_ALTERNATIVE));
else
stringTextBuffer(tb, chessSymbol(END_ALTERNATIVE));
}
if (diagramMoveP(move) && !comments)
{ diagramPosition(pos, tb);
printNextDots = TRUE;
printSpace = FALSE;
}
if (marked && (comments || variations || diagramMoveP(move)))
stringTextBuffer(tb, "\\begin{moves}");
printDots = printNextDots;
printNextDots = FALSE;
}
if (marked)
stringTextBuffer(tb, "\\end{moves}");
/*
if (level == 1)
stringTextBuffer(tb, chessSymbol(END_MAJOR_ALTERNATIVE));
if (level > 1)
stringTextBuffer(tb, chessSymbol(END_ALTERNATIVE));
*/
freePosition(pos);
}
/*------------------------------------------------------------
* Portable Game Notation
*------------------------------------------------------------*/
void
pgnGame(Game g, FILE *fd, int notation)
{ TextBuffer tb;
Position pos;
if (!fullGameP(g))
{ fprintf(stderr, "Don't know how to print partial game (%ld) in PGN\n",
g->number);
return;
}
tb = newTextBuffer(fd, 75);
formatTextBuffer(tb, "[Event \"%s\"]\n", getSourceGame(g));
formatTextBuffer(tb, "[Site \"%s\"]\n", getSourceGame(g));
if (getYearGame(g))
formatTextBuffer(tb, "[Date \"%d\"]\n", getYearGame(g));
else
stringTextBuffer(tb, "[Date \"\"]\n");
if (getRoundGame(g))
formatTextBuffer(tb, "[Round \"%d\"]\n", getRoundGame(g));
else
stringTextBuffer(tb, "[Round \"\"]\n");
if (getWhiteGame(g))
formatTextBuffer(tb, "[White \"%s\"]\n", getWhiteGame(g));
else
stringTextBuffer(tb, "[White \"\"]\n");
if (getBlackGame(g))
formatTextBuffer(tb, "[Black \"%s\"]\n", getBlackGame(g));
else
stringTextBuffer(tb, "[Black \"\"]\n");
if (getResultGame(g) != NO_RESULT)
formatTextBuffer(tb, "[Result \"%s\"]\n", chessSymbol(getResultGame(g)));
else
stringTextBuffer(tb, "[Result \"\"]\n");
stringTextBuffer(tb, "\n");
pos = newPosition();
pgnMovesGame(g, getFirstMoveGame(g), pos, 0, notation, tb);
if (getResultGame(g) != NO_RESULT)
stringSpaceTextBuffer(tb, chessSymbol(getResultGame(g)));
stringNewlineTextBuffer(tb, "\n\n");
freeTextBuffer(tb);
}
void
pgnMovesGame(Game g, /* Game we are printing */
Move move, /* Move under consideration */
Position pos, /* Position before ``move'' */
int ply, /* Move number as a ply (0..) */
int notation, /* SHORT/LONG_ALGEBRAIC */
TextBuffer tb) /* Output TextBuffer */
{ for (; move; move=move->next, ply++)
{ stringSpaceTextBuffer(tb, "");
if (pos->toMove == WHITE)
{ formatTextBuffer(tb, "%d", (ply/2+1));
stringTextBuffer(tb, chessSymbol(WHITE_MOVE_SYMBOL));
}
stringTextBuffer(tb, getStringMovePosition(pos, move, notation));
doMovePosition(pos, move);
}
freePosition(pos);
}
/*------------------------------------------------------------
* Status of a game
*------------------------------------------------------------*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node bytesGame
@deftypefun {unsigned long} bytesGame (Game @var{g})
Returns the number of bytes game @var{g} occupies on disk. @code{NULL}
is returned on an error.
@end deftypefun
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
unsigned long
bytesGame(Game g)
{ if (g->flags & GAME_INIT_OK)
{ unsigned long bytes;
g->cbGame = newCbGame();
if ((bytes=readCbGame(g->cbGame, g->database, g->number)))
{ if (extractHeaderCbGame(g->cbGame, g))
{ g->flags |= GAME_HEADER_OK;
return bytes;
}
freeCbGame(g->cbGame);
g->cbGame = NULL;
return (unsigned long) NULL;
}
freeCbGame(g->cbGame);
g->cbGame = NULL;
return (unsigned long) NULL;
}
if (g->cbGame)
freeCbGame(g->cbGame);
g->cbGame = NULL;
return (unsigned long) NULL;
}
static void
requireHeaderGame(Game g)
{ if (g->flags & GAME_HEADER_OK)
return;
if (g->flags & GAME_INIT_OK)
{ g->cbGame = newCbGame();
if (readCbGame(g->cbGame, g->database, g->number))
{ if (extractHeaderCbGame(g->cbGame, g))
{ g->flags |= GAME_HEADER_OK;
return;
}
freeCbGame(g->cbGame);
g->cbGame = NULL;
return;
}
freeCbGame(g->cbGame);
g->cbGame = NULL;
return;
}
if (g->cbGame)
freeCbGame(g->cbGame);
g->cbGame = NULL;
}
static void
requireMovesGame(Game g)
{ if (g->flags & GAME_MOVES_OK)
return;
requireHeaderGame(g);
if (g->cbGame)
{ if (extractMovesCbGame(g->cbGame, g))
{ g->flags |= GAME_MOVES_OK;
return;
}
}
}