X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=lasker-2.2.3%2Fsrc%2Fmovecheck.c;h=30405fa0635d7f1f40f40f0fd7012f6daa1a07e7;hb=d5de5c406540b053c30e9732ae6c7b93c594bf27;hp=953298c68a66748e98f7974aef7547e06479f9a5;hpb=707e46a1e2dba3ef53b97c63520d50f4ecc3996b;p=capablanca.git diff --git a/lasker-2.2.3/src/movecheck.c b/lasker-2.2.3/src/movecheck.c index 953298c..30405fa 100644 --- a/lasker-2.2.3/src/movecheck.c +++ b/lasker-2.2.3/src/movecheck.c @@ -141,7 +141,7 @@ int InitPieceLoop(board_t b, int *f, int *r, int color) static int legal_pawn_move( struct game_state_t *gs, int ff, int fr, int tf, int tr ) { if (ff == tf) { - if (gs->board[tf][tr] != NOPIECE && !gs->palace) return 0; // [HGM] XQ pawns can capture straight ahead + if (gs->board[tf][tr] != NOPIECE && !gs->palace && gs->promoType != 3) return 0; // [HGM] XQ and Shogi pawns can capture straight ahead if (gs->onMove == WHITE) { if (tr - fr == 1) return 1; if ((fr <= gs->pawnDblStep) && (tr - fr == 2) && gs->board[ff][fr+1]==NOPIECE) return 1; @@ -151,7 +151,7 @@ static int legal_pawn_move( struct game_state_t *gs, int ff, int fr, int tf, int } return 0; } - if (ff != tf) { /* Capture ? */ + if (ff != tf && gs->promoType != 3) { /* Capture ? ([HGM] but not in Shogi) */ if ((ff - tf != 1) && (tf - ff != 1)) return 0; if (gs->onMove == WHITE) { if(gs->palace) return (fr >= gs->ranks/2 && fr == tr); // [HGM] XQ promoted pawns @@ -218,7 +218,7 @@ static int legal_honorablehorse_move(struct game_state_t * gs, int ff, int fr, i dx = ff - tf; dy = fr - tr; - if (dy == gs->onMove == WHITE ? 2 : -2) { + if (dy == (gs->onMove == WHITE ? -2 : 2)) { if (abs(dx) == 1) return 1; } @@ -621,21 +621,23 @@ static void possible_pawn_moves(struct game_state_t * gs, int *posf, int *posr, int *numpos) { if (gs->onMove == WHITE) { - if (gs->board[onf][onr + 1] == NOPIECE || gs->palace) { + if (gs->board[onf][onr + 1] == NOPIECE || gs->palace || gs->promoType == 3) { add_pos(onf, onr + 1, posf, posr, numpos); if ((onr <= gs->pawnDblStep) && (gs->board[onf][onr + 2] == NOPIECE)) add_pos(onf, onr + 2, posf, posr, numpos); } if (onf > 0) { if (gs->board[onf - 1][onr + 1] != NOPIECE && - iscolor(gs->board[onf - 1][onr + 1], BLACK)) + iscolor(gs->board[onf - 1][onr + 1], BLACK) && + !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi add_pos(onf - 1, onr + 1, posf, posr, numpos); if(gs->palace && onr >= gs->ranks/2 && (gs->board[onf-1][onr] || iscolor(gs->board[onf-1][onr], BLACK))) add_pos(onf - 1, onr, posf, posr, numpos); // XQ promoted pawn } if (onf < gs->files-1) { if (gs->board[onf + 1][onr + 1] != NOPIECE && - iscolor(gs->board[onf + 1][onr + 1], BLACK)) + iscolor(gs->board[onf + 1][onr + 1], BLACK) && + !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi add_pos(onf + 1, onr + 1, posf, posr, numpos); if(gs->palace && onr >= gs->ranks/2 && (gs->board[onf+1][onr] || iscolor(gs->board[onf+1][onr], BLACK))) add_pos(onf + 1, onr, posf, posr, numpos); // XQ promoted pawn @@ -645,21 +647,23 @@ static void possible_pawn_moves(struct game_state_t * gs, if (gs->ep_possible[0][onf] == 1) add_pos(onf + 1, onr + 1, posf, posr, numpos); } else { - if (gs->board[onf][onr - 1] == NOPIECE || gs->palace) { + if (gs->board[onf][onr - 1] == NOPIECE || gs->palace || gs->promoType == 3) { add_pos(onf, onr - 1, posf, posr, numpos); if ((onr >= gs->ranks - gs->pawnDblStep - 1) && (gs->board[onf][onr - 2] == NOPIECE)) add_pos(onf, onr - 2, posf, posr, numpos); } if (onf > 0) { if (gs->board[onf - 1][onr - 1] != NOPIECE && - iscolor(gs->board[onf - 1][onr - 1], WHITE)) + iscolor(gs->board[onf - 1][onr - 1], WHITE) && + !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi add_pos(onf - 1, onr - 1, posf, posr, numpos); if(gs->palace && onr < gs->ranks/2 && !iscolor(gs->board[onf-1][onr], BLACK)) add_pos(onf - 1, onr, posf, posr, numpos); // XQ promoted pawn } if (onf < gs->files-1) { if (gs->board[onf + 1][onr - 1] != NOPIECE && - iscolor(gs->board[onf + 1][onr - 1], WHITE)) + iscolor(gs->board[onf + 1][onr - 1], WHITE) && + !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi add_pos(onf + 1, onr - 1, posf, posr, numpos); if(gs->palace && onr < gs->ranks/2 && !iscolor(gs->board[onf+1][onr], BLACK)) add_pos(onf + 1, onr, posf, posr, numpos); // XQ promoted pawn @@ -1299,6 +1303,21 @@ int legal_move(struct game_state_t * gs, return 0; if (gs->board[tFile][tRank] != NOPIECE) return 0; + if (gs->promoType == 3) { // Shogi + int r; + switch(move_piece) { + case PAWN: // check for own Pawn in same file + for(r=0; rranks; r++) if(gs->board[tFile][r] == (gs->onMove|PAWN)) return 0; + case LANCE: // Pawns and Lances not on last rank + if(gs->onMove == WHITE && tRank >= gs->ranks-1) return 0; + if(gs->onMove == BLACK && tRank < 1) return 0; + break; + case HONORABLEHORSE: // Knights at least two ranks from edge + if(gs->onMove == WHITE && tRank >= gs->ranks-2) return 0; + if(gs->onMove == BLACK && tRank < 2) return 0; + default: ; + } + } else if (move_piece == PAWN && (tRank == 0 || tRank == gs->ranks-1)) return 0; return 1; @@ -1479,13 +1498,53 @@ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int prom // [HGM] castle: generalized castling, fr and tr give from and to file of Rook. sprintf(mt->moveString, mt->toRank > mt->toFile ? "o-o-o" : "o-o"); } else { + if(gs->promoType == 3) { // Shogi-style promotions: not just Pawns, but many pieces can promote + int piece = gs->board[mt->fromFile][mt->fromRank]; + mt->piecePromotionTo = NOPIECE; + if(colorval(piece) == WHITE && mt->fromRank < gs->ranks - gs->ranks/3 + && mt->toRank < gs->ranks - gs->ranks/3 || + colorval(piece) == BLACK && mt->fromRank >= gs->ranks/3 + && mt->toRank >= gs->ranks/3 ) + promote = NOPIECE; // suppress promotion outside zone + if(promote) { // promotion piece determined by original, no matter what was requested + switch(piecetype(piece)) { + case PAWN: + case LANCE: + case HONORABLEHORSE: + case SILVER: + promote = GOLD; break; + case BISHOP: + promote = DRAGONHORSE; break; + case ROOK: + promote = DRAGONKING; break; + default: promote = NOPIECE; // not a promotion + } + } else + switch(piecetype(piece)) { // force mandatory promotions + case HONORABLEHORSE: + if(mt->toRank == 1 || mt->toRank == gs->files-2) promote = GOLD; + case PAWN: + case LANCE: + if(mt->toRank == 0 || mt->toRank == gs->files-1) promote = GOLD; + default: break; + } + if(promote) mt->piecePromotionTo = promote | (colorval(gs->board[mt->fromFile][mt->fromRank])); + } 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; } @@ -1518,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? */ @@ -1534,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; @@ -1542,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; @@ -1577,7 +1637,7 @@ int in_check(struct game_state_t * gs) } for (InitPieceLoop(gs->board, &f, &r, gs->onMove); NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) { - if (legal_move(gs, f, r, kf, kr)) { /* In Check? */ + if (legal_move(gs, f, r, kf, kr)) { /* In Check? */ return 1; } } @@ -1716,10 +1776,8 @@ int has_legal_move(struct game_state_t * gs) if(game_globals.garray[gs->gameNum].link < 0) { // we have no partner, so we must have something to drop now for(i=QUEEN; i>=PAWN; i--) - if(gs->holding[gs->onMove==WHITE ? 0 : 1][i-1]) break; - if(i > PAWN) return 1; // we have a non-Pawn to drop - // We have a Pawn, but check if it legal to drop it - if(i == PAWN && r != 0 && r != gs->ranks-1) return 1; // [HGM] todo: for Shogi there are extra conditions on Pawn drops! + if (legal_andcheck_move(gs, ALG_DROP, i, f, r)) return 1; + return 0; } return 1; } @@ -1820,7 +1878,7 @@ int parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt, int pro mt->fromFile = ALG_CASTLE; } - if (mt->piecePromotionTo != NOPIECE) { + if (mt->piecePromotionTo != NOPIECE) { promote = piecetype(mt->piecePromotionTo); } @@ -1894,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 @@ -2008,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; }