Implement Spartan Chess
[capablanca.git] / lasker-2.2.3 / src / gamedb.c
index 76aed03..da255dc 100644 (file)
@@ -30,7 +30,8 @@ static int game_zero(int g);
  
 const char *TypeStrings[NUM_GAMETYPES] = {"untimed", "blitz", "standard", 
                                          "nonstandard", "wild", "lightning", 
-                                         "bughouse"};
+                                         "bughouse", "gothic", "knightmate", 
+                                         "capablanca"};
 
 /* this method is awful! how about allocation as we need it and freeing
     afterwards! */
@@ -127,7 +128,7 @@ static char *game_time_str(int wt, int winc, int bt, int binc)
   return tstr;
 }
 
-const char *bstr[] = {"untimed", "blitz", "standard", "non-standard", "wild", "lightning", "Bughouse"};
+const char *bstr[] = {"untimed", "blitz", "standard", "non-standard", "wild", "lightning", "Bughouse", "Gothic", "Knightmate", "Capablanca"};
 
 const char *rstr[] = {"unrated", "rated"};
 
@@ -160,6 +161,12 @@ int game_isblitz(int wt, int winc, int bt, int binc,
   if(cat && cat[0]) {
     if (!strcmp(cat, "bughouse"))
       return TYPE_BUGHOUSE;
+    if (!strcmp(cat, "gothic"))
+      return TYPE_GOTHIC;
+    if (!strcmp(cat, "knightmate"))
+      return TYPE_KNIGHTMATE;
+    if (!strcmp(cat, "capablanca"))
+      return TYPE_CAPABLANCA;
     if (board && board[0]) {
       if (!strcmp(cat, "wild"))
         return TYPE_WILD;
@@ -247,7 +254,14 @@ void send_boards(int g)
 
        if ((game_globals.garray[g].status != GAME_SETUP) && 
            (check_kings(&game_globals.garray[g].game_state))) {
-               d_printf( "Game has invalid amount of kings.  Aborting...\n");
+               d_printf( "Game has invalid number of kings.  Aborting...\n");
+{ int f, r;
+d_printf("files = %d, ranks = %d\n", game_globals.garray[g].game_state.files, game_globals.garray[g].game_state.ranks);
+for(r=0; r<game_globals.garray[g].game_state.ranks; r++) {
+  for(f=0; f<game_globals.garray[g].game_state.files; f++)
+       d_printf("b[%d][%d]=%d\n",f,r,game_globals.garray[g].game_state.board[f][r]);
+}
+}
                game_finish(g);
                
                for (p = 0; p < player_globals.p_num; p++) {
@@ -344,6 +358,10 @@ char *EndString(int g, int personal)
     sprintf(endstr, "%s checkmated",
            game_globals.garray[g].winner == WHITE ? blackguy : whiteguy);
     break;
+  case END_BARE:
+    sprintf(endstr, "%s bared",
+           game_globals.garray[g].winner == WHITE ? blackguy : whiteguy);
+    break;
   case END_RESIGN:
     sprintf(endstr, "%s resigned",
            game_globals.garray[g].winner == WHITE ? blackguy : whiteguy);
@@ -423,6 +441,7 @@ const char *EndSym(int g)
        case END_RESIGN:
        case END_FLAG:
        case END_ADJWIN:
+       case END_BARE:
                return ((game_globals.garray[g].winner == WHITE) ? symbols[0] : symbols[1]);
                break;
        case END_AGREEDDRAW:
@@ -471,7 +490,8 @@ char *movesToString(int g, int pgn)
            "\n[Event \"%s %s %s game\"]\n"
            "[Site \"%s, %s\"]\n",
            config_get_tmp("SERVER_NAME"),
-           rstr[game_globals.garray[g].rated], bstr[game_globals.garray[g].type],
+           rstr[game_globals.garray[g].rated], /*bstr[game_globals.garray[g].type],*/ 
+           game_globals.garray[g].variant, // [HGM] allow more variation in game_types
            config_get_tmp("SERVER_NAME"),
            config_get_tmp("SERVER_LOCATION"));
     strftime(tmp, sizeof(tmp),
@@ -487,6 +507,19 @@ char *movesToString(int g, int pgn)
            "[BlackElo \"%d\"]\n",
            game_globals.garray[g].white_name, game_globals.garray[g].black_name, wr, br);
     strcat(gameString, tmp);
+    if(game_globals.garray[g].game_state.variant[0]) { // [HGM] variant: print variant tag
+        sprintf(tmp,
+           "[Variant \"%s\"]\n",
+           game_globals.garray[g].game_state.variant);
+        strcat(gameString, tmp);
+    }
+    if(game_globals.garray[g].game_state.setup) { // [HGM] setup: print the FEN
+        sprintf(tmp,
+           "[Setup \"1\"]\n"
+           "[FEN \"%s\"]\n",
+           game_globals.garray[g].FENstartPos);
+        strcat(gameString, tmp);
+    }
     sprintf(tmp,
            "[TimeControl \"%d+%d\"]\n"
            "[Mode \"ICS\"]\n"
@@ -511,6 +544,14 @@ char *movesToString(int g, int pgn)
        col = 0;
       }
       strcat(gameString, tmp);
+      if(moves[i].depth > 0) { // [HGM] computer game, add {score/depth} comment
+       if ((col += sprintf(tmp, "{%s%.2f/%d} ", moves[i].score > 0 ? "+" : "",
+                               moves[i].score, moves[i].depth)) > 70) {
+         strcat(gameString, "\n");
+         col = 0;
+       }
+       strcat(gameString, tmp);
+      }
     }
     strcat(gameString, "\n");
 
@@ -538,7 +579,8 @@ char *movesToString(int g, int pgn)
     } else {
       strcat(gameString, "\nUnrated ");
     }
-    strcat (gameString, TypeStrings[game_globals.garray[g].type]);
+//    strcat (gameString, TypeStrings[game_globals.garray[g].type]);
+    strcat (gameString, game_globals.garray[g].variant);
     strcat(gameString, " match, initial time: ");
     if ((game_globals.garray[g].bInitTime != game_globals.garray[g].wInitTime) || (game_globals.garray[g].wIncrement != game_globals.garray[g].bIncrement)) { /* different starting times */ 
       sprintf(tmp, "%d minutes, increment: %d seconds AND %d minutes, increment: %d seconds.\n\n", game_globals.garray[g].wInitTime / 600, game_globals.garray[g].wIncrement / 10, game_globals.garray[g].bInitTime / 600, game_globals.garray[g].bIncrement / 10);
@@ -546,6 +588,46 @@ char *movesToString(int g, int pgn)
       sprintf(tmp, "%d minutes, increment: %d seconds.\n\n", game_globals.garray[g].wInitTime / 600, game_globals.garray[g].wIncrement / 10);
     }
     strcat(gameString, tmp);
+
+    if(game_globals.garray[g].game_state.setup) { // [HGM] setup: print the initial position board
+       char *q; struct game_state_t initial_gs; struct move_t ml[600]; int r, f;
+
+       initial_gs.gameNum = g;
+       initial_gs.wkrmoved = 0; // [HGM] for some reason calling reset_board_vars() does not work here
+       initial_gs.wqrmoved = 0; //       so I just duplicated the code and pasted it here...
+       initial_gs.wkmoved = 0;
+       initial_gs.bkrmoved = 0;
+       initial_gs.bqrmoved = 0;
+       initial_gs.bkmoved = 0;
+       initial_gs.onMove = WHITE;
+       initial_gs.lastIrreversable = -1;
+       initial_gs.files = game_globals.garray[g].game_state.files;
+       initial_gs.ranks = game_globals.garray[g].game_state.ranks;
+       initial_gs.holdings = game_globals.garray[g].game_state.holdings;
+       strcpy(initial_gs.variant, game_globals.garray[g].game_state.variant);
+        for (f = 0; f < 2; f++) {
+          for (r = 0; r < initial_gs.files; r++)
+             initial_gs.ep_possible[f][r] = 0;
+          for (r = PAWN; r <= PIECES-1; r++)
+            initial_gs.holding[f][r-PAWN] = 0;
+       }
+       FEN_to_board(game_globals.garray[g].FENstartPos ,&initial_gs);
+
+       kludgeFlag = 1; // [HGM] setup: this is not thread safe. Must it be???
+       q = board_to_string(
+                     game_globals.garray[g].white_name,
+                     game_globals.garray[g].black_name,
+                     game_globals.garray[g].wTime,
+                     game_globals.garray[g].bTime,
+                     &initial_gs,
+                     ml,
+                     11,
+                     WHITE, 0, 0);
+       kludgeFlag = 0;
+
+        strcat(gameString, q);
+        strcat(gameString, "\n");
+    }
     sprintf(tmp, "Move  %-19s%-19s\n", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
     strcat(gameString, tmp);
     strcat(gameString, "----  ----------------   ----------------\n");
@@ -584,8 +666,78 @@ void game_disconnect(int g, int p)
   game_ended(g, (game_globals.garray[g].white == p) ? WHITE : BLACK, END_LOSTCONNECTION);
 }
 
-int CharToPiece(char c)
+int CharToPiece(char c, char *variant)
 {
+
+  if(variant) {
+    if(!strcmp(variant, "shogi")) {
+      switch(c) {
+       case 'N':
+         return W_HONORABLEHORSE;
+       case 'n':
+         return B_HONORABLEHORSE;
+       case 'L':
+         return W_LANCE;
+       case 'l':
+         return B_LANCE;
+       case 'S':
+         return W_SILVER;
+       case 's':
+         return B_SILVER;
+       case 'G':
+         return W_GOLD;
+       case 'g':
+         return B_GOLD;
+      }
+    } else if(!strcmp(variant, "xiangqi")) {
+      switch(c) {
+       case 'A':
+         return W_MANDARIN;
+       case 'a':
+         return B_MANDARIN;
+       case 'H':
+         return W_HORSE;
+       case 'h':
+         return B_HORSE;
+       case 'C':
+         return W_CANNON;
+       case 'c':
+         return B_CANNON;
+      }
+    } else if(!strcmp(variant, "super")) {
+      switch(c) {
+       case 'E':
+         return W_EMPRESS;
+       case 'e':
+         return B_EMPRESS;
+       case 'S':
+         return W_PRINCESS;
+       case 's':
+         return B_PRINCESS;
+       case 'Z':
+         return W_AMAZON;
+       case 'z':
+         return B_AMAZON;
+       case 'V':
+         return W_CENTAUR;
+       case 'v':
+         return B_CENTAUR;
+      }
+    } else if(!strcmp(variant, "spartan")) {
+      switch(c) {
+       case 'w':
+         return B_WARLORD;
+       case 'g':
+         return B_GENERAL;
+       case 'l':
+         return B_LIEUTENANT;
+       case 'c':
+         return B_CAPTAIN;
+       case 'h':
+         return B_HOPLITE;
+      }
+    }
+  }
   switch (c) {
   case 'P':
     return W_PAWN;
@@ -603,10 +755,32 @@ int CharToPiece(char c)
     return W_ROOK;
   case 'r':
     return B_ROOK;
+  case 'A':
+    return W_CARDINAL;
+  case 'a':
+    return B_CARDINAL;
+  case 'C':
+    return W_MARSHALL;
+  case 'c':
+    return B_MARSHALL;
+  case 'M':
+    return W_MAN;
+  case 'm':
+    return B_MAN;
   case 'Q':
     return W_QUEEN;
   case 'q':
     return B_QUEEN;
+  case 'E':
+    if(!strcmp(variant, "seirawan")) return W_ELEPHANT;
+    return W_ELEPHANT;
+  case 'e':
+    if(!strcmp(variant, "seirawan")) return B_ELEPHANT;
+    return B_ELEPHANT;
+  case 'H':
+    return W_HAWK;
+  case 'h':
+    return B_HAWK;
   case 'K':
     return W_KING;
   case 'k':
@@ -623,8 +797,10 @@ char PieceToChar(int piece)
   case B_PAWN:
     return 'p';
   case W_KNIGHT:
+  case W_HONORABLEHORSE:
     return 'N';
   case B_KNIGHT:
+  case B_HONORABLEHORSE:
     return 'n';
   case W_BISHOP:
     return 'B';
@@ -634,14 +810,101 @@ char PieceToChar(int piece)
     return 'R';
   case B_ROOK:
     return 'r';
+  case W_CARDINAL:
+  case W_MANDARIN:
+  case W_ALFIL2:
+    return 'A';
+  case B_CARDINAL:
+  case B_MANDARIN:
+  case B_ALFIL2:
+    return 'a';
+  case W_CANNON:
+  case W_MARSHALL:
+    return 'C';
+  case B_CAPTAIN:
+  case B_CANNON:
+  case B_MARSHALL:
+    return 'c';
+  case W_MAN:
+  case W_MINISTER:
+    return 'M';
+  case B_MAN:
+  case B_MINISTER:
+    return 'm';
   case W_QUEEN:
     return 'Q';
   case B_QUEEN:
     return 'q';
+  case W_SELEPHANT:
+  case W_ELEPHANT:
+  case W_EMPRESS:
+    return 'E';
+  case B_SELEPHANT:
+  case B_ELEPHANT:
+  case B_EMPRESS:
+    return 'e';
+  case W_ALFIL:
+    return 'B';
+  case B_ALFIL:
+    return 'b';
+  case W_FERZ:
+    return 'Q';
+  case B_FERZ:
+    return 'q';
+  case W_FERZ2:
+    return 'F';
+  case B_FERZ2:
+    return 'f';
+  case W_WAZIR:
+  case W_WOODY:
+    return 'W';
+  case B_WARLORD:
+  case B_WAZIR:
+  case B_WOODY:
+    return 'w';
+  case W_HAWK:
+  case W_HORSE:
+  case W_PRIESTESS:
+  case W_NIGHTRIDER:
+    return 'H';
+  case B_HAWK:
+  case B_HORSE:
+  case B_HOPLITE:
+  case B_PRIESTESS:
+  case B_NIGHTRIDER:
+    return 'h';
+  case W_SILVER:
+  case W_PRINCESS:
+  case W_MAN2:
+    return 'S';
+  case B_SILVER:
+  case B_PRINCESS:
+  case B_MAN2:
+    return 's';
+  case W_GOLD:
+  case W_MASTODON:
+    return 'G';
+  case B_GOLD:
+  case B_GENERAL:
+  case B_MASTODON:
+    return 'g';
+  case W_AMAZON:
+    return 'Z';
+  case B_AMAZON:
+    return 'z';
+  case W_CENTAUR:
+    return 'V';
+  case B_CENTAUR:
+    return 'v';
   case W_KING:
     return 'K';
   case B_KING:
     return 'k';
+  case W_LANCE:
+    return 'L';
+  case B_LIEUTENANT:
+  case B_LANCE:
+    return 'l';
   default:
     return ' ';
   }
@@ -779,7 +1042,10 @@ int game_read(int g, int wp, int bp)
   if (game_globals.garray[g].type == TYPE_BLITZ) {
     game_globals.garray[g].white_rating = player_globals.parray[wp].b_stats.rating;
     game_globals.garray[g].black_rating = player_globals.parray[bp].b_stats.rating;
-  } else if (game_globals.garray[g].type == TYPE_WILD) {
+  } else if (game_globals.garray[g].type == TYPE_WILD ||
+            game_globals.garray[g].type == TYPE_KNIGHTMATE ||
+            game_globals.garray[g].type == TYPE_CAPABLANCA ||
+            game_globals.garray[g].type == TYPE_GOTHIC) {
     game_globals.garray[g].white_rating = player_globals.parray[wp].w_stats.rating;
     game_globals.garray[g].black_rating = player_globals.parray[bp].w_stats.rating;
   } else if (game_globals.garray[g].type == TYPE_LIGHT) {
@@ -797,7 +1063,7 @@ int game_read(int g, int wp, int bp)
   if (!fp) {
     return -1;
   }
-  for (piece=PAWN; piece <= QUEEN; piece++) {
+  for (piece=PAWN; piece < KING; piece++) {
     game_globals.garray[g].game_state.holding[0][piece-PAWN]
       = game_globals.garray[g].game_state.holding[1][piece-PAWN] = 0;
   }
@@ -977,7 +1243,10 @@ static void write_g_out(int g, char *file, int maxlines, int isDraw,
     wr = player_globals.parray[wp].b_stats.rating;
     br = player_globals.parray[bp].b_stats.rating;
     type[1] = 'b';
-  } else if (game_globals.garray[g].type == TYPE_WILD) {
+  } else if (game_globals.garray[g].type == TYPE_WILD ||
+            game_globals.garray[g].type == TYPE_KNIGHTMATE ||
+            game_globals.garray[g].type == TYPE_CAPABLANCA ||
+            game_globals.garray[g].type == TYPE_GOTHIC) {
     wr = player_globals.parray[wp].w_stats.rating;
     br = player_globals.parray[bp].w_stats.rating;
     type[1] = 'w';
@@ -1412,10 +1681,10 @@ void game_write_complete(int g, int isDraw, char *EndSymbol)
        
        sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR,
                player_globals.parray[wp].login[0], player_globals.parray[wp].login, STATS_GAMES);
-       write_g_out(g, fname, 10, isDraw, EndSymbol, player_globals.parray[wp].name, &now);
+       write_g_out(g, fname, 40, isDraw, EndSymbol, player_globals.parray[wp].name, &now);
        sprintf(fname, "%s/player_data/%c/%s.%s", STATS_DIR,
                player_globals.parray[bp].login[0], player_globals.parray[bp].login, STATS_GAMES);
-       write_g_out(g, fname, 10, isDraw, EndSymbol, player_globals.parray[bp].name, &now);
+       write_g_out(g, fname, 40, isDraw, EndSymbol, player_globals.parray[bp].name, &now);
        
        if (isDraw)
                Result = -1;
@@ -1458,14 +1727,14 @@ static int check_kings(struct game_state_t *gs)
        int f, r;
        
        
-       for (f = 0; f < 8; f++) {
-               for (r = 0; r < 8; r++) {
+       for (f = 0; f < gs->files; f++) {
+               for (r = 0; r < gs->ranks; r++) {
                        if (gs->board[f][r] == B_KING) blackking++;
                        if (gs->board[f][r] == W_KING) whiteking++;
                }
        }
        
-       if (blackking == 1 && whiteking == 1) return 0; /* Perfect! */
+       if ((blackking == 1 || blackking == 2 && !strcmp(gs->variant, "spartan")) && whiteking == 1) return 0; /* Perfect! */
        
        return -1;
 }