Implement S-Chess
[capablanca.git] / lasker-2.2.3 / src / gameproc.c
index a0dba3f..52f42e2 100644 (file)
@@ -413,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 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;
@@ -425,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];
@@ -550,8 +571,9 @@ 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] == '=') {
+    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':
@@ -598,6 +620,20 @@ printf("promo '%s'\n", command);
       case 'g':
        pp->promote = MASTODON;
        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;
@@ -675,14 +711,14 @@ printf("promo '%s'\n", command);
     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 */
-      int victim = move.pieceCaptured, partner = gg->link;
+      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 (was_promoted(&game_globals.garray[g], move.toFile, move.toRank))
-        update_holding(partner, colorval(victim) | PAWN); // [HGM] todo: for Shogi we would have to demote differently!
+      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(partner, victim);
     }
@@ -872,13 +908,14 @@ static int CheckRepetition (int p, int g)
   if (game_globals.garray[g].numHalfMoves < 8)  /* can't have three repeats any quicker. */
     return 0;
 
-  for (move_num = game_globals.garray[g].game_state.lastIrreversable;
+  for (move_num = game_globals.garray[g].game_state.lastIrreversable - 1; // [HGM] FEN stored in moveList[numHalfMoves-1] !
        move_num < game_globals.garray[g].numHalfMoves - 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++;
+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) {