Finish implementation of Shogi
[capablanca.git] / lasker-2.2.3 / src / gameproc.c
index 7e2cd5d..ec6918c 100644 (file)
@@ -139,6 +139,11 @@ 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_RESIGN:
     sprintf(tmp, "%s resigns} %s", NameOfLoser, winSymbol);
     strcpy(EndSymbol, "Res");
@@ -335,7 +340,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 +413,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 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;
@@ -545,8 +559,10 @@ 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] == '=') {
+printf("promo '%s'\n", command);
       switch (tolower(command[strlen(command) - 1])) {
       case 'n':
        pp->promote = KNIGHT;
@@ -557,9 +573,49 @@ 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;
+      // Shogi promotions
+      case '^':
+      case '+':
+       pp->promote = GOLD;
+       break;
+      case '=':
+       pp->promote = NOPIECE;
+       break;
       default:
        pprintf(p, "Don't understand that move.\n");
        return;
@@ -567,6 +623,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 +690,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 +796,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)
@@ -1039,8 +1118,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: