home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR2
/
CBUFF09.ZIP
/
SRC.ZIP
/
CBGAME.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-16
|
12KB
|
511 lines
/* $Id: cbgame.c,v 1.1.1.1 1993/06/21 11:11:59 anjo Exp $
*
* File cbgame.c
* Part of ChessBase utilities file format (CBUFF)
* Author Anjo Anjewierden, anjo@swi.psy.uva.nl
* Purpose Internal representation of a ChessBase game
* Works with GNU CC 2.4.5
*
* Notice Copyright (c) 1993 Anjo Anjewierden
*
* History 09/06/93 (Created)
* 31/10/93 (Last modified)
*/
/*------------------------------------------------------------
* Directives
*------------------------------------------------------------*/
#include "cbuff.h"
/*------------------------------------------------------------
* Definitions
*------------------------------------------------------------*/
static bool extractVariationsCbGame(CbGame cg, Game game);
/*------------------------------------------------------------
* Initialisation
*------------------------------------------------------------*/
CbGame
newCbGame()
{ CbGame cg;
cg = alloc(sizeof(struct cbgame));
cg->header = newCbHeader();
cg->text = NULL;
cg->moves = NULL;
cg->comments = NULL;
cg->position = NULL;
cg->textLength = 0;
cg->movesLength = 0;
cg->commentLength = 0;
return cg;
}
void
freeCbGame(CbGame cg)
{ if (cg->text)
unalloc(cg->text);
if (cg->moves)
unalloc(cg->moves);
if (cg->comments)
unalloc(cg->comments);
freeCbHeader(cg->header);
unalloc(cg);
}
void
resetCbGame(CbGame cg)
{ if (cg->text)
unalloc(cg->text);
if (cg->moves)
unalloc(cg->moves);
if (cg->comments)
unalloc(cg->comments);
resetCbHeader(cg->header);
cg->text = NULL;
cg->moves = NULL;
cg->comments = NULL;
cg->textLength = 0;
cg->movesLength = 0;
cg->commentLength = 0;
}
/*------------------------------------------------------------
* Reading
*------------------------------------------------------------*/
long
readCbGame(CbGame cg, CBase cb, long no)
{ long pos; /* Position in file */
unsigned char h[14]; /* Undecoded game header */
CbHeader ch = cg->header; /* Game header */
long rawBytes = 0;
resetCbGame(cg);
environmentError(cb, NULL, no);
if (no < 1 || no > getNoGamesCBase(cb))
{ setError(ERR_GAME_NUMBER_OUT_OF_RANGE);
return (long) NULL;
}
pos = getIndexGameCBase(cb, no);
if (fseek(cb->cbf, pos, 0))
{ setError(ERR_CANNOT_SEEK);
return (long) NULL;
}
if (fread(h,1,14,cb->cbf) != 14)
{ setError(ERR_CANNOT_READ_HEADER);
return (long) NULL;
}
rawBytes += 14;
initCbHeader(ch, h);
if (foundError())
return (long) NULL;
cg->textLength = playersLengthCbHeader(ch) + sourceLengthCbHeader(ch);
cg->movesLength = movesLengthCbHeader(ch);
cg->commentLength = commentLengthCbHeader(ch);
cg->text = alloc(cg->textLength);
cg->moves = alloc(cg->movesLength);
cg->comments = alloc(cg->commentLength);
if (fread(cg->text,1,cg->textLength,cb->cbf) != cg->textLength)
{ setError(ERR_CANNOT_READ_TEXT);
return (long) NULL;
}
rawBytes += cg->textLength;
if (fread(cg->moves,1,cg->movesLength,cb->cbf) != cg->movesLength)
{ setError(ERR_CANNOT_READ_MOVES);
return (long) NULL;
}
rawBytes += cg->movesLength;
if (fread(cg->comments,1,cg->commentLength,cb->cbf) != cg->commentLength)
{ setError(ERR_CANNOT_READ_COMMENTS);
return (long) NULL;
}
rawBytes += cg->commentLength;
if (!fullGameCbHeaderP(ch))
{ unsigned char nextMove;
unsigned char board[32];
int file, rank;
if (fread(board,1,32,cb->cbf) != 32)
{ setError(ERR_CANNOT_READ_POSITION);
return (long) NULL;
}
rawBytes += 32;
if (fread(&nextMove,1,1,cb->cbf) != 1)
{ setError(ERR_CANNOT_READ_MOVE_NUMBER);
return (long) NULL;
}
rawBytes += 1;
cg->nextMove = ((short) nextMove) + 1;
for (rank=0; rank<8; rank++)
{ for (file=0; file<8; file+=2)
{ unsigned char b = board[rank*4+file/2];
cg->board[makeSquare(file,rank)] = (Piece) (b >> 4);
cg->board[makeSquare(file+1,rank)] = (Piece) (b & 0xf);
}
}
}
{ unsigned char k;
int i;
int l = cg->textLength;
k = 3*l;
for (i=l-1; i>=0; i--)
{ cg->text[i] ^= k;
k *= 3;
}
}
{ unsigned char k;
int i;
int l = cg->movesLength;
k = 7*(l+1);
for (i=l-1; i>0; i--)
{ k *= 7;
cg->moves[i] ^= k;
}
}
return rawBytes;
}
/*------------------------------------------------------------
* Counting
*------------------------------------------------------------*/
long
countCbGame(CbGame cg, CBase cb, long no)
{ long pos; /* Position in file */
unsigned char h[14]; /* Undecoded game header */
CbHeader ch = cg->header; /* Game header */
long rawBytes = 0;
resetCbGame(cg);
environmentError(cb, NULL, no);
if (no < 1 || no > getNoGamesCBase(cb))
{ setError(ERR_GAME_NUMBER_OUT_OF_RANGE);
return (long) NULL;
}
pos = getIndexGameCBase(cb, no);
if (fseek(cb->cbf, pos, 0))
{ setError(ERR_CANNOT_SEEK);
return (long) NULL;
}
if (fread(h,1,14,cb->cbf) != 14)
{ setError(ERR_CANNOT_READ_HEADER);
return (long) NULL;
}
rawBytes += 14;
initCbHeader(ch, h);
if (foundError())
return (long) NULL;
cg->textLength = playersLengthCbHeader(ch) + sourceLengthCbHeader(ch);
cg->movesLength = movesLengthCbHeader(ch);
cg->commentLength = commentLengthCbHeader(ch);
rawBytes += cg->textLength;
rawBytes += cg->movesLength;
rawBytes += cg->commentLength;
if (!fullGameCbHeaderP(ch))
{ rawBytes += 32;
rawBytes += 1;
}
return rawBytes;
}
bool
extractHeaderCbGame(CbGame cg, Game game)
{ unsigned int slen;
unsigned int plen;
CbHeader ch = cg->header;
game->year = yearCbHeader(ch);
switch(ch->result)
{ case 0: game->result = BLACK_WINS; break;
case 1: game->result = DRAW; break;
case 2: game->result = WHITE_WINS; break;
case 3: game->result = NO_RESULT; break;
case 7: game->result = WHITE_WINNING; break;
case 11: game->result = WHITE_ADVANTAGE; break;
case 15: game->result = WHITE_BETTER; break;
case 19: game->result = EQUALITY; break;
case 23: game->result = UNCLEAR; break;
case 27: game->result = BLACK_BETTER; break;
case 31: game->result = BLACK_ADVANTAGE; break;
case 35: game->result = BLACK_WINNING; break;
case 39: game->result = COMPENSATION; break;
case 43: game->result = COMPENSATION; break;
case 47: game->result = WITH_COUNTERPLAY; break;
case 51: game->result = WITH_INITIATIVE; break;
case 55: game->result = WITH_ATTACK; break;
case 59: game->result = TIME_TROUBLE; break;
case 63: game->result = ONLY_MOVE; break;
default: setError(ERR_ILLEGAL_RESULT);
game->result = NO_RESULT;
}
plen = playersLengthCbHeader(ch);
slen = sourceLengthCbHeader(ch);
game->eloWhite = whiteEloCbHeader(ch);
game->eloBlack = blackEloCbHeader(ch);
game->moves = movesCbHeader(ch);
game->plies = game->moves * 2;
strcpy(game->eco, ecoCbHeader(ch));
game->flags |= (flags2bit6CbHeader(ch) ? GAME_FLAGS2_BIT6 : 0);
game->flags |= (deletedCbHeaderP(ch) ? GAME_DELETED : 0);
game->flags |= (markedCbHeaderP(ch) ? GAME_MARKED : 0);
strncpy(game->players, cg->text, plen);
game->players[plen] = '\0';
strncpy(game->source, &cg->text[plen], slen);
game->source[slen] = '\0';
if (!fullGameCbHeaderP(ch))
{ Position p;
p = game->position = newPosition();
memcpy(p->board, cg->board, sizeof(Piece) * 64);
p->nextMove = cg->nextMove;
p->toMove = (ch->flags1 & COLOUR_TO_MOVE_MASK ? BLACK : WHITE);
p->enPassant = ch->flags2 & EN_PASSANT_MASK;
p->castling = 0;
if (ch->flags1 & WHITE_CASTLE_LONG_MASK)
p->castling |= WHITE_LONG;
if (ch->flags1 & WHITE_CASTLE_SHORT_MASK)
p->castling |= WHITE_SHORT;
if (ch->flags1 & BLACK_CASTLE_LONG_MASK)
p->castling |= BLACK_LONG;
if (ch->flags1 & BLACK_CASTLE_SHORT_MASK)
p->castling |= BLACK_SHORT;
} else
game->flags |= GAME_INITIAL_POSITION;
return TRUE;
}
bool
extractMovesCbGame(CbGame cg, Game game)
{ int plies = cg->movesLength;
unsigned char *comments;
Position pos;
Move move;
int i;
int n;
if (containsVariationsGameP(game))
return extractVariationsCbGame(cg, game);
comments = cg->comments;
pos = newPosition();
for (i=0; i<plies; i++)
{ if (cg->moves[i] == START_VARIATION || cg->moves[i] == END_VARIATION)
{ setError(ERR_VARIATION_SEEN);
freePosition(pos);
return FALSE;
}
if (i == 0)
move = game->firstMove = newMove();
else
move = move->next = newMove();
n = cg->moves[i] & 0x7f;
if (!getMovePosition(pos,n,move))
{ setError(ERR_CANNOT_INTERPRET_MOVE);
freePosition(pos);
return FALSE;
}
doMovePosition(pos, move);
if (cg->moves[i] & 0x80) /* Comment */
comments = commentMove(move, comments);
if (foundError())
return FALSE;
}
game->plies = plies;
if (game->moves != (plies+1)/2)
{ setError(ERR_MOVE_COUNT_INCORRECT);
freePosition(pos);
return FALSE;
}
freePosition(pos);
return TRUE;
}
/* The code below is a bit "hairy".
*/
#define MAX_LEVELS (MAX_LEVEL_NESTING*2)
static bool
extractVariationsCbGame(CbGame cg, Game game)
{ int l;
int i;
int j;
int v;
int n;
unsigned char *comments;
Position pos;
Position variations[MAX_LEVELS]; /* Positions at given level */
Move currentMoves[MAX_LEVELS]; /* Current move at given level */
v = 0; /* Depth of variation */
j = 0; /* Moves seen */
l = 0; /* Plies seen */
comments = cg->comments;
for (i=0; i<MAX_LEVELS; i++)
{ variations[i] = newPosition();
currentMoves[i] = NULL;
}
for (i=0; i<cg->movesLength; i++)
{ Move move;
if (cg->moves[i] == START_VARIATION)
{ v += 2;
copyPosition(variations[v], variations[v-1]);
currentMoves[v] = NULL;
continue;
}
if ( cg->moves[i] == END_VARIATION
&& (i+1) < cg->movesLength
&& cg->moves[i+1] == START_VARIATION)
{ copyPosition(variations[v], variations[v-1]);
i++;
currentMoves[v] = NULL;
continue;
}
if (cg->moves[i] == END_VARIATION)
{ v -= 2;
continue;
}
if ((i+1) < cg->movesLength && cg->moves[i+1] == START_VARIATION)
{ copyPosition(variations[v+1], variations[v]);
currentMoves[v+1] = NULL;
}
pos = variations[v];
move = currentMoves[v];
if (v == 0)
{ if (move == NULL)
move = game->firstMove = newMove();
else
move = move->next = newMove();
} else
{ if (move == NULL)
{ Move alternative;
move = newMove();
alternative = currentMoves[v-2];
while (alternative->alternative)
alternative = alternative->alternative;
alternative->alternative = move;
} else
move = move->next = newMove();
}
currentMoves[v] = move;
{ if (pos->toMove == WHITE && v == 0)
j++;
n = cg->moves[i] & 0x7f;
if (!getMovePosition(pos,n,move) /* || (l>=m) */)
{ setError(ERR_CANNOT_INTERPRET_MOVE);
goto errorFound;
}
doMovePosition(pos, move);
if (cg->moves[i] & 0x80) /* Comment */
comments = commentMove(move, comments);
if (v == 0)
l++;
if (foundError())
goto errorFound;
}
}
for (i=0; i<MAX_LEVELS; i++)
freePosition(variations[i]);
game->plies = l;
if (game->moves != j)
{ setError(ERR_MOVE_COUNT_INCORRECT);
return FALSE;
}
return TRUE;
errorFound:
for (i=0; i<MAX_LEVELS; i++)
freePosition(variations[i]);
return FALSE;
}
/*------------------------------------------------------------
* Debugging
*------------------------------------------------------------*/
void
dumpCommentsCbGame(CbGame cg, FILE *fd)
{ unsigned char *s;
int i;
if (cg->commentLength == 0)
return;
fprintf(fd, "Comments (%x; %d):", (int) cg->comments, cg->commentLength);
for (i=0, s=cg->comments; i<cg->commentLength; i++, s++)
{ if (*s == 0xff)
fprintf(fd, "\n");
fprintf(fd, "%03o ", *s);
}
fprintf(fd, "\n");
}