From ec7b6bb32ba9632cda17b308808ce9ba1e27c090 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Tue, 29 Nov 2011 18:05:44 +0100 Subject: [PATCH] Implement S-Chess The value drops=2 in the gameState controls whether gating in pieces from the holdings is possible, and implies holdings even if holdings=0. New incarations of Cardinal and Marshall are added to the piece types, under the names H and E. Gating has to be entered as promotion ('/' in stead of '=' is allowed). King does no longer have to be the last piece type; a macro PIECES has been added to indicate the number of piece types. --- lasker-2.2.3/data/boards/seirawan/0 | 3 + lasker-2.2.3/src/Makefile.in | 2 + lasker-2.2.3/src/algcheck.c | 260 ++++---- lasker-2.2.3/src/board.c | 1171 ++++++++++++++++++----------------- lasker-2.2.3/src/board.h | 11 +- lasker-2.2.3/src/gameproc.c | 14 +- lasker-2.2.3/src/matchproc.c | 3 + lasker-2.2.3/src/movecheck.c | 37 +- 8 files changed, 784 insertions(+), 717 deletions(-) create mode 100644 lasker-2.2.3/data/boards/seirawan/0 diff --git a/lasker-2.2.3/data/boards/seirawan/0 b/lasker-2.2.3/data/boards/seirawan/0 new file mode 100644 index 0000000..e627474 --- /dev/null +++ b/lasker-2.2.3/data/boards/seirawan/0 @@ -0,0 +1,3 @@ +S 8x8 g +W: P a2 b2 c2 d2 e2 f2 g2 h2 N b1 g1 B c1 f1 Q d1 K e1 R a1 h1 D @ U @ +B: P a7 b7 c7 d7 e7 f7 g7 h7 N b8 g8 B c8 f8 Q d8 K e8 R a8 h8 D @ U @ diff --git a/lasker-2.2.3/src/Makefile.in b/lasker-2.2.3/src/Makefile.in index 531038e..b0aff55 100644 --- a/lasker-2.2.3/src/Makefile.in +++ b/lasker-2.2.3/src/Makefile.in @@ -141,6 +141,7 @@ install: $(ALL) install -d -m0755 ${CHESSDDIR}/data/boards/courier install -d -m0755 ${CHESSDDIR}/data/boards/fairy install -d -m0755 ${CHESSDDIR}/data/boards/great + install -d -m0755 ${CHESSDDIR}/data/boards/seirawan install -d -m0755 ${CHESSDDIR}/games/history install -d -m0755 ${CHESSDDIR}/games/journal install -d -m0755 ${CHESSDDIR}/games/adjourned @@ -166,6 +167,7 @@ install: $(ALL) cp -u ${srcdir}/../data/boards/fairy/* ${CHESSDDIR}/data/boards/fairy cp -u ${srcdir}/../data/boards/great/* ${CHESSDDIR}/data/boards/great cp -u ${srcdir}/../data/boards/caparandom/* ${CHESSDDIR}/data/boards/caparandom + cp -u ${srcdir}/../data/boards/seirawan/* ${CHESSDDIR}/data/boards/seirawan perl -e 'mkdir("${CHESSDDIR}/players/$$_",0755) for ("a".."z")' perl -e 'mkdir("${CHESSDDIR}/games/history/$$_",0755) for ("0".."99")' perl -e 'mkdir("${CHESSDDIR}/games/journal/$$_",0755) for ("a".."z")' diff --git a/lasker-2.2.3/src/algcheck.c b/lasker-2.2.3/src/algcheck.c index 3efc4ce..aa7d5af 100644 --- a/lasker-2.2.3/src/algcheck.c +++ b/lasker-2.2.3/src/algcheck.c @@ -106,9 +106,9 @@ static int get_move_info(const char *str, int *piece, int *ff, int *fr, int *tf, case 'r': if ((tmp[j] < '0') || (tmp[j] > '9')) // [HGM] also match 0- and 9-rank goto nomatch; - if (ltr == ALG_UNKNOWN) - ltr = tmp[j] - '0'; // [HGM] allow 0-rank for Xiangqi, correct later - else + if (ltr == ALG_UNKNOWN) + ltr = tmp[j] - '0'; // [HGM] allow 0-rank for Xiangqi, correct later + else lfr = tmp[j] - '0'; break; case 'p': @@ -261,18 +261,18 @@ static void add_promotion(struct game_state_t *gs, const char *mstr, struct move case 'q': piece = QUEEN; break; - case 'c': - if(!gs->capablancaPieces) return; // [HGM] should make variant-dependent piece mask - piece = MARSHALL; - break; - case 'a': - if(!gs->capablancaPieces) return; - piece = CARDINAL; - break; - case 'm': - if(!gs->royalKnight) return; // [HGM] only in knightmate - piece = MAN; - break; + case 'c': + if(!gs->capablancaPieces) return; // [HGM] should make variant-dependent piece mask + piece = MARSHALL; + break; + case 'a': + if(!gs->capablancaPieces) return; + piece = CARDINAL; + break; + case 'm': + if(!gs->royalKnight) return; // [HGM] only in knightmate + piece = MAN; + break; case 'r': piece = ROOK; break; @@ -280,7 +280,7 @@ static void add_promotion(struct game_state_t *gs, const char *mstr, struct move piece = BISHOP; break; case 'n': - if(gs->royalKnight) return; // [HGM] not in knightmate + if(gs->royalKnight) return; // [HGM] not in knightmate piece = KNIGHT; break; // Superchess promotons: filtered out later by promoType @@ -296,18 +296,22 @@ static void add_promotion(struct game_state_t *gs, const char *mstr, struct move case 'v': piece = CENTAUR; break; - case 'e': - piece = EMPRESS; + case 'e': + piece = gs->drops == 2 ? SELEPHANT : EMPRESS; // for Seirawan break; case 's': piece = PRINCESS; break; + case 'h': + if(gs->drops != 2) return; + piece = HAWK; + break; default: return; } i = colorval(gs->board[mt->fromFile][mt->fromRank]) == WHITE ? 0 : 1; if(gs->promoType == 2 && gs->holding[i][piece-1] == 0) return; // only if piece was captured - if(piece >= WOODY && (gs->promoType != 2 || gs->promoZone == 3)) return; // reserved for Superchess + if(piece >= WOODY && piece < KING && (gs->promoType != 2 || gs->promoZone == 3)) return; // reserved for Superchess mt->piecePromotionTo = piece | colorval(gs->board[mt->fromFile][mt->fromRank]); } @@ -322,13 +326,13 @@ int alg_parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt) d_printf( "CHESSD: Shouldn't try to algebraicly parse non-algabraic move string.\n"); return MOVE_ILLEGAL; } - // [HGM] check if move does not stray off board - if(gs->ranks < 10) { - if(tr == 0 || fr == 0) return MOVE_ILLEGAL; // used nonexistent 0-rank - if(tr != ALG_UNKNOWN) tr--; if(fr != ALG_UNKNOWN) fr--; // shift to lowest rank = 1 - } - if(tr >= gs->ranks || fr >= gs->ranks || tf >= gs->files || ff >= gs->files) - return MOVE_ILLEGAL; + // [HGM] check if move does not stray off board + if(gs->ranks < 10) { + if(tr == 0 || fr == 0) return MOVE_ILLEGAL; // used nonexistent 0-rank + if(tr != ALG_UNKNOWN) tr--; if(fr != ALG_UNKNOWN) fr--; // shift to lowest rank = 1 + } + if(tr >= gs->ranks || fr >= gs->ranks || tf >= gs->files || ff >= gs->files) + return MOVE_ILLEGAL; // [HGM] resolve ambiguity in piece, type based on variant switch(piece) { @@ -371,7 +375,7 @@ int alg_parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt) if(strstr(gs->variant, "great")) piece = MASTODON; break; } - + /* Resolve ambiguities in to-ness */ if (tf == ALG_UNKNOWN) { d_printf("Ambiguous %s(%d)\n", __FUNCTION__, __LINE__); @@ -521,14 +525,14 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) piece = piecetype(gs->board[mt->fromFile][mt->fromRank]); } - if ((mt->fromFile == ALG_CASTLE) && (mt->toFile > mt->toRank)) { // [HGM] castle: K ends right of R - strcpy(mStr, "O-O"); - goto check; - } - if ((mt->fromFile == ALG_CASTLE) && (mt->toFile < mt->toRank)) { // [HGM] castle: K ends left of R - strcpy(mStr, "O-O-O"); - goto check; - } + if ((mt->fromFile == ALG_CASTLE) && (mt->toFile > mt->toRank)) { // [HGM] castle: K ends right of R + strcpy(mStr, "O-O"); + goto check; + } + if ((mt->fromFile == ALG_CASTLE) && (mt->toFile < mt->toRank)) { // [HGM] castle: K ends left of R + strcpy(mStr, "O-O-O"); + goto check; + } strcpy(mStr, ""); switch (piece) { case PAWN: @@ -551,16 +555,16 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) break; case ALFIL2: case AMAZON: - case CARDINAL: - strcpy(mStr, "A"); - break; + case CARDINAL: + strcpy(mStr, "A"); + break; case CANNON: - case MARSHALL: - strcpy(mStr, "C"); - break; - case MAN: - strcpy(mStr, "M"); - break; + case MARSHALL: + strcpy(mStr, "C"); + break; + case MAN: + strcpy(mStr, "M"); + break; case FERZ: case QUEEN: strcpy(mStr, "Q"); @@ -625,8 +629,8 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) /* Checks for ambiguity in short notation ( Ncb3, R8e8 or so) */ if (piece != PAWN) { ambig = r_ambig = f_ambig = 0; - for (r = 0; r < gs->ranks; r++) - for (f = 0; f < gs->files; f++) { + for (r = 0; r < gs->ranks; r++) + for (f = 0; f < gs->files; f++) { if ((gs->board[f][r] != NOPIECE) && iscolor(gs->board[f][r], gs->onMove) && (piecetype(gs->board[f][r]) == piece) && ((f != mt->fromFile) || (r != mt->fromRank))) { @@ -660,87 +664,89 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) } } } - if (ambig > 0) { - /* Ambiguity in short notation, need to add file,rank or _both_ in - notation */ - if (f_ambig == 0) { - sprintf(tmp, "%c", mt->fromFile + 'a'); - strcat(mStr, tmp); - } else if (r_ambig == 0) { - sprintf(tmp, "%d", mt->fromRank + 1 - (gs->ranks > 9)); - strcat(mStr, tmp); - } else { - sprintf(tmp, "%c%d", mt->fromFile + 'a', mt->fromRank + 1 - (gs->ranks > 9)); - strcat(mStr, tmp); - } - } - } - if ((gs->board[mt->toFile][mt->toRank] != NOPIECE) || - ((piece == PAWN) && (mt->fromFile != mt->toFile))) { - strcat(mStr, "x"); - } - } - sprintf(tmp, "%c%d", mt->toFile + 'a', mt->toRank + 1 - (gs->ranks > 9)); - strcat(mStr, tmp); - - if ((piece == PAWN || gs->promoType == 3) && (mt->piecePromotionTo != NOPIECE)) { - strcat(mStr, "="); /* = before promoting piece */ - switch (piecetype(mt->piecePromotionTo)) { - case KNIGHT: - strcat(mStr, "N"); - break; - case BISHOP: - strcat(mStr, "B"); - break; - case ROOK: - strcat(mStr, "R"); - break; - case CARDINAL: - strcat(mStr, "A"); - break; - case MARSHALL: - strcat(mStr, "C"); - break; - case MAN: - strcat(mStr, "M"); - break; - case QUEEN: - strcat(mStr, "Q"); - break; - case FERZ2: - strcat(mStr, "F"); - break; - case WOODY: - strcat(mStr, "W"); - break; - case EMPRESS: - strcat(mStr, "E"); - break; - case CENTAUR: - strcat(mStr, "V"); - break; - case PRINCESS: - strcat(mStr, "S"); - break; - case SQUIRREL: - strcat(mStr, "O"); - break; - case MASTODON: - strcat(mStr, "G"); - break; - case GOLD: // [HGM] Shogi promotions: avoid use of '+' - strcat(mStr, "G"); - break; - case DRAGONHORSE: - strcat(mStr, "H"); - break; - case DRAGONKING: - strcat(mStr, "D"); - break; - default: - break; - } - } + if (ambig > 0) { + /* Ambiguity in short notation, need to add file,rank or _both_ in + notation */ + if (f_ambig == 0) { + sprintf(tmp, "%c", mt->fromFile + 'a'); + strcat(mStr, tmp); + } else if (r_ambig == 0) { + sprintf(tmp, "%d", mt->fromRank + 1 - (gs->ranks > 9)); + strcat(mStr, tmp); + } else { + sprintf(tmp, "%c%d", mt->fromFile + 'a', mt->fromRank + 1 - (gs->ranks > 9)); + strcat(mStr, tmp); + } + } + } + if ((gs->board[mt->toFile][mt->toRank] != NOPIECE) || + ((piece == PAWN) && (mt->fromFile != mt->toFile))) { + strcat(mStr, "x"); + } + } + sprintf(tmp, "%c%d", mt->toFile + 'a', mt->toRank + 1 - (gs->ranks > 9)); + strcat(mStr, tmp); + + if ((piece == PAWN || gs->promoType == 3) && (mt->piecePromotionTo != NOPIECE)) { + strcat(mStr, "="); /* = before promoting piece */ + switch (piecetype(mt->piecePromotionTo)) { + case KNIGHT: + strcat(mStr, "N"); + break; + case BISHOP: + strcat(mStr, "B"); + break; + case ROOK: + strcat(mStr, "R"); + break; + case CARDINAL: + strcat(mStr, "A"); + break; + case MARSHALL: + strcat(mStr, "C"); + break; + case MAN: + strcat(mStr, "M"); + break; + case QUEEN: + strcat(mStr, "Q"); + break; + case FERZ2: + strcat(mStr, "F"); + break; + case WOODY: + strcat(mStr, "W"); + break; + case SELEPHANT: + case EMPRESS: + strcat(mStr, "E"); + break; + case CENTAUR: + strcat(mStr, "V"); + break; + case PRINCESS: + strcat(mStr, "S"); + break; + case SQUIRREL: + strcat(mStr, "O"); + break; + case MASTODON: + strcat(mStr, "G"); + break; + case GOLD: // [HGM] Shogi promotions: avoid use of '+' + strcat(mStr, "G"); + break; + case HAWK: + case DRAGONHORSE: + strcat(mStr, "H"); + break; + case DRAGONKING: + strcat(mStr, "D"); + break; + default: + break; + } + } check:; fakeMove = *gs; execute_move(&fakeMove, mt, 0); diff --git a/lasker-2.2.3/src/board.c b/lasker-2.2.3/src/board.c index 6aa7524..8c92473 100644 --- a/lasker-2.2.3/src/board.c +++ b/lasker-2.2.3/src/board.c @@ -24,11 +24,11 @@ const char *wpstring[] = {" ", "P", "N", "B", "R", "A", "C", "M", "Q", "E", "B", "Q", "W", "H", "N", "D", "H", "L", - "C", "S", "G", "H", "A", "F", "E", "H", "M", "S", "E", "W", "O", "G", "V", "S", "E", "A", "K"}; + "C", "S", "G", "H", "A", "F", "E", "H", "M", "S", "E", "W", "O", "G", "V", "S", "E", "A", "K", "H", "E"}; const char *bpstring[] = {" ", "p", "n", "b", "r", "a", "c", "m", "q", "e", "b", "q", "w", "h", "n", "d", "h", "l", - "c", "s", "g", "h", "a", "f", "e", "h", "m", "s", "e", "w", "o", "g", "v", "s", "e", "a", "k"}; + "c", "s", "g", "h", "a", "f", "e", "h", "m", "s", "e", "w", "o", "g", "v", "s", "e", "a", "k", "h", "e"}; -int pieceValues[KING+1] = {0, 1, 3, 3, 5, 8, 9, 3, 9, 1, 1, 2, 2, 2, 1, 6, 5, 2, 3, 3, 3, 1, 5, 2, 1, 7, 7, 3, 3, 3, 7, 7, 7, 8, 9, 12, 0}; +int pieceValues[PIECES] = {0, 1, 3, 3, 5, 8, 9, 3, 9, 1, 1, 2, 2, 2, 1, 6, 5, 2, 3, 3, 3, 1, 5, 2, 1, 7, 7, 3, 3, 3, 7, 7, 7, 8, 9, 12, 0, 8, 9}; static const int mach_type = (1<<7) | (1<<8) | (1<<9) | (1<<10) | (1<<11); #define IsMachineStyle(n) (((1<<(n)) & mach_type) != 0) @@ -78,7 +78,7 @@ static void reset_board_vars(struct game_state_t *gs) for (f = 0; f < 2; f++) { for (r = 0; r < BW; r++) gs->ep_possible[f][r] = 0; - for (r = PAWN; r <= KING-1; r++) + for (r = PAWN; r <= PIECES-1; r++) gs->holding[f][r-PAWN] = 0; } gs->wkmoved = gs->wqrmoved = gs->wkrmoved = -1; // [HGM] castle: no rights @@ -103,42 +103,42 @@ void board_standard(struct game_state_t *gs) { int f,r; - for (f = 0; f < BW; f++) - for (r = 0; r < BH; r++) - gs->board[f][r] = NOPIECE; - for (f = 0; f < gs->files; f++) - gs->board[f][gs->ranks-7] = W_PAWN; - for (f = 0; f < gs->files; f++) - gs->board[f][6] = B_PAWN; - gs->board[0][0] = W_ROOK; - gs->board[1][0] = W_KNIGHT; - gs->board[2][0] = W_BISHOP; - gs->board[3][0] = W_QUEEN; - gs->board[gs->files/2][0] = W_KING; - gs->board[gs->files-3][0] = W_BISHOP; - gs->board[gs->files-2][0] = W_KNIGHT; - gs->board[gs->files-1][0] = W_ROOK; - gs->board[0][gs->ranks-1] = B_ROOK; - gs->board[1][gs->ranks-1] = B_KNIGHT; - gs->board[2][gs->ranks-1] = B_BISHOP; - gs->board[3][gs->ranks-1] = B_QUEEN; - gs->board[gs->files/2][gs->ranks-1] = B_KING; - gs->board[gs->files-3][gs->ranks-1] = B_BISHOP; - gs->board[gs->files-2][gs->ranks-1] = B_KNIGHT; - gs->board[gs->files-1][gs->ranks-1] = B_ROOK; + for (f = 0; f < BW; f++) + for (r = 0; r < BH; r++) + gs->board[f][r] = NOPIECE; + for (f = 0; f < gs->files; f++) + gs->board[f][gs->ranks-7] = W_PAWN; + for (f = 0; f < gs->files; f++) + gs->board[f][6] = B_PAWN; + gs->board[0][0] = W_ROOK; + gs->board[1][0] = W_KNIGHT; + gs->board[2][0] = W_BISHOP; + gs->board[3][0] = W_QUEEN; + gs->board[gs->files/2][0] = W_KING; + gs->board[gs->files-3][0] = W_BISHOP; + gs->board[gs->files-2][0] = W_KNIGHT; + gs->board[gs->files-1][0] = W_ROOK; + gs->board[0][gs->ranks-1] = B_ROOK; + gs->board[1][gs->ranks-1] = B_KNIGHT; + gs->board[2][gs->ranks-1] = B_BISHOP; + gs->board[3][gs->ranks-1] = B_QUEEN; + gs->board[gs->files/2][gs->ranks-1] = B_KING; + gs->board[gs->files-3][gs->ranks-1] = B_BISHOP; + gs->board[gs->files-2][gs->ranks-1] = B_KNIGHT; + gs->board[gs->files-1][gs->ranks-1] = B_ROOK; #if 1 - if(gs->files == 10) { - gs->board[6][0] = W_CARDINAL; - gs->board[4][0] = W_MARSHALL; - gs->board[6][gs->ranks-1] = B_CARDINAL; - gs->board[4][gs->ranks-1] = B_MARSHALL; - } - if(gs->royalKnight) { - gs->board[1][0] = W_MAN; - gs->board[gs->files-2][0] = W_MAN; - gs->board[1][gs->ranks-1] = B_MAN; - gs->board[gs->files-2][gs->ranks-1] = B_MAN; - } + if(gs->files == 10) { + gs->board[6][0] = W_CARDINAL; + gs->board[4][0] = W_MARSHALL; + gs->board[6][gs->ranks-1] = B_CARDINAL; + gs->board[4][gs->ranks-1] = B_MARSHALL; + } + if(gs->royalKnight) { + gs->board[1][0] = W_MAN; + gs->board[gs->files-2][0] = W_MAN; + gs->board[1][gs->ranks-1] = B_MAN; + gs->board[gs->files-2][gs->ranks-1] = B_MAN; + } #endif reset_board_vars(gs); @@ -156,9 +156,9 @@ int board_init(int g,struct game_state_t *b, char *category, char *board) int retval = 0; int wval, i, j; - b->files = b->ranks = 8; - b->pawnDblStep = (!category || strcmp(category, "shatranj")); - b->royalKnight = (category && !strcmp(category, "knightmate")); + b->files = b->ranks = 8; + b->pawnDblStep = (!category || strcmp(category, "shatranj")); + b->royalKnight = (category && !strcmp(category, "knightmate")); b->capablancaPieces = 0; b->holdings = 0; b->drops = 0; @@ -169,24 +169,24 @@ int board_init(int g,struct game_state_t *b, char *category, char *board) b->stalemate = 1; b->promoType = 1; b->promoZone = 1; - b->variant[0] = 0; // [HGM] variant: default is normal, if variant name is missing - if (!category || !board || !category[0] || !board[0]) - /* accounts for bughouse too */ - board_standard(b); + b->variant[0] = 0; // [HGM] variant: default is normal, if variant name is missing + if (!category || !board || !category[0] || !board[0]) + /* accounts for bughouse too */ + board_standard(b); else { - if(category && category[0]) strcpy(b->variant, category); // [HGM] variant: remember category name + if(category && category[0]) strcpy(b->variant, category); // [HGM] variant: remember category name if (!strcmp(category, "wild") && sscanf(board, "%d", &wval) == 1) { - if(wval >= 1 && wval <= 4) + if(wval >= 1 && wval <= 4) wild_update(b->board, wval); - sprintf(b->variant, "wild/%d", wval); + sprintf(b->variant, "wild/%d", wval); } if (board && !strcmp(board, "0")) - b->setup = 0; // [HGM] variant: any board in the default file "0" is supposed to be implied by the variant + b->setup = 0; // [HGM] variant: any board in the default file "0" is supposed to be implied by the variant - if (!strcmp(category, "knightmate")) { - board_standard(b); - } else if (!strcmp(category, "super")) { + if (!strcmp(category, "knightmate")) { + board_standard(b); + } else if (!strcmp(category, "super")) { board_standard(b); b->holdings = 1; b->promoType = 2; @@ -203,17 +203,17 @@ int board_init(int g,struct game_state_t *b, char *category, char *board) placed = 1; } while(!placed); } - b->setup = 1; - } else if (!strcmp(category, "fischerandom")) { + b->setup = 1; + } else if (!strcmp(category, "fischerandom")) { wild_update(b->board, 22); b->castlingStyle = 2; - b->setup = 1; // [HGM] FRC: even the default is a setup position, for which an initial board has to be printed + b->setup = 1; // [HGM] FRC: even the default is a setup position, for which an initial board has to be printed } else if (!strcmp(category, "caparandom")) { - b->files = 10; + b->files = 10; wild_update(b->board, 46); b->castlingStyle = 2; - b->setup = 1; - } else retval = board_read_file(category, board, b); + b->setup = 1; + } else retval = board_read_file(category, board, b); } if(b->setup && game_globals.garray[g].FENstartPos[0]) // [HGM] use pre-existing start position, if one available FEN_to_board(game_globals.garray[g].FENstartPos, b); // (could be wild board, or shuffle variant) @@ -236,7 +236,7 @@ int board_init(int g,struct game_state_t *b, char *category, char *board) } } } - + MakeFENpos(g, game_globals.garray[g].FENstartPos); return retval; @@ -257,7 +257,7 @@ void board_calc_strength(struct game_state_t *b, int *ws, int *bs) *p += pieceValues[piecetype(b->board[r][f])]; } } - for (r = PAWN; r < KING; r++) { + for (r = PAWN; r < PIECES; r++) { *ws += b->holding[0][r-1] * pieceValues[r]; *bs += b->holding[1][r-1] * pieceValues[r]; } @@ -269,7 +269,7 @@ static char *holding_str(int *holding) int p,i,j; i = 0; - for (p = PAWN; p < KING; p++) { + for (p = PAWN; p < PIECES; p++) { for (j = 0; j < holding[p-1]; j++) { tmp[i++] = wpstring[p][0]; } @@ -350,7 +350,7 @@ char *board_to_string(char *wn, char *bn, int p) { int bh = (b->gameNum >= 0 && game_globals.garray[b->gameNum].link >= 0 - || b->holdings ); // [HGM] zh: make sure holdings are printed + || b->holdings || b->drops == 2); // [HGM] zh: make sure holdings are printed (also in Seirawan) orient = orientation; myTurn = relation; @@ -433,96 +433,96 @@ static int genstyle(struct game_state_t *b, struct move_t *ml, const char *wp[], const char *top, const char *mid, const char *start, const char *end, const char *label,const char *blabel) { - int f, r, count, i; - char tmp[80], mylabel[80], *p, *q, myTop[80], myMid[80]; - int firstR, lastR, firstF, lastF, inc; - int ws, bs, sqrSize = strlen(wp[0]); - - board_calc_strength(b, &ws, &bs); - if (orient == WHITE) { - firstR = b->ranks-1; - firstF = b->files-1; - lastR = lastF = 0; - inc = -1; - } else { - firstR = firstF = 0; - lastR = b->ranks-1; - lastF = b->files-1; - inc = 1; + int f, r, count, i; + char tmp[80], mylabel[80], *p, *q, myTop[80], myMid[80]; + int firstR, lastR, firstF, lastF, inc; + int ws, bs, sqrSize = strlen(wp[0]); + + board_calc_strength(b, &ws, &bs); + if (orient == WHITE) { + firstR = b->ranks-1; + firstF = b->files-1; + lastR = lastF = 0; + inc = -1; + } else { + firstR = firstF = 0; + lastR = b->ranks-1; + lastF = b->files-1; + inc = 1; } strcpy(myTop, top); strcpy(myMid, mid); - Enlarge(myTop, sqrSize, b->files); - Enlarge(myMid, sqrSize, b->files); - strcat(bstring, myTop); - for (f = firstR, count = b->ranks-1; f != lastR + inc; f += inc, count--) { - sprintf(tmp, " %d %s", f + (b->ranks < 10), start); - strcat(bstring, tmp); - for (r = lastF; r != firstF - inc; r = r - inc) { - if (square_color(r, f) == WHITE) - strcat(bstring, wsqr); - else - strcat(bstring, bsqr); - if (piecetype(b->board[r][f]) == NOPIECE) { - if (square_color(r, f) == WHITE) - strcat(bstring, bp[0]); - else - strcat(bstring, wp[0]); + Enlarge(myTop, sqrSize, b->files); + Enlarge(myMid, sqrSize, b->files); + strcat(bstring, myTop); + for (f = firstR, count = b->ranks-1; f != lastR + inc; f += inc, count--) { + sprintf(tmp, " %d %s", f + (b->ranks < 10), start); + strcat(bstring, tmp); + for (r = lastF; r != firstF - inc; r = r - inc) { + if (square_color(r, f) == WHITE) + strcat(bstring, wsqr); + else + strcat(bstring, bsqr); + if (piecetype(b->board[r][f]) == NOPIECE) { + if (square_color(r, f) == WHITE) + strcat(bstring, bp[0]); + else + strcat(bstring, wp[0]); } else { int piece = piecetype(b->board[r][f]); -// if(piece > QUEEN) piece = ELEPHANT + (piece == KING); // All fairies become elephants in ascii styles - if (colorval(b->board[r][f]) == WHITE) - strcat(bstring, wp[piece]); - else - strcat(bstring, bp[piece]); - } - } - sprintf(tmp, "%s", end); - strcat(bstring, tmp); - switch (count) { - case 7: - sprintf(tmp, " Move # : %d (%s)", b->moveNum, CString(b->onMove)); - strcat(bstring, tmp); - break; - case 6: -/* if ((b->moveNum > 1) || (b->onMove == BLACK)) { */ -/* The change from the above line to the one below is a kludge by hersco. */ - if (game_globals.garray[b->gameNum].numHalfMoves > 0) { -/* loon: think this fixes the crashing ascii board on takeback bug */ - sprintf(tmp, " %s Moves : '%s'", CString(CToggle(b->onMove)), - move_and_time(&ml[game_globals.garray[b->gameNum].numHalfMoves - 1])); - strcat(bstring, tmp); - } - break; - case 5: - break; - case 4: - sprintf(tmp, " Black Clock : %s", tenth_str(((bTime > 0) ? bTime : 0), 1)); - strcat(bstring, tmp); - break; - case 3: - sprintf(tmp, " White Clock : %s", tenth_str(((wTime > 0) ? wTime : 0), 1)); - strcat(bstring, tmp); - break; - case 2: - sprintf(tmp, " Black Strength : %d", bs); - strcat(bstring, tmp); - break; - case 1: - sprintf(tmp, " White Strength : %d", ws); - strcat(bstring, tmp); - break; - case 0: - break; - } - strcat(bstring, "\n"); - if (count != 0) - strcat(bstring, myMid); - else - strcat(bstring, myTop); - } +// if(piece > QUEEN) piece = ELEPHANT + (piece == KING); // All fairies become elephants in ascii styles + if (colorval(b->board[r][f]) == WHITE) + strcat(bstring, wp[piece]); + else + strcat(bstring, bp[piece]); + } + } + sprintf(tmp, "%s", end); + strcat(bstring, tmp); + switch (count) { + case 7: + sprintf(tmp, " Move # : %d (%s)", b->moveNum, CString(b->onMove)); + strcat(bstring, tmp); + break; + case 6: +/* if ((b->moveNum > 1) || (b->onMove == BLACK)) { */ +/* The change from the above line to the one below is a kludge by hersco. */ + if (game_globals.garray[b->gameNum].numHalfMoves > 0) { +/* loon: think this fixes the crashing ascii board on takeback bug */ + sprintf(tmp, " %s Moves : '%s'", CString(CToggle(b->onMove)), + move_and_time(&ml[game_globals.garray[b->gameNum].numHalfMoves - 1])); + strcat(bstring, tmp); + } + break; + case 5: + break; + case 4: + sprintf(tmp, " Black Clock : %s", tenth_str(((bTime > 0) ? bTime : 0), 1)); + strcat(bstring, tmp); + break; + case 3: + sprintf(tmp, " White Clock : %s", tenth_str(((wTime > 0) ? wTime : 0), 1)); + strcat(bstring, tmp); + break; + case 2: + sprintf(tmp, " Black Strength : %d", bs); + strcat(bstring, tmp); + break; + case 1: + sprintf(tmp, " White Strength : %d", ws); + strcat(bstring, tmp); + break; + case 0: + break; + } + strcat(bstring, "\n"); + if (count != 0) + strcat(bstring, myMid); + else + strcat(bstring, myTop); + } q = mylabel; i = 0; - if (orient == WHITE) { + if (orient == WHITE) { p = label; while(*p) { switch(*p) { @@ -547,439 +547,440 @@ static int genstyle(struct game_state_t *b, struct move_t *ml, const char *wp[], *q++ = *p++ + b->files - 12; if(++i >= b->files) { *q++ = '\n'; *q++ = 0; } } - } - } + } + } *q++ = 0; - strcat(bstring, mylabel); - return 0; + strcat(bstring, mylabel); + return 0; } -/* Experimental ANSI board for colour representation */ -static int style13(struct game_state_t *b, struct move_t *ml) -{ - static const char *wp[] = {" ", "\033[37m\033[1m P ", "\033[37m\033[1m N ", "\033[37m\033[1m B ", "\033[37m\033[1m R ", "\033[37m\033[1m A ", "\033[37m\033[1m C ", "\033[37m\033[1m M ", "\033[37m\033[1m Q ", "\033[37m\033[1m E ", "\033[37m\033[1m K "}; - static const char *bp[] = {" ", "\033[21m\033[37m P ", "\033[21m\033[37m N ", "\033[21m\033[37m B ", "\033[21m\033[37m R ", "\033[21m\033[37m A ", "\033[21m\033[37m C ", "\033[21m\033[37m M ", "\033[21m\033[37m Q ", "\033[21m\033[37m E ", "\033[21m\033[37m K "}; - static const char *wsqr = "\033[40m"; - static const char *bsqr = "\033[45m"; - static const char *top = "\t+------------------------+\n"; - static const char *mid = ""; - static const char *start = "|"; - static const char *end = "\033[0m|"; - static const char *label = "\t a b c d e f g h i j k l\n"; - static const char *blabel = "\t l k j i h g f e d c b a\n"; -return 0; - return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); -} - -/* Standard ICS */ -static int style1(struct game_state_t *b, struct move_t *ml) -{ +/* Experimental ANSI board for colour representation */ +static int style13(struct game_state_t *b, struct move_t *ml) +{ + static const char *wp[] = {" ", "\033[37m\033[1m P ", "\033[37m\033[1m N ", "\033[37m\033[1m B ", "\033[37m\033[1m R ", "\033[37m\033[1m A ", "\033[37m\033[1m C ", "\033[37m\033[1m M ", "\033[37m\033[1m Q ", "\033[37m\033[1m E ", "\033[37m\033[1m K "}; + static const char *bp[] = {" ", "\033[21m\033[37m P ", "\033[21m\033[37m N ", "\033[21m\033[37m B ", "\033[21m\033[37m R ", "\033[21m\033[37m A ", "\033[21m\033[37m C ", "\033[21m\033[37m M ", "\033[21m\033[37m Q ", "\033[21m\033[37m E ", "\033[21m\033[37m K "}; + static const char *wsqr = "\033[40m"; + static const char *bsqr = "\033[45m"; + static const char *top = "\t+------------------------+\n"; + static const char *mid = ""; + static const char *start = "|"; + static const char *end = "\033[0m|"; + static const char *label = "\t a b c d e f g h i j k l\n"; + static const char *blabel = "\t l k j i h g f e d c b a\n"; +return 0; + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Standard ICS */ +static int style1(struct game_state_t *b, struct move_t *ml) +{ static const char *wp[] = {" |", " P |", " N |", " B |", " R |", " A |", " C |", " M |", " Q |", " E |", " B |", " Q |", " W |", " H |", " N |", " D |", " H |", " L |", " C |", " S |", " G |", " H |", " A |", " F |", - " E |", " H |", " M |", " S |", " E |", " W |", " O |", " G |", " V |", " S |", " E |", " A |", " K |"}; + " E |", " H |", " M |", " S |", " E |", " W |", " O |", " G |", " V |", " S |", " E |", " A |", " K |", " H |", " E |"}; static const char *bp[] = {" |", " *P|", " *N|", " *B|", " *R|", " *A|", " *C|", " *M|", " *Q|", " *E|", " *B|", " *Q|", " *W|", " *H|", " *N|", " *D|", " *H|", " *L|", " *C|", " *S|", " *G|", " *H|", " *A|", " *F|", - " *E|", " *H|", " *M|", " *S|", " *E|", " *W|", " *O|", " *G|", " *V|", " *S|", " *E|", " *A|", " *K|"}; - static char *wsqr = ""; - static char *bsqr = ""; - static char *top = "\t---------------------------------\n"; - static char *mid = "\t|---+---+---+---+---+---+---+---|\n"; - static char *start = "|"; - static char *end = ""; - static char *label = "\t a b c d e f g h i j k l\n"; - static char *blabel = "\t l k j i h g f e d c b a\n"; - - return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); -} - -/* USA-Today Sports Center-style board */ -static int style2(struct game_state_t *b, struct move_t *ml) -{ + " *E|", " *H|", " *M|", " *S|", " *E|", " *W|", " *O|", " *G|", " *V|", " *S|", " *E|", " *A|", " *K|", " *H|", " *E|"}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = "\t---------------------------------\n"; + static char *mid = "\t|---+---+---+---+---+---+---+---|\n"; + static char *start = "|"; + static char *end = ""; + static char *label = "\t a b c d e f g h i j k l\n"; + static char *blabel = "\t l k j i h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* USA-Today Sports Center-style board */ +static int style2(struct game_state_t *b, struct move_t *ml) +{ static const char *wp[] = {"- ", "P ", "N ", "B ", "R ", "A ", "C ", "M ", "Q ", "E ", "B ", "Q ", "W ", "H ", "N ", "D ", "H ", "L ", "C ", "S ", "G ", "H ", "A ", "F ", - "E ", "H ", "M ", "S ", "E ", "W ", "O ", "G ", "V ", "S ", "E ", "A ", "K "}; + "E ", "H ", "M ", "S ", "E ", "W ", "O ", "G ", "V ", "S ", "E ", "A ", "K ", "H ", "E "}; static const char *bp[] = {"+ ", "p' ", "n' ", "b' ", "r' ", "a' ", "c' ", "m' ", "q' ", "e' ", "b' ", "q' ", "w' ", "h' ", "n' ", "d' ", "h' ", "l' ", "c' ", "s' ", "g' ", "h' ", "a' ", "f' ", - "e' ", "h' ", "m' ", "s' ", "e' ", "w' ", "o' ", "g' ", "v' ", "s' ", "e' ", "a' ", "k' "}; - static char *wsqr = ""; - static char *bsqr = ""; - static char *top = ""; - static char *mid = ""; - static char *start = ""; - static char *end = ""; - static char *label = "\ta b c d e f g h i j k l\n"; - static char *blabel = "\tl k j i h g f e d c b a\n"; - - return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); -} - -/* Experimental vt-100 ANSI board for dark backgrounds */ -static int style3(struct game_state_t *b, struct move_t *ml) -{ + "e' ", "h' ", "m' ", "s' ", "e' ", "w' ", "o' ", "g' ", "v' ", "s' ", "e' ", "a' ", "k' ", "h' ", "e' "}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = ""; + static char *mid = ""; + static char *start = ""; + static char *end = ""; + static char *label = "\ta b c d e f g h i j k l\n"; + static char *blabel = "\tl k j i h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Experimental vt-100 ANSI board for dark backgrounds */ +static int style3(struct game_state_t *b, struct move_t *ml) +{ static const char *wp[] = {" ", " P ", " N ", " B ", " R ", " A ", " C ", " M ", " Q ", " E ", " B ", " Q ", " W ", " H ", " N ", " D ", " H ", " L ", " C ", " S ", " G ", " H ", " A ", " F ", - " E ", " H ", " M ", " S ", " E ", " W ", " O ", " G ", " V ", " S ", " E ", " A ", " K "}; + " E ", " H ", " M ", " S ", " E ", " W ", " O ", " G ", " V ", " S ", " E ", " A ", " K ", " H ", " E "}; static const char *bp[] = {" ", " *P", " *N", " *B", " *R", " *A", " *C", " *M", " *Q", " *E", " *B", " *Q", " *W", " *H", " *N", " *D", " *H", " *L", " *C", " *S", " *G", " *H", " *A", " *F", - " *E", " *H", " *M", " *S", " *E", " *W", " *O", " *G", " *V", " *S", " *E", " *A", " *K"}; - static char *wsqr = "\033[0m"; - static char *bsqr = "\033[7m"; - static char *top = "\t+------------------------+\n"; - static char *mid = ""; - static char *start = "|"; - static char *end = "\033[0m|"; - static char *label = "\t a b c d e f g h i j k l\n"; - static char *blabel = "\t l k j i h g f e d c b a\n"; - - return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); -} - -/* Experimental vt-100 ANSI board for light backgrounds */ -static int style4(struct game_state_t *b, struct move_t *ml) -{ + " *E", " *H", " *M", " *S", " *E", " *W", " *O", " *G", " *V", " *S", " *E", " *A", " *K", " *H", " *E"}; + static char *wsqr = "\033[0m"; + static char *bsqr = "\033[7m"; + static char *top = "\t+------------------------+\n"; + static char *mid = ""; + static char *start = "|"; + static char *end = "\033[0m|"; + static char *label = "\t a b c d e f g h i j k l\n"; + static char *blabel = "\t l k j i h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Experimental vt-100 ANSI board for light backgrounds */ +static int style4(struct game_state_t *b, struct move_t *ml) +{ static const char *wp[] = {" ", " P ", " N ", " B ", " R ", " A ", " C ", " M ", " Q ", " E ", " B ", " Q ", " W ", " H ", " N ", " D ", " H ", " L ", " C ", " S ", " G ", " H ", " A ", " F ", - " E ", " H ", " M ", " S ", " E ", " W ", " O ", " G ", " V ", " S ", " E ", " A ", " K "}; + " E ", " H ", " M ", " S ", " E ", " W ", " O ", " G ", " V ", " S ", " E ", " A ", " K ", " H ", " E "}; static const char *bp[] = {" ", " *P", " *N", " *B", " *R", " *A", " *C", " *M", " *Q", " *E", " *B", " *Q", " *W", " *H", " *N", " *D", " *H", " *L", " *C", " *S", " *G", " *H", " *A", " *F", - " *E", " *H", " *M", " *S", " *E", " *W", " *O", " *G", " *V", " *S", " *E", " *A", " *K"}; - static char *wsqr = "\033[7m"; - static char *bsqr = "\033[0m"; - static char *top = "\t+------------------------+\n"; - static char *mid = ""; - static char *start = "|"; - static char *end = "\033[0m|"; - static char *label = "\t a b c d e f g h i j k l\n"; - static char *blabel = "\t l k j i h g f e d c b a\n"; - - return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); -} - -/* Style suggested by ajpierce@med.unc.edu */ -static int style5(struct game_state_t *b, struct move_t *ml) -{ + " *E", " *H", " *M", " *S", " *E", " *W", " *O", " *G", " *V", " *S", " *E", " *A", " *K", " *H", " *E"}; + static char *wsqr = "\033[7m"; + static char *bsqr = "\033[0m"; + static char *top = "\t+------------------------+\n"; + static char *mid = ""; + static char *start = "|"; + static char *end = "\033[0m|"; + static char *label = "\t a b c d e f g h i j k l\n"; + static char *blabel = "\t l k j i h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Style suggested by ajpierce@med.unc.edu */ +static int style5(struct game_state_t *b, struct move_t *ml) +{ static const char *wp[] = {" ", " o ", " :N:", " ", " |R|", " (A)", " [C]", " :M:", " {Q}", " !E!", " ", " {Q}", " .W.", " :H:", " :N:", " ", " |D|", " |L|", " |C|", " !S!", " :G:", " :H:", " {A}", " {F}", " !E!", " (H)", " [M]", " :S:", - " !E!", " |W|", " *O*", " {G}", " :V:", " (S)", " [E]", " &A&", " =K="}; + " !E!", " |W|", " *O*", " {G}", " :V:", " (S)", " [E]", " &A&", " =K=", " (H)", " [E]"}; static const char *bp[] = {" ", " p ", " :n:", " ", " |r|", " (a)", " [c]", " :m:", " {q}", " !e!", " ", " {q}", " .w.", " :h:", " :n:", " ", " |d|", " |l|", " |c|", " !s!", " :g:", " :h:", " {a}", " {f}", " !e!", " (h)", " [m]", " :s:", - " !e!", " |w|", " *o*", " {g}", " :v:", " (s)", " [e]", " &a&", " =k="}; - static char *wsqr = ""; - static char *bsqr = ""; - static char *top = " . . . . . . . . .\n"; - static char *mid = " . . . . . . . . .\n"; - static char *start = ""; - static char *end = ""; - static char *label = "\t a b c d e f g h i j k l\n"; - static char *blabel = "\t l k j i h g f e d c b a\n"; - - return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); -} - -/* Email Board suggested by Thomas Fought (tlf@rsch.oclc.org) */ -static int style6(struct game_state_t *b, struct move_t *ml) -{ + " !e!", " |w|", " *o*", " {g}", " :v:", " (s)", " [e]", " &a&", " =k=", " (f)", " [e]"}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = " . . . . . . . . .\n"; + static char *mid = " . . . . . . . . .\n"; + static char *start = ""; + static char *end = ""; + static char *label = "\t a b c d e f g h i j k l\n"; + static char *blabel = "\t l k j i h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Email Board suggested by Thomas Fought (tlf@rsch.oclc.org) */ +static int style6(struct game_state_t *b, struct move_t *ml) +{ static const char *wp[] = {" |", " wp |", " WN |", " WB |", " WR |", " WA |", " WC |", " WM |", " WQ |", " WE |", " WB |", " WQ |", " WW |", " WH |", " WN |", " WD |", " WH |", " WL |", " WC |", " WS |", " WG |", " WH |", " WA |", " WF |", " WE |", " WH |", " WM |", - " WS |", " WE |", " WW |", " WO |", " WG |", " WV |", " WS |", " WE |", " WA |", " WK |"}; + " WS |", " WE |", " WW |", " WO |", " WG |", " WV |", " WS |", " WE |", " WA |", " WK |", " WH |", " WE |"}; static const char *bp[] = {" |", " bp |", " BN |", " BB |", " BR |", " BA |", " BC |", " BM |", " BQ |", " BE |", " BB |", " BQ |", " BW |", " BH |", " BN |", " BD |", " BH |", " BL |", " BC |", " BS |", " BG |", " BH |", " BA |", " BF |", " BE |", " BH |", " BM |", - " BS |", " BE |", " BW |", " BO |", " BG |", " BV |", " BS |", " BE |", " BA |", " BK |"}; - static char *wsqr = ""; - static char *bsqr = ""; - static char *top = "\t-----------------------------------------\n"; - static char *mid = "\t-----------------------------------------\n"; - static char *start = "|"; - static char *end = ""; - static char *label = "\t A B C D E F G H I J K L\n"; - static char *blabel = "\t L K J I H G F E D C B A\n"; - - return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); -} - -/* Miniature board */ -static int style7(struct game_state_t *b, struct move_t *ml) -{ + " BS |", " BE |", " BW |", " BO |", " BG |", " BV |", " BS |", " BE |", " BA |", " BK |", " BH |", " BE |"}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = "\t-----------------------------------------\n"; + + static char *mid = "\t-----------------------------------------\n"; + static char *start = "|"; + static char *end = ""; + static char *label = "\t A B C D E F G H I J K L\n"; + static char *blabel = "\t L K J I H G F E D C B A\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Miniature board */ +static int style7(struct game_state_t *b, struct move_t *ml) +{ static const char *wp[] = {" ", " P", " N", " B", " R", " A", " C", " M", " Q", " E", " B", " Q", " W", " H", " N", " D", " H", " L", - " C", " S", " G", " H", " A", " F", " E", " H", " M", " S", " E", " W", " O", " G", " V", " S", " E", " A", " K"}; + " C", " S", " G", " H", " A", " F", " E", " H", " M", " S", " E", " W", " O", " G", " V", " S", " E", " A", " K", " H", " E"}; static const char *bp[] = {" -", " p", " n", " b", " r", " a", " c", " m", " q", " e", " b", " q", " w", " h", " n", " d", " h", " l", - " c", " s", " g", " h", " a", " f", " e", " h", " m", " s", " e", " w", " o", " g", " v", " s", " e", " a", " k"}; - static char *wsqr = ""; - static char *bsqr = ""; - static char *top = "\t:::::::::::::::::::::\n"; - static char *mid = ""; - static char *start = ".."; - static char *end = " .."; - static char *label = "\t a b c d e f g h i j k l\n"; - static char *blabel = "\t l k j i h g f e d c b a\n"; - - return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); -} - -/* ICS interface maker board-- raw data dump */ -static int style8(struct game_state_t *b, struct move_t *ml) -{ - char tmp[160]; - int f, r; - int ws, bs; - - board_calc_strength(b, &ws, &bs); - sprintf(tmp, "#@#%03d%-16s%s%-16s%s", b->gameNum + 1, - game_globals.garray[b->gameNum].white_name, - (orient == WHITE) ? "*" : ":", - game_globals.garray[b->gameNum].black_name, - (orient == WHITE) ? ":" : "*"); - strcat(bstring, tmp); - for (r = 0; r < b->ranks; r++) { - for (f = 0; f < b->files; f++) { - if (b->board[f][r] == NOPIECE) { - strcat(bstring, " "); - } else { - if (colorval(b->board[f][r]) == WHITE) - strcat(bstring, wpstring[piecetype(b->board[f][r])]); - else - strcat(bstring, bpstring[piecetype(b->board[f][r])]); - } - } - } - sprintf(tmp, "%03d%s%02d%02d%05d%05d%-7s(%s)@#@\n", - game_globals.garray[b->gameNum].numHalfMoves / 2 + 1, - (b->onMove == WHITE) ? "W" : "B", - ws, - bs, - (wTime + 5) / 10, - (bTime + 5) / 10, - game_globals.garray[b->gameNum].numHalfMoves ? - ml[game_globals.garray[b->gameNum].numHalfMoves - 1].algString : - "none", - game_globals.garray[b->gameNum].numHalfMoves ? - tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : - "0:00"); - strcat(bstring, tmp); - return 0; -} - -/* last 2 moves only (previous non-verbose mode) */ -static int style9(struct game_state_t *b, struct move_t *ml) -{ - int i, count; - char tmp[160]; - int startmove; - - sprintf(tmp, "\nMove %-23s%s\n", - game_globals.garray[b->gameNum].white_name, - game_globals.garray[b->gameNum].black_name); - strcat(bstring, tmp); - sprintf(tmp, "---- -------------- --------------\n"); - strcat(bstring, tmp); - startmove = ((game_globals.garray[b->gameNum].numHalfMoves - 3) / 2) * 2; - if (startmove < 0) - startmove = 0; - for (i = startmove, count = 0; - i < game_globals.garray[b->gameNum].numHalfMoves && count < 4; - i++, count++) { - if (!(i & 0x01)) { - sprintf(tmp, " %2d ", i / 2 + 1); - strcat(bstring, tmp); - } - sprintf(tmp, "%-23s", move_and_time(&ml[i])); - strcat(bstring, tmp); - if (i & 0x01) - strcat(bstring, "\n"); - } - if (i & 0x01) - strcat(bstring, "\n"); - return 0; -} - -/* Sleator's 'new and improved' raw dump format... */ -static int style10(struct game_state_t *b, struct move_t *ml) -{ - int f, r; - char tmp[160]; - int ws, bs; - - board_calc_strength(b, &ws, &bs); - sprintf(tmp, "<10>\n"); - strcat(bstring, tmp); - for (r = b->ranks-1; r >= 0; r--) { - strcat(bstring, "|"); - for (f = 0; f < b->files; f++) { - if (b->board[f][r] == NOPIECE) { - strcat(bstring, " "); - } else { - if (colorval(b->board[f][r]) == WHITE) - strcat(bstring, wpstring[piecetype(b->board[f][r])]); - else - strcat(bstring, bpstring[piecetype(b->board[f][r])]); - } - } - strcat(bstring, "|\n"); - } - strcat(bstring, (b->onMove == WHITE) ? "W " : "B "); - if (game_globals.garray[b->gameNum].numHalfMoves) { - sprintf(tmp, "%d ", - ml[game_globals.garray[b->gameNum].numHalfMoves - 1].doublePawn); - } else { - sprintf(tmp, "-1 "); - } - strcat(bstring, tmp); - sprintf(tmp, "%d %d %d %d %d\n", - (b->wkmoved >= 0 && b->wkrmoved >= 0), // [HGM] castle: inverted the logic, both must have rights - (b->wkmoved >= 0 && b->wqrmoved >= 0), - (b->bkmoved >= 0 && b->bkrmoved >= 0), - (b->bkmoved >= 0 && b->bqrmoved >= 0), - (game_globals.garray[b->gameNum].numHalfMoves - ((b->lastIrreversable == -1) ? 0 : - b->lastIrreversable))); - strcat(bstring, tmp); - sprintf(tmp, "%d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d\n", - b->gameNum, - game_globals.garray[b->gameNum].white_name, - game_globals.garray[b->gameNum].black_name, - myTurn, - game_globals.garray[b->gameNum].wInitTime / 600, - game_globals.garray[b->gameNum].wIncrement / 10, - ws, - bs, - (wTime + 5) / 10, - (bTime + 5) / 10, - game_globals.garray[b->gameNum].numHalfMoves / 2 + 1, - game_globals.garray[b->gameNum].numHalfMoves ? - ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString : - "none", - game_globals.garray[b->gameNum].numHalfMoves ? - tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : - "0:00", - game_globals.garray[b->gameNum].numHalfMoves ? - ml[game_globals.garray[b->gameNum].numHalfMoves - 1].algString : - "none", - (orient == WHITE) ? 0 : 1); - strcat(bstring, tmp); - sprintf(tmp, ">10<\n"); - strcat(bstring, tmp); - return 0; -} - -/* Same as 8, but with verbose moves ("P/e3-e4", instead of "e4") */ -static int style11(struct game_state_t *b, struct move_t *ml) -{ - char tmp[160]; - int f, r; - int ws, bs; - - board_calc_strength(b, &ws, &bs); - sprintf(tmp, "#@#%03d%-16s%s%-16s%s", b->gameNum, - game_globals.garray[b->gameNum].white_name, - (orient == WHITE) ? "*" : ":", - game_globals.garray[b->gameNum].black_name, - (orient == WHITE) ? ":" : "*"); - strcat(bstring, tmp); - for (r = 0; r < b->ranks; r++) { - for (f = 0; f < b->files; f++) { - if (b->board[f][r] == NOPIECE) { - strcat(bstring, " "); - } else { - if (colorval(b->board[f][r]) == WHITE) - strcat(bstring, wpstring[piecetype(b->board[f][r])]); - else - strcat(bstring, bpstring[piecetype(b->board[f][r])]); - } - } - } - sprintf(tmp, "%03d%s%02d%02d%05d%05d%-7s(%s)@#@\n", - game_globals.garray[b->gameNum].numHalfMoves / 2 + 1, - (b->onMove == WHITE) ? "W" : "B", - ws, - bs, - (wTime + 5) / 10, - (bTime + 5) / 10, - game_globals.garray[b->gameNum].numHalfMoves ? - ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString : - "none", - game_globals.garray[b->gameNum].numHalfMoves ? - tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : - "0:00"); - strcat(bstring, tmp); - return 0; -} - - -int kludgeFlag = 0; -/* Similar to style 10. See the "style12" help file for information */ -static int style12(struct game_state_t *b, struct move_t *ml) -{ - int f, r; - char tmp[160]; // [HGM] 80 caused problems with long login names + " c", " s", " g", " h", " a", " f", " e", " h", " m", " s", " e", " w", " o", " g", " v", " s", " e", " a", " k", " h", " e"}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = "\t:::::::::::::::::::::\n"; + static char *mid = ""; + static char *start = ".."; + static char *end = " .."; + static char *label = "\t a b c d e f g h i j k l\n"; + static char *blabel = "\t l k j i h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* ICS interface maker board-- raw data dump */ +static int style8(struct game_state_t *b, struct move_t *ml) +{ + char tmp[160]; + int f, r; + int ws, bs; + + board_calc_strength(b, &ws, &bs); + sprintf(tmp, "#@#%03d%-16s%s%-16s%s", b->gameNum + 1, + game_globals.garray[b->gameNum].white_name, + (orient == WHITE) ? "*" : ":", + game_globals.garray[b->gameNum].black_name, + (orient == WHITE) ? ":" : "*"); + strcat(bstring, tmp); + for (r = 0; r < b->ranks; r++) { + for (f = 0; f < b->files; f++) { + if (b->board[f][r] == NOPIECE) { + strcat(bstring, " "); + } else { + if (colorval(b->board[f][r]) == WHITE) + strcat(bstring, wpstring[piecetype(b->board[f][r])]); + else + strcat(bstring, bpstring[piecetype(b->board[f][r])]); + } + } + } + sprintf(tmp, "%03d%s%02d%02d%05d%05d%-7s(%s)@#@\n", + game_globals.garray[b->gameNum].numHalfMoves / 2 + 1, + (b->onMove == WHITE) ? "W" : "B", + ws, + bs, + (wTime + 5) / 10, + (bTime + 5) / 10, + game_globals.garray[b->gameNum].numHalfMoves ? + ml[game_globals.garray[b->gameNum].numHalfMoves - 1].algString : + "none", + game_globals.garray[b->gameNum].numHalfMoves ? + tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : + "0:00"); + strcat(bstring, tmp); + return 0; +} + +/* last 2 moves only (previous non-verbose mode) */ +static int style9(struct game_state_t *b, struct move_t *ml) +{ + int i, count; + char tmp[160]; + int startmove; + + sprintf(tmp, "\nMove %-23s%s\n", + game_globals.garray[b->gameNum].white_name, + game_globals.garray[b->gameNum].black_name); + strcat(bstring, tmp); + sprintf(tmp, "---- -------------- --------------\n"); + strcat(bstring, tmp); + startmove = ((game_globals.garray[b->gameNum].numHalfMoves - 3) / 2) * 2; + if (startmove < 0) + startmove = 0; + for (i = startmove, count = 0; + i < game_globals.garray[b->gameNum].numHalfMoves && count < 4; + i++, count++) { + if (!(i & 0x01)) { + sprintf(tmp, " %2d ", i / 2 + 1); + strcat(bstring, tmp); + } + sprintf(tmp, "%-23s", move_and_time(&ml[i])); + strcat(bstring, tmp); + if (i & 0x01) + strcat(bstring, "\n"); + } + if (i & 0x01) + strcat(bstring, "\n"); + return 0; +} + +/* Sleator's 'new and improved' raw dump format... */ +static int style10(struct game_state_t *b, struct move_t *ml) +{ + int f, r; + char tmp[160]; + int ws, bs; + + board_calc_strength(b, &ws, &bs); + sprintf(tmp, "<10>\n"); + strcat(bstring, tmp); + for (r = b->ranks-1; r >= 0; r--) { + strcat(bstring, "|"); + for (f = 0; f < b->files; f++) { + if (b->board[f][r] == NOPIECE) { + strcat(bstring, " "); + } else { + if (colorval(b->board[f][r]) == WHITE) + strcat(bstring, wpstring[piecetype(b->board[f][r])]); + else + strcat(bstring, bpstring[piecetype(b->board[f][r])]); + } + } + strcat(bstring, "|\n"); + } + strcat(bstring, (b->onMove == WHITE) ? "W " : "B "); + if (game_globals.garray[b->gameNum].numHalfMoves) { + sprintf(tmp, "%d ", + ml[game_globals.garray[b->gameNum].numHalfMoves - 1].doublePawn); + } else { + sprintf(tmp, "-1 "); + } + strcat(bstring, tmp); + sprintf(tmp, "%d %d %d %d %d\n", + (b->wkmoved >= 0 && b->wkrmoved >= 0), // [HGM] castle: inverted the logic, both must have rights + (b->wkmoved >= 0 && b->wqrmoved >= 0), + (b->bkmoved >= 0 && b->bkrmoved >= 0), + (b->bkmoved >= 0 && b->bqrmoved >= 0), + (game_globals.garray[b->gameNum].numHalfMoves - ((b->lastIrreversable == -1) ? 0 : + b->lastIrreversable))); + strcat(bstring, tmp); + sprintf(tmp, "%d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d\n", + b->gameNum, + game_globals.garray[b->gameNum].white_name, + game_globals.garray[b->gameNum].black_name, + myTurn, + game_globals.garray[b->gameNum].wInitTime / 600, + game_globals.garray[b->gameNum].wIncrement / 10, + ws, + bs, + (wTime + 5) / 10, + (bTime + 5) / 10, + game_globals.garray[b->gameNum].numHalfMoves / 2 + 1, + game_globals.garray[b->gameNum].numHalfMoves ? + ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString : + "none", + game_globals.garray[b->gameNum].numHalfMoves ? + tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : + "0:00", + game_globals.garray[b->gameNum].numHalfMoves ? + ml[game_globals.garray[b->gameNum].numHalfMoves - 1].algString : + "none", + (orient == WHITE) ? 0 : 1); + strcat(bstring, tmp); + sprintf(tmp, ">10<\n"); + strcat(bstring, tmp); + return 0; +} + +/* Same as 8, but with verbose moves ("P/e3-e4", instead of "e4") */ +static int style11(struct game_state_t *b, struct move_t *ml) +{ + char tmp[160]; + int f, r; + int ws, bs; + + board_calc_strength(b, &ws, &bs); + sprintf(tmp, "#@#%03d%-16s%s%-16s%s", b->gameNum, + game_globals.garray[b->gameNum].white_name, + (orient == WHITE) ? "*" : ":", + game_globals.garray[b->gameNum].black_name, + (orient == WHITE) ? ":" : "*"); + strcat(bstring, tmp); + for (r = 0; r < b->ranks; r++) { + for (f = 0; f < b->files; f++) { + if (b->board[f][r] == NOPIECE) { + strcat(bstring, " "); + } else { + if (colorval(b->board[f][r]) == WHITE) + strcat(bstring, wpstring[piecetype(b->board[f][r])]); + else + strcat(bstring, bpstring[piecetype(b->board[f][r])]); + } + } + } + sprintf(tmp, "%03d%s%02d%02d%05d%05d%-7s(%s)@#@\n", + game_globals.garray[b->gameNum].numHalfMoves / 2 + 1, + (b->onMove == WHITE) ? "W" : "B", + ws, + bs, + (wTime + 5) / 10, + (bTime + 5) / 10, + game_globals.garray[b->gameNum].numHalfMoves ? + ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString : + "none", + game_globals.garray[b->gameNum].numHalfMoves ? + tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : + "0:00"); + strcat(bstring, tmp); + return 0; +} + + +int kludgeFlag = 0; +/* Similar to style 10. See the "style12" help file for information */ +static int style12(struct game_state_t *b, struct move_t *ml) +{ + int f, r; + char tmp[160]; // [HGM] 80 caused problems with long login names int ws, bs; int nhm = kludgeFlag ? 0 : game_globals.garray[b->gameNum].numHalfMoves; // [HGM] setup: the number of half moves appeared in this routine an enormous number of times, // and had to be dug out of the game_globals, so that this routine could only be used to print // a board from a game, and not just any board given by an isolated game_state_t. This was very // inconvenient for printing initial boards in move lists of shuffle variants, so I added the - // global kludgeFlag to signal that we want to print an initial position, and force nhm = 0. - - board_calc_strength(b, &ws, &bs); - - sprintf(bstring, "<12> "); - for (r = b->ranks-1; r >= 0; r--) { + // global kludgeFlag to signal that we want to print an initial position, and force nhm = 0. + + board_calc_strength(b, &ws, &bs); + + sprintf(bstring, "<12> "); + for (r = b->ranks-1; r >= 0; r--) { for (f = 0; f < b->files; f++) { - if (b->board[f][r] == NOPIECE) { - strcat(bstring, "-"); - } else { - if (colorval(b->board[f][r]) == WHITE) - strcat(bstring, wpstring[piecetype(b->board[f][r])]); - else - strcat(bstring, bpstring[piecetype(b->board[f][r])]); - } - } - strcat(bstring, " "); + if (b->board[f][r] == NOPIECE) { + strcat(bstring, "-"); + } else { + if (colorval(b->board[f][r]) == WHITE) + strcat(bstring, wpstring[piecetype(b->board[f][r])]); + else + strcat(bstring, bpstring[piecetype(b->board[f][r])]); + } + } + strcat(bstring, " "); + } + + strcat(bstring, (b->onMove == WHITE) ? "W " : "B "); + if (nhm) { + sprintf(tmp, "%d ", + ml[nhm - 1].doublePawn); + } else { + sprintf(tmp, "-1 "); } - - strcat(bstring, (b->onMove == WHITE) ? "W " : "B "); - if (nhm) { - sprintf(tmp, "%d ", - ml[nhm - 1].doublePawn); - } else { - sprintf(tmp, "-1 "); - } - strcat(bstring, tmp); - sprintf(tmp, "%d %d %d %d %d ", - (b->wkmoved >= 0 && b->wkrmoved >= 0), // [HGM] castle: inverted the logic, both must have rights - (b->wkmoved >= 0 && b->wqrmoved >= 0), - (b->bkmoved >= 0 && b->bkrmoved >= 0), - (b->bkmoved >= 0 && b->bqrmoved >= 0), - (nhm - ((b->lastIrreversable == -1) ? 0 : b->lastIrreversable))); strcat(bstring, tmp); - sprintf(tmp, "%d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d %d\n", - b->gameNum + 1, - game_globals.garray[b->gameNum].white_name, - game_globals.garray[b->gameNum].black_name, - myTurn, - game_globals.garray[b->gameNum].wInitTime / 600, - game_globals.garray[b->gameNum].wIncrement / 10, - ws, - bs, - (wTime / 10), - (bTime / 10), - nhm / 2 + 1, - nhm ? - ml[nhm - 1].moveString : - "none", - nhm ? - tenth_str(ml[nhm - 1].tookTime, 0) : - "0:00", - nhm ? - ml[nhm - 1].algString : - "none", (orient == WHITE) ? 0 : 1, - b->moveNum > 1 ? 1 : 0); /* ticking */ - - strcat(bstring, tmp); - return 0; -} + sprintf(tmp, "%d %d %d %d %d ", + (b->wkmoved >= 0 && b->wkrmoved >= 0), // [HGM] castle: inverted the logic, both must have rights + (b->wkmoved >= 0 && b->wqrmoved >= 0), + (b->bkmoved >= 0 && b->bkrmoved >= 0), + (b->bkmoved >= 0 && b->bqrmoved >= 0), + (nhm - ((b->lastIrreversable == -1) ? 0 : b->lastIrreversable))); + strcat(bstring, tmp); + sprintf(tmp, "%d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d %d\n", + b->gameNum + 1, + game_globals.garray[b->gameNum].white_name, + game_globals.garray[b->gameNum].black_name, + myTurn, + game_globals.garray[b->gameNum].wInitTime / 600, + game_globals.garray[b->gameNum].wIncrement / 10, + ws, + bs, + (wTime / 10), + (bTime / 10), + nhm / 2 + 1, + nhm ? + ml[nhm - 1].moveString : + "none", + nhm ? + tenth_str(ml[nhm - 1].tookTime, 0) : + "0:00", + nhm ? + ml[nhm - 1].algString : + "none", (orient == WHITE) ? 0 : 1, + b->moveNum > 1 ? 1 : 0); /* ticking */ + + strcat(bstring, tmp); + return 0; +} static int board_read_file(char *category, char *gname, struct game_state_t *gs) { @@ -1023,6 +1024,9 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs) case 'd': gs->drops = 1; break; + case 'g': + gs->drops = 2; + break; case 'h': gs->holdings = -1; // color-flip holdings break; @@ -1088,15 +1092,15 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs) case 'B': onPiece = BISHOP; break; - case 'A': - onPiece = CARDINAL; - break; - case 'C': - onPiece = MARSHALL; - break; - case 'M': - onPiece = MAN; - break; + case 'A': + onPiece = CARDINAL; + break; + case 'C': + onPiece = MARSHALL; + break; + case 'M': + onPiece = MAN; + break; case 'Q': onPiece = QUEEN; break; @@ -1175,41 +1179,48 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs) case 'K': onPiece = KING; break; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - onFile = c - 'a'; - if(onFile >= gs->files) { onFile = -1; break; } - onRank = -1; - break; + case 'D': + onPiece = SELEPHANT; + break; + case 'U': + onPiece = HAWK; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + onFile = c - 'a'; + if(onFile >= gs->files) { onFile = -1; break; } + onRank = -1; + break; case '@': - if (onColor >= 0 && onPiece >= 0) // allow placement in holdings + if (onColor >= 0 && onPiece >= 0) // allow placement in holdings gs->holding[onColor == BLACK][onPiece-1]++; - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '0': - onRank = c - '1' + (gs->ranks > 9); - if(onRank < 0 || onRank >= gs->ranks) { onRank = -1; break; } - if (onFile >= 0 && onColor >= 0 && onPiece >= 0) - gs->board[onFile][onRank] = onPiece | onColor; - break; case '#': + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '0': + onRank = c - '1' + (gs->ranks > 9); + if(onRank < 0 || onRank >= gs->ranks) { onRank = -1; break; } + if (onFile >= 0 && onColor >= 0 && onPiece >= 0) + gs->board[onFile][onRank] = onPiece | onColor; + break; + case '#': while (!feof(fp) && c != '\n') c = fgetc(fp); /* Comment line */ case '\n': diff --git a/lasker-2.2.3/src/board.h b/lasker-2.2.3/src/board.h index c1aa22f..611ff80 100644 --- a/lasker-2.2.3/src/board.h +++ b/lasker-2.2.3/src/board.h @@ -65,6 +65,9 @@ #define EMPRESS 34 #define AMAZON 35 #define KING 36 +#define HAWK 37 +#define SELEPHANT 38 +#define PIECES 39 #define MAX_BOARD_STRING_LENGTH 1280 /* Abitrarily 80 * 16 */ #define MAX_STYLES 13 @@ -103,6 +106,8 @@ #define W_MASTODON (MASTODON | WHITE) #define W_MAN2 (MAN2 | WHITE) #define W_NIGHTRIDER (NIGHTRIDER | WHITE) +#define W_HAWK (HAWK | WHITE) +#define W_SELEPHANT (SELEPHANT | WHITE) #define B_PAWN (PAWN | BLACK) #define B_KNIGHT (KNIGHT | BLACK) @@ -138,6 +143,8 @@ #define B_MASTODON (MASTODON | BLACK) #define B_MAN2 (MAN2 | BLACK) #define B_NIGHTRIDER (NIGHTRIDER | BLACK) +#define B_HAWK (HAWK | BLACK) +#define B_SELEPHANT (SELEPHANT | BLACK) #define isblack(p) ((p) & BLACK) #define iswhite(p) (!isblack(p)) @@ -146,7 +153,7 @@ #define colorval(p) ((p) & 0x80) #define square_color(r,f) ((((r)+(f)) & 0x01) ? BLACK : WHITE) -extern int pieceValues[KING+1]; +extern int pieceValues[PIECES]; #define BW 12 #define BH 10 @@ -156,7 +163,7 @@ typedef int board_t[BW][BH]; GENSTRUCT struct game_state_t { int board[BW][BH]; /* for bughouse */ - int holding[2][KING]; + int holding[2][PIECES]; /* For castling */ char wkmoved, wqrmoved, wkrmoved; char bkmoved, bqrmoved, bkrmoved; diff --git a/lasker-2.2.3/src/gameproc.c b/lasker-2.2.3/src/gameproc.c index b7aab88..52f42e2 100644 --- a/lasker-2.2.3/src/gameproc.c +++ b/lasker-2.2.3/src/gameproc.c @@ -434,6 +434,18 @@ static int was_promoted(struct game *g, int f, int r) return 0; } +static int is_virgin(struct game *g, int f, int r) +{ + int i; + + for (i = g->numHalfMoves-2; i > 0; i -= 2) { + if (g->moveList[i].toFile == f && g->moveList[i].toRank == r) { + return 0; + } + } + return 1; +} + int pIsPlaying (int p) { struct player *pp = &player_globals.parray[p]; @@ -561,7 +573,7 @@ void process_move(int p, char *command) } pp->promote = NOPIECE; // [HGM] this seemed to be uninitialized, which caused spurious promotion in Shogi if ((len = strlen(command)) > 1) { - if (command[len - 2] == '=') { + if (command[len - 2] == '=' || gg->gameState.drops == 2 && command[len - 2] == '/') { // [HGM] encode gating as promotion printf("promo '%s'\n", command); switch (tolower(command[strlen(command) - 1])) { case 'n': diff --git a/lasker-2.2.3/src/matchproc.c b/lasker-2.2.3/src/matchproc.c index 1e79943..88c0366 100644 --- a/lasker-2.2.3/src/matchproc.c +++ b/lasker-2.2.3/src/matchproc.c @@ -531,6 +531,9 @@ static int parse_match_string(int p, int* wt,int* bt,int* winc,int* binc, if(!strcmp("su", category)) { strcpy(category, "super"); } else + if(!strcmp("sc", category)) { + strcpy(category, "seirawan"); + } else if(!strcmp("sg", category)) { strcpy(category, "shogi"); } else diff --git a/lasker-2.2.3/src/movecheck.c b/lasker-2.2.3/src/movecheck.c index 8f0dd9c..6996d09 100644 --- a/lasker-2.2.3/src/movecheck.c +++ b/lasker-2.2.3/src/movecheck.c @@ -1296,7 +1296,7 @@ int legal_move(struct game_state_t * gs, if (fFile == ALG_DROP) { move_piece = fRank; - if(!gs->drops) return 0; // [HGM] variants: no drops in this variant + if(gs->drops != 1) return 0; // [HGM] variants: no drops in this variant if (move_piece == KING) return 0; if (gs->holding[gs->onMove==WHITE ? 0 : 1][move_piece-1] == 0) @@ -1387,10 +1387,12 @@ int legal_move(struct game_state_t * gs, case ROOK: legal = legal_rook_move(gs, fFile, fRank, tFile, tRank); break; + case HAWK: case CARDINAL: case PRINCESS: legal = legal_cardinal_move(gs, fFile, fRank, tFile, tRank); break; + case SELEPHANT: case MARSHALL: case EMPRESS: legal = legal_marshall_move(gs, fFile, fRank, tFile, tRank); @@ -1484,6 +1486,7 @@ int legal_move(struct game_state_t * gs, static int move_calculate(struct game_state_t * gs, struct move_t * mt, int promote) { struct game_state_t fakeMove; + int gating = 0; mt->pieceCaptured = gs->board[mt->toFile][mt->toRank]; mt->enPassant = 0; /* Don't know yet, let execute move take care @@ -1536,15 +1539,23 @@ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int prom int stm = colorval(gs->board[mt->fromFile][mt->fromRank]); if(!promote && (mt->toRank == 0 || mt->toRank == gs->ranks-1)) { // promotion obligatory, but not specified if(gs->promoType != 2) promote = QUEEN; else { // choose a default - for(promote=KING-1; promote>PAWN; promote--) if(gs->holding[stm == BLACK][promote-1]) break; + for(promote=PIECES-1; promote>PAWN; promote--) if(gs->holding[stm == BLACK][promote-1]) break; if(promote == PAWN) return MOVE_ILLEGAL; // nothing available } - } // if not obligatory, we defer unless promoton was explicitly specified! + } // if not obligatory, we defer unless promotion was explicitly specified! if(!gs->pawnDblStep && promote == PRINCESS) promote = MAN2; if(!gs->pawnDblStep && promote != FERZ2 && promote != MAN2) promote = FERZ; // [HGM] kludge to recognize shatranj // non-promotion can still be an option for deeper promotion zones mt->piecePromotionTo = promote ? (promote | stm) : NOPIECE; if(promote && gs->promoType == 2 && !gs->holding[stm == BLACK][promote-1]) return MOVE_ILLEGAL; // unavailable piece specified + } else if(gs->drops == 2 && promote && mt->fromRank == (stm == WHITE ? 0 : gs->ranks-1)) { // [HGM] Seirawan-style gating + int i; struct game *g = &game_globals.garray[gs->gameNum]; + if(!gs->holding[stm == BLACK][promote-1]) return MOVE_ILLEGAL; // unavailable piece specified + // now we must test virginity of the moved piece. Yegh! + for (i = g->numHalfMoves-2; i > 0; i -= 2) { + if (g->moveList[i].toFile == mt->fromFile && g->moveList[i].toRank == mt->fromRank) return MOVE_ILLEGAL; + } + gating = 1; // gating OK; remember we did it for check test } else { mt->piecePromotionTo = NOPIECE; } @@ -1579,6 +1590,7 @@ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int prom fakeMove = *gs; /* Calculates enPassant also */ execute_move(&fakeMove, mt, 0); + if(gating) fakeMove.board[mt-fromFile][mt->fromRank] = NOPIECE; // [HGM] gating is only legal if non-gating move was (weird, but true) /* Does making this move leave ME in check? */ if (in_check(&fakeMove)) @@ -1667,10 +1679,12 @@ int has_legal_move(struct game_state_t * gs) case ROOK: possible_rook_moves(gs, f, r, possiblef, possibler, &numpossible); break; + case HAWK: case CARDINAL: case PRINCESS: possible_cardinal_moves(gs, f, r, possiblef, possibler, &numpossible); break; + case SELEPHANT: case MARSHALL: case EMPRESS: possible_marshall_moves(gs, f, r, possiblef, possibler, &numpossible); @@ -1922,13 +1936,19 @@ int execute_move(struct game_state_t * gs, struct move_t * mt, int check_game_st } else { movedPiece = gs->board[mt->fromFile][mt->fromRank]; tookPiece = gs->board[mt->toFile][mt->toRank]; - if (mt->piecePromotionTo == NOPIECE) { + if(gs->drops == 2 && mt->piecePromotionTo != NOPIECE && pieceType(movedPiece) != PAWN) { // [HGM] Seirawan-style gating gs->board[mt->toFile][mt->toRank] = gs->board[mt->fromFile][mt->fromRank]; + gs->board[mt->fromFile][mt->fromRank] = mt->piecePromotionTo | gs->onMove;; + gs->holding[gs->onMove==WHITE ? 0 : 1][mt->piecePromotionTo-1]--; // remove gated piece from holdings } else { - gs->board[mt->toFile][mt->toRank] = mt->piecePromotionTo | gs->onMove; - if(gs->promoType == 2) gs->holding[gs->onMove][mt->piecePromotionTo-1]--; + if (mt->piecePromotionTo == NOPIECE) { + gs->board[mt->toFile][mt->toRank] = gs->board[mt->fromFile][mt->fromRank]; + } else { + gs->board[mt->toFile][mt->toRank] = mt->piecePromotionTo | gs->onMove; + if(gs->promoType == 2) gs->holding[gs->onMove][mt->piecePromotionTo-1]--; + } + gs->board[mt->fromFile][mt->fromRank] = NOPIECE; } - gs->board[mt->fromFile][mt->fromRank] = NOPIECE; /* Check if irreversable */ if ((piecetype(movedPiece) == PAWN) && (mt->fromRank != mt->toRank) // [HGM] XQ: sideway Pawn move reversible! || (tookPiece != NOPIECE)) { @@ -2243,6 +2263,9 @@ int backup_move(int g, int mode) goto cleanupMove; } gs->board[m->toFile][m->toRank] = m->pieceCaptured; + if(gs->board[m->fromFile][m->fromRank] != NOPIECE) { // [HGM] from-square occupied, must have been Seirawan-style gating + gs->holding[gs->onMove==WHITE ? 1 : 0][piecetype(gs->board[m->fromFile][m->fromRank])-1]++; // put back in holdings (onMove not flipped yet!) + } cleanupMove: if (game_globals.garray[g].status != GAME_EXAMINE) { game_update_time(g); -- 1.7.0.4