Implement Grand Chess
authorH.G. Muller <h.g.muller@hccnet.nl>
Tue, 8 Mar 2011 18:24:46 +0000 (19:24 +0100)
committerH.G. Muller <h.g.muller@hccnet.nl>
Tue, 8 Mar 2011 18:24:46 +0000 (19:24 +0100)
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.

lasker-2.2.3/src/algcheck.c
lasker-2.2.3/src/board.c
lasker-2.2.3/src/board.h
lasker-2.2.3/src/movecheck.c

index cdc97b2..3efc4ce 100644 (file)
@@ -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;
   }
-  \r
   // [HGM] check if move does not stray off board\r
   if(gs->ranks < 10) { \r
     if(tr == 0 || fr == 0) return MOVE_ILLEGAL; // used nonexistent 0-rank\r
@@ -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;
index e60f659..6aa7524 100644 (file)
@@ -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\r
   if (!category || !board || !category[0] || !board[0]) \r
                                /* accounts for bughouse too */\r
@@ -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;
index a94a96e..c1aa22f 100644 (file)
@@ -181,6 +181,7 @@ GENSTRUCT struct game_state_t {
        char bareKingLoses;
        char stalemate;
        char promoType;
+       char promoZone;
        char variant[20];
 };
 
index 468a8a3..30405fa 100644 (file)
@@ -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\r
-      ((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 |\r
-      (colorval(gs->board[mt->fromFile][mt->fromRank]));\r
+    // 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 {\r
     mt->piecePromotionTo = NOPIECE;\r
   }\r
@@ -1569,7 +1577,7 @@ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int prom
 \r
   sprintf(mt->algString, alg_unparse(gs, mt));\r
   fakeMove = *gs;\r
-  /* Calculates enPassant also */\r
+  /* Calculates enPassant also */
   execute_move(&fakeMove, mt, 0);\r
 \r
   /* Does making this move leave ME in check? */\r
@@ -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
 \r
   if (mt->piecePromotionTo != NOPIECE) {
          promote = piecetype(mt->piecePromotionTo);\r
-printf("promotion piece = %d, type = %d",mt->piecePromotionTo, promote);\r
   }\r
 \r
   return move_calculate(gs, mt, promote);\r
@@ -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++) {\r
     gs->ep_possible[0][i] = 0;\r
     gs->ep_possible[1][i] = 0;\r
-  }\r
+  }
 /* 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;\r
   } else {\r
     gs->onMove = CToggle(gs->onMove);\r
-  }\r
+  }
+\r
   return MOVE_OK;\r
 }