From: H.G. Muller Date: Tue, 8 Mar 2011 18:24:46 +0000 (+0100) Subject: Implement Grand Chess X-Git-Url: http://winboard.nl/cgi-bin?p=capablanca.git;a=commitdiff_plain;h=534b15b1773a6f879b0b83fb0cfa0b02b003813c Implement Grand Chess This required an extra game parameter to indicate the depth of the promotion zone. The character 'Z' in the board file sets this to 3. The promotion code had to be changed to allow for deferral when the last rank is not yet reached. A missing promo char now defaults to deferral when possible, and to the highest available piece if not. --- diff --git a/lasker-2.2.3/src/algcheck.c b/lasker-2.2.3/src/algcheck.c index cdc97b2..3efc4ce 100644 --- a/lasker-2.2.3/src/algcheck.c +++ b/lasker-2.2.3/src/algcheck.c @@ -199,6 +199,7 @@ static int get_move_info(const char *str, int *piece, int *ff, int *fr, int *tf, matchVal = i; nomatch:; } + if (matchVal != -1) return MS_ALG; else @@ -221,7 +222,6 @@ static void add_promotion(struct game_state_t *gs, const char *mstr, struct move if (s == NULL) { return; } - if(gs->promoType == 3) { // handle Shogi promotions piece = gs->board[mt->fromFile][mt->fromRank]; if(colorval(piece) == WHITE && mt->fromRank < gs->ranks - gs->ranks/3 @@ -250,7 +250,7 @@ static void add_promotion(struct game_state_t *gs, const char *mstr, struct move if (piecetype(gs->board[mt->fromFile][mt->fromRank]) != PAWN) { return; } - if (mt->toRank != gs->ranks-1 && mt->toRank != 0) { + if (mt->toRank < gs->ranks - gs->promoZone && mt->toRank >= gs->promoZone) { return; } @@ -305,9 +305,9 @@ static void add_promotion(struct game_state_t *gs, const char *mstr, struct move default: return; } - i = colorval(gs->board[mt->fromFile][mt->fromRank]) == WHITE ? 0 : 1; - if(piece >= WOODY && (gs->promoType != 2 || gs->holding[i][piece-1] == 0)) return; + 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 mt->piecePromotionTo = piece | colorval(gs->board[mt->fromFile][mt->fromRank]); } @@ -322,7 +322,6 @@ 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 @@ -431,7 +430,6 @@ int alg_parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt) // note that the interpretation Bxc4 is matched last, and has set piece to BISHOP continue; } - if (legal_andcheck_move(gs, f, r, tf, tr)) { if ((piecetype(gs->board[f][r]) == PAWN) && (f != tolower(mstr[0]) - 'a')) { continue; diff --git a/lasker-2.2.3/src/board.c b/lasker-2.2.3/src/board.c index e60f659..6aa7524 100644 --- a/lasker-2.2.3/src/board.c +++ b/lasker-2.2.3/src/board.c @@ -168,6 +168,7 @@ int board_init(int g,struct game_state_t *b, char *category, char *board) b->bareKingLoses = 0; 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 */ @@ -1035,6 +1036,10 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs) case 'S': gs->promoType = 3; // Shogi-type promotions break; + case 'Z': + gs->promoZone = 3; // for Grand Chess + gs->pawnDblStep = 2; + break; case 'F': gs->castlingStyle = 2; // FRC castling break; diff --git a/lasker-2.2.3/src/board.h b/lasker-2.2.3/src/board.h index a94a96e..c1aa22f 100644 --- a/lasker-2.2.3/src/board.h +++ b/lasker-2.2.3/src/board.h @@ -181,6 +181,7 @@ GENSTRUCT struct game_state_t { char bareKingLoses; char stalemate; char promoType; + char promoZone; char variant[20]; }; diff --git a/lasker-2.2.3/src/movecheck.c b/lasker-2.2.3/src/movecheck.c index 468a8a3..30405fa 100644 --- a/lasker-2.2.3/src/movecheck.c +++ b/lasker-2.2.3/src/movecheck.c @@ -1532,11 +1532,19 @@ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int prom } else if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == PAWN) && !gs->palace && // [HGM] XQ: no promotions in xiangqi - ((mt->toRank == 0) || (mt->toRank == gs->ranks-1))) { + ((mt->toRank < gs->promoZone) || (mt->toRank >= gs->ranks - gs->promoZone))) { + 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; + if(promote == PAWN) return MOVE_ILLEGAL; // nothing available + } + } // if not obligatory, we defer unless promoton was explicitly specified! if(!gs->pawnDblStep && promote == PRINCESS) promote = MAN2; if(!gs->pawnDblStep && promote != FERZ2 && promote != MAN2) promote = FERZ; // [HGM] kludge to recognize shatranj - mt->piecePromotionTo = promote | - (colorval(gs->board[mt->fromFile][mt->fromRank])); + // 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 { mt->piecePromotionTo = NOPIECE; } @@ -1569,7 +1577,7 @@ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int prom sprintf(mt->algString, alg_unparse(gs, mt)); fakeMove = *gs; - /* Calculates enPassant also */ + /* Calculates enPassant also */ execute_move(&fakeMove, mt, 0); /* Does making this move leave ME in check? */ @@ -1585,6 +1593,7 @@ int legal_andcheck_move(struct game_state_t * gs, int tFile, int tRank) { struct move_t mt; + if (!legal_move(gs, fFile, fRank, tFile, tRank)) return 0; mt.color = gs->onMove; @@ -1593,7 +1602,7 @@ int legal_andcheck_move(struct game_state_t * gs, mt.toFile = tFile; mt.toRank = tRank; /* This should take into account a pawn promoting to another piece */ - if (move_calculate(gs, &mt, QUEEN) == MOVE_OK) + if (move_calculate(gs, &mt, NOPIECE) == MOVE_OK) return 1; else return 0; @@ -1871,7 +1880,6 @@ int parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt, int pro if (mt->piecePromotionTo != NOPIECE) { promote = piecetype(mt->piecePromotionTo); -printf("promotion piece = %d, type = %d",mt->piecePromotionTo, promote); } return move_calculate(gs, mt, promote); @@ -1944,7 +1952,7 @@ int execute_move(struct game_state_t * gs, struct move_t * mt, int check_game_st for (i = 0; i < gs->files; i++) { gs->ep_possible[0][i] = 0; gs->ep_possible[1][i] = 0; - } + } /* Added by Sparky 3/16/95 From soso@Viktoria.drp.fmph.uniba.sk Thu Mar 16 13:08:51 1995 @@ -2058,7 +2066,8 @@ int execute_move(struct game_state_t * gs, struct move_t * mt, int check_game_st return MOVE_NOMATERIAL; } else { gs->onMove = CToggle(gs->onMove); - } + } + return MOVE_OK; }