X-Git-Url: http://winboard.nl/cgi-bin?p=capablanca.git;a=blobdiff_plain;f=lasker-2.2.3%2Fsrc%2Fgameproc.c;h=295aed6e3ee19b6ee43f7e322a97d7db8c0ee9d1;hp=7e2cd5d8d2d160c4e029f553325e6cec8db66d18;hb=c214e749e3e62f654061433589f3bcb7cd1aed14;hpb=76f1e81b3426b94e1d80c9daa309f78045e5335b diff --git a/lasker-2.2.3/src/gameproc.c b/lasker-2.2.3/src/gameproc.c index 7e2cd5d..295aed6 100644 --- a/lasker-2.2.3/src/gameproc.c +++ b/lasker-2.2.3/src/gameproc.c @@ -139,6 +139,16 @@ void game_ended(int g, int winner, int why) strcpy(EndSymbol, "Mat"); rate_change = 1; break; + case END_BARE: + sprintf(tmp, "%s bared} %s", NameOfLoser, winSymbol); + strcpy(EndSymbol, "Bar"); + rate_change = 1; + break; + case END_PERPETUAL: + sprintf(tmp, "%s perpetually checking} %s", NameOfLoser, winSymbol); + strcpy(EndSymbol, "Per"); + rate_change = 1; + break; case END_RESIGN: sprintf(tmp, "%s resigns} %s", NameOfLoser, winSymbol); strcpy(EndSymbol, "Res"); @@ -335,7 +345,7 @@ void game_ended(int g, int winner, int why) pprintf (p,"\n%s",avail_black); avail_printed = 1; } - if (gl != -1) /* bughouse ? */ { + if (gl == -1) /* bughouse ? */ { if (((player_globals.parray[game_globals.garray[gl].white].b_stats.rating <= pp->availmax) && (player_globals.parray[game_globals.garray[gl].white].b_stats.rating >= pp->availmin)) || (!pp->availmax)) { pprintf (p,"\n%s",avail_bugwhite); avail_printed = 1; @@ -408,8 +418,17 @@ static int was_promoted(struct game *g, int f, int r) for (i = g->numHalfMoves-2; i > 0; i -= 2) { if (g->moveList[i].toFile == f && g->moveList[i].toRank == r) { - if (g->moveList[i].piecePromotionTo) - return 1; + if (g->moveList[i].piecePromotionTo) { + switch(g->moveList[i].moveString[0]) { // [HGM] return original piece type rather than just TRUE + case 'P': return PAWN; + case 'N': return HONORABLEHORSE; // !!! this is Shogi, so no KNIGHT !!! + case 'B': return BISHOP; + case 'R': return ROOK; + case 'L': return LANCE; + case 'S': return SILVER; + default: return GOLD; + } + } if (g->moveList[i].fromFile == ALG_DROP) return 0; f = g->moveList[i].fromFile; @@ -511,7 +530,7 @@ void process_move(int p, char *command) { struct player *pp = &player_globals.parray[p]; struct game *gg; - int g, result, len, i; + int g, result, len, i, f; struct move_t move; unsigned now = 0; @@ -545,9 +564,11 @@ void process_move(int p, char *command) return; } } + pp->promote = NOPIECE; // [HGM] this seemed to be uninitialized, which caused spurious promotion in Shogi if ((len = strlen(command)) > 1) { - if (command[len - 2] == '=') { - switch (tolower(command[strlen(command) - 1])) { + if (command[len - 2] == '=' || gg->game_state.drops == 2 && command[len - 2] == '/') { // [HGM] encode gating as promotion +printf("promo '%s'\n", command); + switch (tolower(command[len - 1])) { case 'n': pp->promote = KNIGHT; break; @@ -557,9 +578,61 @@ void process_move(int p, char *command) case 'r': pp->promote = ROOK; break; + case 'a': + pp->promote = CARDINAL; + break; + case 'c': + pp->promote = MARSHALL; + break; + case 'm': + pp->promote = MAN; + break; case 'q': pp->promote = QUEEN; break; + // courier promotion + case 'f': + pp->promote = FERZ2; + break; + // Superchess promotions + case 'e': + pp->promote = EMPRESS; + break; + case 's': + pp->promote = PRINCESS; + break; + case 'v': + pp->promote = CENTAUR; + break; + case 'w': + pp->promote = WOODY; + break; + case 'o': + pp->promote = SQUIRREL; + break; + case 'g': + pp->promote = MASTODON; + break; + case 'l': + pp->promote = LIEUTENANT; + break; + case 'k': + pp->promote = KING; + break; + // Shogi promotions + case 'h': + pp->promote = DRAGONHORSE; + break; + case 'd': + pp->promote = DRAGONKING; + break; + case '^': + case '+': + pp->promote = GOLD; + break; + case '=': + pp->promote = NOPIECE; + break; default: pprintf(p, "Don't understand that move.\n"); return; @@ -567,6 +640,7 @@ void process_move(int p, char *command) } } } + switch (parse_move(command, &gg->game_state, &move, pp->promote)) { case MOVE_ILLEGAL: pprintf(p, "Illegal move.\n"); @@ -633,13 +707,19 @@ void process_move(int p, char *command) gg->moveList = (struct move_t *) realloc(gg->moveList, sizeof(struct move_t) * gg->moveListSize); } result = execute_move(&gg->game_state, &move, 1); - if (result == MOVE_OK && gg->link >= 0 && move.pieceCaptured != NOPIECE) { + if (result == MOVE_OK && (gg->link >= 0 || gg->game_state.holdings) && move.pieceCaptured != NOPIECE) { /* transfer captured piece to partner */ /* check if piece reverts to a pawn */ - if (was_promoted(&game_globals.garray[g], move.toFile, move.toRank)) - update_holding(gg->link, colorval(move.pieceCaptured) | PAWN); + int victim = move.pieceCaptured, partner = gg->link, demoted; + // [HGM] zh: if not Bughouse, the game_state.holdings field decides what happens + if(gg->link < 0) { + partner = g; // pieces stay with current board + if(gg->game_state.holdings == -1) victim ^= WHITE|BLACK; // flip color + } + if (demoted = was_promoted(&game_globals.garray[g], move.toFile, move.toRank)) + update_holding(partner, colorval(victim) | demoted); // [HGM] was_promoted now returns original piece type else - update_holding(gg->link, move.pieceCaptured); + update_holding(partner, victim); } now = tenth_secs(); move.atTime = now; @@ -733,6 +813,22 @@ void process_move(int p, char *command) game_ended(g, CToggle(gg->game_state.onMove), END_NOMATERIAL); } } + if (result == MOVE_BARE) { + if (gg->status == GAME_EXAMINE) { + int p1; + + for (p1 = 0; p1 < player_globals.p_num; p1++) { + if (player_globals.parray[p1].status != PLAYER_PROMPT) + continue; + if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) { + pprintf(p1, "%s bared.\n", + (gg->game_state.onMove == BLACK) ? "White" : "Black"); + } + } + } else { + game_ended(g, gg->game_state.onMove, END_BARE); + } + } } int com_resign(int p, param_list param) @@ -791,6 +887,26 @@ static int Check50MoveRule (int p, int g) return 0; } +static int perp_check(struct game g, int first, int third) +{ + struct game_state_t gs = g.game_state; // current position, both first and last of loop + int half_move, no_perp = 0; +printf("perp %d %d\n",first,third); + for(half_move=first+1; half_move= game_globals.garray[g].game_state.lastIrreversable - 1; move_num--) { pos = GetFENpos (g, move_num); - if (strlen(pos1) == strlen(pos) && !strcmp(pos1, pos)) - flag1++; - if (strlen(pos2) == strlen(pos) && !strcmp(pos2, pos)) - flag2++; + if (!(turn - move_num & 1) && strlen(pos1) == strlen(pos) && !strcmp(pos1, pos)) + flag1++ == 2 && (s1 = move_num); + if ( (turn - move_num & 1) && strlen(pos2) == strlen(pos) && !strcmp(pos2, pos)) + flag2++ == 2 && (s2 = move_num); // remember start of last two loops +printf("%2d. %d-%d '%s' '%s' '%s'\n", move_num, flag1, flag2, pos1,pos2,pos); } if (flag1 >= 3 || flag2 >= 3) { if ((pend = find_pend(pp->opponent, p, PEND_DRAW)) != NULL) { delete_pending(pend); decline_withdraw_offers(p, -1, -1,DO_DECLINE); } - game_ended(g, (game_globals.garray[g].white == p) ? BLACK : WHITE, END_REPETITION); + if(game_globals.garray[g].game_state.palace) { // [HGM] in Xiangqi we have to test for perpetuals to determine the outcome + if(flag2 >= 3) result = perp_check(game_globals.garray[g], s2, numPly); + else result = perp_check(game_globals.garray[g], s1, numPly - (pos2[0] != 0)); + if(result == END_NOTENDED) { + pprintf(p, "Perpetuals can be claimed only during the turn of the winner\n"); + return 1; + } + game_ended(g, (numPly&1) ? BLACK : WHITE, result); // stm wins + return 1; + } + game_ended(g, (game_globals.garray[g].white == p) ? BLACK : WHITE, result); return 1; } else return 0; @@ -1039,8 +1173,8 @@ static int player_has_mating_material(struct game_state_t *gs, int color) int piece; int minor_pieces = 0; - for (i = 0; i < 8; i++) - for (j = 0; j < 8; j++) { + for (i = 0; i < gs->files; i++) + for (j = 0; j < gs->ranks; j++) { piece = gs->board[i][j]; switch (piecetype(piece)) { case BISHOP: