Implement S-Chess
[capablanca.git] / lasker-2.2.3 / src / board.c
index 8fdbb0e..8c92473 100644 (file)
 #include "includes.h"
 
 
-const char *wpstring[] = {" ", "P", "N", "B", "R", "Q", "K"};
-static const char *bpstring[] = {" ", "p", "n", "b", "r", "q", "k"};
+const char *wpstring[] = {" ", "P", "N", "B", "R", "A", "C", "M", "Q", "E", "B", "Q", "W", "H", "N", "D", "H", "L", 
+                         "C", "S", "G", "H", "A", "F", "E", "H", "M", "S", "E", "W", "O", "G", "V", "S", "E", "A", "K", "H", "E"};
+const char *bpstring[] = {" ", "p", "n", "b", "r", "a", "c", "m", "q", "e", "b", "q", "w", "h", "n", "d", "h", "l", 
+                         "c", "s", "g", "h", "a", "f", "e", "h", "m", "s", "e", "w", "o", "g", "v", "s", "e", "a", "k", "h", "e"};
 
-static int pieceValues[7] = {0, 1, 3, 3, 5, 9, 0};
+int pieceValues[PIECES] = {0, 1, 3, 3, 5, 8, 9, 3, 9, 1, 1, 2, 2, 2, 1, 6, 5, 2, 3, 3, 3, 1, 5, 2, 1, 7, 7, 3, 3, 3, 7, 7, 7, 8, 9, 12, 0, 8, 9};
 
 static const int mach_type = (1<<7) | (1<<8) | (1<<9) | (1<<10) | (1<<11);
 #define IsMachineStyle(n) (((1<<(n)) & mach_type) != 0)
 
-static char bstring[MAX_BOARD_STRING_LEGTH];
+static char bstring[MAX_BOARD_STRING_LENGTH];
 
 static int board_read_file(char *category, char *gname, struct game_state_t *gs);
-static void wild_update(int style);
+static void wild_update(board_t b, int style);
 
 static int style1(struct game_state_t *b, struct move_t *ml);
 static int style2(struct game_state_t *b, struct move_t *ml);
@@ -71,14 +73,16 @@ static void reset_board_vars(struct game_state_t *gs)
 {
  int f,r;
 
+  if(gs->files <= 0) gs->files = 8; // [HGM] for pristine board, set default size
+  if(gs->ranks <= 0) gs->ranks = 8;
   for (f = 0; f < 2; f++) {
-    for (r = 0; r < 8; r++)
+    for (r = 0; r < BW; r++)
       gs->ep_possible[f][r] = 0;
-    for (r = PAWN; r <= QUEEN; r++)
+    for (r = PAWN; r <= PIECES-1; r++)
       gs->holding[f][r-PAWN] = 0;
   }
-  gs->wkmoved = gs->wqrmoved = gs->wkrmoved = 0;
-  gs->bkmoved = gs->bqrmoved = gs->bkrmoved = 0;
+  gs->wkmoved = gs->wqrmoved = gs->wkrmoved = -1; // [HGM] castle: no rights
+  gs->bkmoved = gs->bqrmoved = gs->bkrmoved = -1;
   gs->onMove = WHITE;
   gs->moveNum = 1;
   gs->lastIrreversable = -1;
@@ -89,8 +93,8 @@ void board_clear(struct game_state_t *gs)
 {
  int f,r;
 
- for (f = 0; f < 8; f++)
-    for (r = 0; r < 8; r++)
+ for (f = 0; f < BW; f++)
+    for (r = 0; r < BH; r++)
       gs->board[f][r] = NOPIECE;
  reset_board_vars(gs);
 }
@@ -99,48 +103,142 @@ void board_standard(struct game_state_t *gs)
 {
  int f,r;
 
- for (f = 0; f < 8; f++)
-    for (r = 2; r < 6; r++)
+ for (f = 0; f < BW; f++)
+    for (r = 0; r < BH; r++)
       gs->board[f][r] = NOPIECE;
- for (f = 0; f < 8; f++)
-   gs->board[f][1] = W_PAWN;
- for (f = 0; f < 8; f++)
+ for (f = 0; f < gs->files; f++)
+   gs->board[f][gs->ranks-7] = W_PAWN;
+ for (f = 0; f < gs->files; f++)
    gs->board[f][6] = B_PAWN;
  gs->board[0][0] = W_ROOK;
  gs->board[1][0] = W_KNIGHT;
  gs->board[2][0] = W_BISHOP; 
  gs->board[3][0] = W_QUEEN;
- gs->board[4][0] = W_KING;
- gs->board[5][0] = W_BISHOP;
- gs->board[6][0] = W_KNIGHT;
- gs->board[7][0] = W_ROOK;
- gs->board[0][7] = B_ROOK;
- gs->board[1][7] = B_KNIGHT;
- gs->board[2][7] = B_BISHOP;
- gs->board[3][7] = B_QUEEN;
- gs->board[4][7] = B_KING;
- gs->board[5][7] = B_BISHOP;
- gs->board[6][7] = B_KNIGHT;
- gs->board[7][7] = B_ROOK;
+ gs->board[gs->files/2][0] = W_KING;
+ gs->board[gs->files-3][0] = W_BISHOP;
+ gs->board[gs->files-2][0] = W_KNIGHT;
+ gs->board[gs->files-1][0] = W_ROOK;
+ gs->board[0][gs->ranks-1] = B_ROOK;
+ gs->board[1][gs->ranks-1] = B_KNIGHT;
+ gs->board[2][gs->ranks-1] = B_BISHOP;
+ gs->board[3][gs->ranks-1] = B_QUEEN;
+ gs->board[gs->files/2][gs->ranks-1] = B_KING;
+ gs->board[gs->files-3][gs->ranks-1] = B_BISHOP;
+ gs->board[gs->files-2][gs->ranks-1] = B_KNIGHT;
+ gs->board[gs->files-1][gs->ranks-1] = B_ROOK;
+#if 1
+ if(gs->files == 10) {
+  gs->board[6][0] = W_CARDINAL;
+  gs->board[4][0] = W_MARSHALL;
+  gs->board[6][gs->ranks-1] = B_CARDINAL;
+  gs->board[4][gs->ranks-1] = B_MARSHALL;
+ }
+ if(gs->royalKnight) {
+   gs->board[1][0] = W_MAN;
+   gs->board[gs->files-2][0] = W_MAN;
+   gs->board[1][gs->ranks-1] = B_MAN;
+   gs->board[gs->files-2][gs->ranks-1] = B_MAN;
+ }
+#endif
+
  reset_board_vars(gs);
+ // [HGM] castle: standard setup has rights for corner Rooks and central King
+ gs->wkmoved = gs->files/2;
+ gs->bkmoved = gs->files/2;
+ gs->wkrmoved = gs->files-1;
+ gs->bkrmoved = gs->files-1;
+ gs->wqrmoved = 0;
+ gs->bqrmoved = 0;
 }
 
 int board_init(int g,struct game_state_t *b, char *category, char *board)
 {
   int retval = 0;
-  int wval;
-
+  int wval, i, j;
+
+  b->files = b->ranks = 8;
+  b->pawnDblStep = (!category || strcmp(category, "shatranj")); 
+  b->royalKnight = (category && !strcmp(category, "knightmate"));
+  b->capablancaPieces = 0;
+  b->holdings = 0;
+  b->drops = 0;
+  b->castlingStyle = 1;
+  b->palace = 0;
+  b->setup = 0;
+  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
   if (!category || !board || !category[0] || !board[0]) 
                                /* accounts for bughouse too */
     board_standard(b);
   else {
-    if (!strcmp(category, "wild")) {
-      if (sscanf(board, "%d", &wval) == 1 && wval >= 1 && wval <= 4)
-        wild_update(wval);
+    if(category && category[0]) strcpy(b->variant, category); // [HGM] variant: remember category name
+    if (!strcmp(category, "wild") && sscanf(board, "%d", &wval) == 1) {
+       if(wval >= 1 && wval <= 4)
+            wild_update(b->board, wval);
+       sprintf(b->variant, "wild/%d", wval);
+    }
+
+    if (board && !strcmp(board, "0"))
+       b->setup = 0; // [HGM] variant: any board in the default file "0" is supposed to be implied by the variant
+
+    if (!strcmp(category, "knightmate")) {
+      board_standard(b);
+    } else if (!strcmp(category, "super")) {
+      board_standard(b);
+      b->holdings = 1;
+      b->promoType = 2;
+      for(i=CENTAUR; i<=AMAZON; i++) {
+       int placed = 0;
+       do { int p, newp;
+         j = random() % 8;
+         if((p = piecetype(b->board[j][0])) >= CENTAUR) continue; // includes King
+         b->holding[1][p-PAWN] = ++b->holding[0][p-PAWN]; // piece to holding
+         if(board && !strcmp(board, "1")) newp = i - CENTAUR + WOODY; else newp = i;
+         if(board && !strcmp(board, "2")) newp = WOODY + random()%7;
+         b->board[j][0] = newp | WHITE; // place replacements
+         b->board[j][7] = newp | BLACK;
+         placed = 1;
+       } while(!placed);
       }
-    retval = board_read_file(category, board, b); 
+      b->setup = 1;
+    } else if (!strcmp(category, "fischerandom")) {
+      wild_update(b->board, 22);
+      b->castlingStyle = 2;
+      b->setup = 1; // [HGM] FRC: even the default is a setup position, for which an initial board has to be printed
+    } else if (!strcmp(category, "caparandom")) {
+      b->files = 10;
+      wild_update(b->board, 46);
+      b->castlingStyle = 2;
+      b->setup = 1; 
+    } else retval = board_read_file(category, board, b); 
   }
+  if(b->setup && game_globals.garray[g].FENstartPos[0])  // [HGM] use pre-existing start position, if one available
+    FEN_to_board(game_globals.garray[g].FENstartPos, b); //       (could be wild board, or shuffle variant)
+  if(b->castlingStyle == 1) {
+    b->wkmoved = b->files/2;
+    b->bkmoved = b->files/2;
+    b->wkrmoved = b->files-1;
+    b->bkrmoved = b->files-1;
+    b->wqrmoved = 0;
+    b->bqrmoved = 0;
+  } else if(b->castlingStyle == 2) {
+    for(i=j=0; i < b->files; i++) {
+      int p = b->board[i][0];
+      if(p == W_ROOK || p == W_KING) {
+       switch(j++) {
+         case 0: b->wqrmoved = b->bqrmoved = i; break;
+         case 1: b->wkmoved  = b->bkmoved  = i; break;
+         case 2: b->wkrmoved = b->bkrmoved = i; break;
+       }
+      }
+    }
+  }
+
   MakeFENpos(g, game_globals.garray[g].FENstartPos);
+
   return retval;
 }
 
@@ -150,8 +248,8 @@ void board_calc_strength(struct game_state_t *b, int *ws, int *bs)
   int *p;
 
   *ws = *bs = 0;
-  for (f = 0; f < 8; f++) {
-    for (r = 0; r < 8; r++) {
+  for (f = 0; f < b->ranks; f++) {
+    for (r = 0; r < b->files; r++) {
       if (colorval(b->board[r][f]) == WHITE)
        p = ws;
       else
@@ -159,7 +257,7 @@ void board_calc_strength(struct game_state_t *b, int *ws, int *bs)
       *p += pieceValues[piecetype(b->board[r][f])];
     }
   }
-  for (r = PAWN; r <= QUEEN; r++) {
+  for (r = PAWN; r < PIECES; r++) {
     *ws += b->holding[0][r-1] * pieceValues[r];
     *bs += b->holding[1][r-1] * pieceValues[r];
   }
@@ -167,11 +265,11 @@ void board_calc_strength(struct game_state_t *b, int *ws, int *bs)
 
 static char *holding_str(int *holding)
 {
-       static char tmp[30];
+       static char tmp[80];
        int p,i,j;
 
        i = 0;
-       for (p = PAWN; p <= QUEEN; p++) {
+       for (p = PAWN; p < PIECES; p++) {
                for (j = 0; j < holding[p-1]; j++) {
                        tmp[i++] = wpstring[p][0];
                }
@@ -183,7 +281,7 @@ static char *holding_str(int *holding)
 static char *append_holding_machine(char *buf, int g, int c, int p)
 {
   struct game_state_t *gs = &game_globals.garray[g].game_state;
-  char tmp[50];
+  char tmp[160];
 
   sprintf(tmp, "<b1> game %d white [%s] black [", g+1, holding_str(gs->holding[0]));
   strcat(tmp, holding_str(gs->holding[1]));
@@ -213,7 +311,7 @@ void update_holding(int g, int pieceCaptured)
   int c = colorval(pieceCaptured);
   struct game_state_t *gs = &game_globals.garray[g].game_state;
   int pp, pl;
-  char tmp1[80], tmp2[80];
+  char tmp1[160], tmp2[160];
 
   if (c == WHITE) {
     c = 0;
@@ -251,7 +349,8 @@ char *board_to_string(char *wn, char *bn,
                      int orientation, int relation,
                      int p)
 {
-  int bh = (b->gameNum >= 0 && game_globals.garray[b->gameNum].link >= 0);
+  int bh = (b->gameNum >= 0 && game_globals.garray[b->gameNum].link >= 0
+             || b->holdings || b->drops == 2); // [HGM] zh: make sure holdings are printed (also in Seirawan)
   orient = orientation;
   myTurn = relation;
 
@@ -262,6 +361,7 @@ char *board_to_string(char *wn, char *bn,
      move happened, not current time */
   if (game_globals.garray[b->gameNum].status == GAME_EXAMINE) {
          unsigned nhm = game_globals.garray[b->gameNum].numHalfMoves;
+
          if (nhm > 0) {
                  wTime = ml[nhm - 1].wTime;
                  bTime = ml[nhm - 1].bTime;
@@ -288,8 +388,10 @@ char *board_to_string(char *wn, char *bn,
     bstring[0] = '\0';
   if (bh && !IsMachineStyle(style))
     append_holding_display(bstring, b, orientation==BLACK);
+
   if (styleFuncs[style] (b, ml))
     return NULL;
+
   if (bh) {
     if (IsMachineStyle(style))
       append_holding_machine(bstring, b->gameNum, 0, 0);
@@ -302,37 +404,61 @@ char *board_to_string(char *wn, char *bn,
 char *move_and_time(struct move_t *m)
 {
        static char tmp[20];
+#if 0
+       if(m->depth>0)
+            sprintf(tmp, "%-7s (%s%.2f/%d)", m->algString, /* tenth_str(m->tookTime, 0), */
+                                       m->score>0 ? "+" : "", m->score, m->depth);
+       else 
+#endif
        sprintf(tmp, "%-7s (%s)", m->algString, tenth_str(m->tookTime, 0));
        return tmp;
 }
 
 /* The following take the game state and whole move list */
 
+void Enlarge(char *a, int ss, int w)
+{
+  int l, i;
+  char *p, *q;
+  if(strlen(a) < ss) return;
+  for(i=8; i<w; i++) {
+    l = strlen(a);
+    p = a + l; q = p + ss;
+    while(q != a+l-ss) *q-- = *p--;
+  }
+}
+
 static int genstyle(struct game_state_t *b, struct move_t *ml, const char *wp[], const char *bp[],
                    const char *wsqr, const char *bsqr,
                    const char *top, const char *mid, const char *start, const char *end, 
                    const char *label,const char *blabel)
 {
-  int f, r, count;
-  char tmp[80];
-  int first, last, inc;
-  int ws, bs;
+  int f, r, count, i;
+  char tmp[80], mylabel[80], *p, *q, myTop[80], myMid[80];
+  int firstR, lastR, firstF, lastF, inc;
+  int ws, bs, sqrSize = strlen(wp[0]);
 
   board_calc_strength(b, &ws, &bs);
   if (orient == WHITE) {
-    first = 7;
-    last = 0;
+    firstR = b->ranks-1;
+    firstF = b->files-1;
+    lastR = lastF = 0;
     inc = -1;
   } else {
-    first = 0;
-    last = 7;
+    firstR = firstF = 0;
+    lastR = b->ranks-1;
+    lastF = b->files-1;
     inc = 1;
   }
-  strcat(bstring, top);
-  for (f = first, count = 7; f != last + inc; f += inc, count--) {
-    sprintf(tmp, "     %d  %s", f + 1, start);
+  strcpy(myTop, top);
+  strcpy(myMid, mid);
+  Enlarge(myTop, sqrSize, b->files);
+  Enlarge(myMid, sqrSize, b->files);
+  strcat(bstring, myTop);
+  for (f = firstR, count = b->ranks-1; f != lastR + inc; f += inc, count--) {
+    sprintf(tmp, "     %d  %s", f + (b->ranks < 10), start);
     strcat(bstring, tmp);
-    for (r = last; r != first - inc; r = r - inc) {
+    for (r = lastF; r != firstF - inc; r = r - inc) {
       if (square_color(r, f) == WHITE)
        strcat(bstring, wsqr);
       else
@@ -343,10 +469,12 @@ static int genstyle(struct game_state_t *b, struct move_t *ml, const char *wp[],
        else
          strcat(bstring, wp[0]);
       } else {
+       int piece = piecetype(b->board[r][f]);
+//     if(piece > QUEEN) piece = ELEPHANT + (piece == KING); // All fairies become elephants in ascii styles
        if (colorval(b->board[r][f]) == WHITE)
-         strcat(bstring, wp[piecetype(b->board[r][f])]);
+         strcat(bstring, wp[piece]);
        else
-         strcat(bstring, bp[piecetype(b->board[r][f])]);
+         strcat(bstring, bp[piece]);
       }
     }
     sprintf(tmp, "%s", end);
@@ -389,47 +517,77 @@ static int genstyle(struct game_state_t *b, struct move_t *ml, const char *wp[],
     }
     strcat(bstring, "\n");
     if (count != 0)
-      strcat(bstring, mid);
+      strcat(bstring, myMid);
     else
-      strcat(bstring, top);
+      strcat(bstring, myTop);
   }
-  if (orient == WHITE)
-    strcat(bstring, label);
-  else
-    strcat(bstring, blabel);
+  q = mylabel; i = 0;
+  if (orient == WHITE) {
+    p = label;
+    while(*p) {
+       switch(*p) {
+         case ' ':
+         case '\t':
+         case '\n':
+               *q++ = *p++; break;
+         default:
+               if(++i > b->files) { *q++ = '\n'; *q++ = 0; }
+               *q++ = *p++;
+       }
+    }
+  } else {
+    p = blabel;
+    while(*p) {
+       switch(*p) {
+         case ' ':
+         case '\t':
+         case '\n':
+               *q++ = *p++; break;
+         default:
+               *q++ = *p++ + b->files - 12;
+               if(++i >= b->files) { *q++ = '\n'; *q++ = 0; }
+       }
+    }
+  }
+  *q++ = 0;
+  strcat(bstring, mylabel);
   return 0;
 }
 
 /* Experimental ANSI board for colour representation */
 static int style13(struct game_state_t *b, struct move_t *ml)
 {
-  static const char *wp[] = {"   ", "\033[37m\033[1m P ", "\033[37m\033[1m N ", "\033[37m\033[1m B ", "\033[37m\033[1m R ", "\033[37m\033[1m Q ", "\033[37m\033[1m K "};
-  static const char *bp[] = {"   ", "\033[21m\033[37m P ", "\033[21m\033[37m N ", "\033[21m\033[37m B ", "\033[21m\033[37m R ", "\033[21m\033[37m Q ", "\033[21m\033[37m K "};
+  static const char *wp[] = {"   ", "\033[37m\033[1m P ", "\033[37m\033[1m N ", "\033[37m\033[1m B ", "\033[37m\033[1m R ", "\033[37m\033[1m A ", "\033[37m\033[1m C ", "\033[37m\033[1m M ", "\033[37m\033[1m Q ", "\033[37m\033[1m E ", "\033[37m\033[1m K "};
+  static const char *bp[] = {"   ", "\033[21m\033[37m P ", "\033[21m\033[37m N ", "\033[21m\033[37m B ", "\033[21m\033[37m R ", "\033[21m\033[37m A ", "\033[21m\033[37m C ", "\033[21m\033[37m M ", "\033[21m\033[37m Q ", "\033[21m\033[37m E ", "\033[21m\033[37m K "};
   static const char *wsqr = "\033[40m";
   static const char *bsqr = "\033[45m";
   static const char *top = "\t+------------------------+\n";
   static const char *mid = "";
   static const char *start = "|";
   static const char *end = "\033[0m|";
-  static const char *label = "\t  a  b  c  d  e  f  g  h\n";
-  static const char *blabel = "\t  h  g  f  e  d  c  b  a\n";
-
+  static const char *label = "\t  a  b  c  d  e  f  g  h  i  j  k  l\n";
+  static const char *blabel = "\t  l  k  j  i  h  g  f  e  d  c  b  a\n";
+return 0;
   return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);
 }
 
 /* Standard ICS */
 static int style1(struct game_state_t *b, struct move_t *ml)
 {
-  static const char *wp[] = {"   |", " P |", " N |", " B |", " R |", " Q |", " K |"};
-  static const char *bp[] = {"   |", " *P|", " *N|", " *B|", " *R|", " *Q|", " *K|"};
+  static const char *wp[] = {"   |", " P |", " N |", " B |", " R |", " A |", " C |", " M |", " Q |", " E |", " B |", " Q |", 
+                            " W |", " H |", " N |", " D |", " H |", " L |", " C |", " S |", " G |", " H |", " A |", " F |",
+                            " E |", " H |", " M |", " S |", " E |", " W |", " O |", " G |", " V |", " S |", " E |", " A |", " K |", " H |", " E |"};
+  static const char *bp[] = {"   |", " *P|", " *N|", " *B|", " *R|", " *A|", " *C|", " *M|", " *Q|", " *E|", " *B|", " *Q|", 
+                            " *W|", " *H|", " *N|", " *D|", " *H|", " *L|", " *C|", " *S|", " *G|", " *H|", " *A|", " *F|",
+                            " *E|", " *H|", " *M|", " *S|", " *E|", " *W|", " *O|", " *G|", " *V|", " *S|", " *E|", " *A|", " *K|", " *H|", " *E|"};
   static char *wsqr = "";
   static char *bsqr = "";
   static char *top = "\t---------------------------------\n";
   static char *mid = "\t|---+---+---+---+---+---+---+---|\n";
   static char *start = "|";
   static char *end = "";
-  static char *label = "\t  a   b   c   d   e   f   g   h\n";
-  static char *blabel = "\t  h   g   f   e   d   c   b   a\n";
+  static char *label = "\t  a   b   c   d   e   f   g   h   i   j   k   l\n";
+  static char *blabel = "\t  l   k   j   i   h   g   f   e   d   c   b   a\n";
 
   return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);
 }
@@ -437,16 +595,20 @@ static int style1(struct game_state_t *b, struct move_t *ml)
 /* USA-Today Sports Center-style board */
 static int style2(struct game_state_t *b, struct move_t *ml)
 {
-  static const char *wp[] = {"+  ", "P  ", "N  ", "B  ", "R  ", "Q  ", "K  "};
-  static const char *bp[] = {"-  ", "p' ", "n' ", "b' ", "r' ", "q' ", "k' "};
+  static const char *wp[] = {"-  ", "P  ", "N  ", "B  ", "R  ", "A  ", "C  ", "M  ", "Q  ", "E  ", "B  ", "Q  ",
+                            "W  ", "H  ", "N  ", "D  ", "H  ", "L  ", "C  ", "S  ", "G  ", "H  ", "A  ", "F  ",
+                            "E  ", "H  ", "M  ", "S  ", "E  ", "W  ", "O  ", "G  ", "V  ", "S  ", "E  ", "A  ", "K  ", "H  ", "E  "};
+  static const char *bp[] = {"+  ", "p' ", "n' ", "b' ", "r' ", "a' ", "c' ", "m' ", "q' ", "e' ", "b' ", "q' ",
+                            "w' ", "h' ", "n' ", "d' ", "h' ", "l' ", "c' ", "s' ", "g' ", "h' ", "a' ", "f' ",
+                            "e' ", "h' ", "m' ", "s' ", "e' ", "w' ", "o' ", "g' ", "v' ", "s' ", "e' ", "a' ", "k' ", "h' ", "e' "};
   static char *wsqr = "";
   static char *bsqr = "";
   static char *top = "";
   static char *mid = "";
   static char *start = "";
   static char *end = "";
-  static char *label = "\ta  b  c  d  e  f  g  h\n";
-  static char *blabel = "\th  g  f  e  d  c  b  a\n";
+  static char *label = "\ta  b  c  d  e  f  g  h  i  j  k  l\n";
+  static char *blabel = "\tl  k  j  i  h  g  f  e  d  c  b  a\n";
 
   return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);
 }
@@ -454,16 +616,20 @@ static int style2(struct game_state_t *b, struct move_t *ml)
 /* Experimental vt-100 ANSI board for dark backgrounds */
 static int style3(struct game_state_t *b, struct move_t *ml)
 {
-  static const char *wp[] = {"   ", " P ", " N ", " B ", " R ", " Q ", " K "};
-  static const char *bp[] = {"   ", " *P", " *N", " *B", " *R", " *Q", " *K"};
+  static const char *wp[] = {"   ", " P ", " N ", " B ", " R ", " A ", " C ", " M ", " Q ", " E ", " B ", " Q ", 
+                            " W ", " H ", " N ", " D ", " H ", " L ", " C ", " S ", " G ", " H ", " A ", " F ",
+                            " E ", " H ", " M ", " S ", " E ", " W ", " O ", " G ", " V ", " S ", " E ", " A ", " K ", " H ", " E "};
+  static const char *bp[] = {"   ", " *P", " *N", " *B", " *R", " *A", " *C", " *M", " *Q", " *E", " *B", " *Q", 
+                            " *W", " *H", " *N", " *D", " *H", " *L", " *C", " *S", " *G", " *H", " *A", " *F",
+                            " *E", " *H", " *M", " *S", " *E", " *W", " *O", " *G", " *V", " *S", " *E", " *A", " *K", " *H", " *E"};
   static char *wsqr = "\033[0m";
   static char *bsqr = "\033[7m";
   static char *top = "\t+------------------------+\n";
   static char *mid = "";
   static char *start = "|";
   static char *end = "\033[0m|";
-  static char *label = "\t  a  b  c  d  e  f  g  h\n";
-  static char *blabel = "\t  h  g  f  e  d  c  b  a\n";
+  static char *label = "\t  a  b  c  d  e  f  g  h  i  j  k  l\n";
+  static char *blabel = "\t  l  k  j  i  h  g  f  e  d  c  b  a\n";
 
   return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);
 }
@@ -471,16 +637,20 @@ static int style3(struct game_state_t *b, struct move_t *ml)
 /* Experimental vt-100 ANSI board for light backgrounds */
 static int style4(struct game_state_t *b, struct move_t *ml)
 {
-  static const char *wp[] = {"   ", " P ", " N ", " B ", " R ", " Q ", " K "};
-  static const char *bp[] = {"   ", " *P", " *N", " *B", " *R", " *Q", " *K"};
+  static const char *wp[] = {"   ", " P ", " N ", " B ", " R ", " A ", " C ", " M ", " Q ", " E ", " B ", " Q ", 
+                            " W ", " H ", " N ", " D ", " H ", " L ", " C ", " S ", " G ", " H ", " A ", " F ",
+                            " E ", " H ", " M ", " S ", " E ", " W ", " O ", " G ", " V ", " S ", " E ", " A ", " K ", " H ", " E "};
+  static const char *bp[] = {"   ", " *P", " *N", " *B", " *R", " *A", " *C", " *M", " *Q", " *E", " *B", " *Q", 
+                            " *W", " *H", " *N", " *D", " *H", " *L", " *C", " *S", " *G", " *H", " *A", " *F",
+                            " *E", " *H", " *M", " *S", " *E", " *W", " *O", " *G", " *V", " *S", " *E", " *A", " *K", " *H", " *E"};
   static char *wsqr = "\033[7m";
   static char *bsqr = "\033[0m";
   static char *top = "\t+------------------------+\n";
   static char *mid = "";
   static char *start = "|";
   static char *end = "\033[0m|";
-  static char *label = "\t  a  b  c  d  e  f  g  h\n";
-  static char *blabel = "\t  h  g  f  e  d  c  b  a\n";
+  static char *label = "\t  a  b  c  d  e  f  g  h  i  j  k  l\n";
+  static char *blabel = "\t  l  k  j  i  h  g  f  e  d  c  b  a\n";
 
   return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);
 }
@@ -488,16 +658,22 @@ static int style4(struct game_state_t *b, struct move_t *ml)
 /* Style suggested by ajpierce@med.unc.edu */
 static int style5(struct game_state_t *b, struct move_t *ml)
 {
-  static const char *wp[] = {"    ", "  o ", " :N:", " <B>", " |R|", " {Q}", " =K="};
-  static const char *bp[] = {"    ", "  p ", " :n:", " <b>", " |r|", " {q}", " =k="};
+  static const char *wp[] = {"    ", "  o ", " :N:", " <B>", " |R|", " (A)", " [C]", " :M:", " {Q}", " !E!",
+                            " <B>", " {Q}", " .W.", " :H:", " :N:", " <H>", " |D|", " |L|", 
+                            " |C|", " !S!", " :G:", " :H:", " {A}", " {F}", " !E!", " (H)", " [M]", " :S:",
+                            " !E!", " |W|", " *O*", " {G}", " :V:", " (S)", " [E]", " &A&", " =K=", " (H)", " [E]"};
+  static const char *bp[] = {"    ", "  p ", " :n:", " <b>", " |r|", " (a)", " [c]", " :m:", " {q}", " !e!",
+                            " <b>", " {q}", " .w.", " :h:", " :n:", " <h>", " |d|", " |l|", 
+                            " |c|", " !s!", " :g:", " :h:", " {a}", " {f}", " !e!", " (h)", " [m]", " :s:",
+                            " !e!", " |w|", " *o*", " {g}", " :v:", " (s)", " [e]", " &a&", " =k=", " (f)", " [e]"};
   static char *wsqr = "";
   static char *bsqr = "";
   static char *top = "        .   .   .   .   .   .   .   .   .\n";
   static char *mid = "        .   .   .   .   .   .   .   .   .\n";
   static char *start = "";
   static char *end = "";
-  static char *label = "\t  a   b   c   d   e   f   g   h\n";
-  static char *blabel = "\t  h   g   f   e   d   c   b   a\n";
+  static char *label = "\t  a   b   c   d   e   f   g   h   i   j   k   l\n";
+  static char *blabel = "\t  l   k   j   i   h   g   f   e   d   c   b   a\n";
 
   return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);
 }
@@ -505,16 +681,23 @@ static int style5(struct game_state_t *b, struct move_t *ml)
 /* Email Board suggested by Thomas Fought (tlf@rsch.oclc.org) */
 static int style6(struct game_state_t *b, struct move_t *ml)
 {
-  static const char *wp[] = {"    |", " wp |", " WN |", " WB |", " WR |", " WQ |", " WK |"};
-  static const char *bp[] = {"    |", " bp |", " BN |", " BB |", " BR |", " BQ |", " BK |"};
+  static const char *wp[] = {"    |", " wp |", " WN |", " WB |", " WR |", " WA |", " WC |", " WM |", " WQ |", 
+                            " WE |", " WB |", " WQ |", " WW |", " WH |", " WN |", " WD |", " WH |", " WL |", 
+                            " WC |", " WS |", " WG |", " WH |", " WA |", " WF |", " WE |", " WH |", " WM |", 
+                            " WS |", " WE |", " WW |", " WO |", " WG |", " WV |", " WS |", " WE |", " WA |", " WK |", " WH |", " WE |"};
+  static const char *bp[] = {"    |", " bp |", " BN |", " BB |", " BR |", " BA |", " BC |", " BM |", " BQ |", 
+                            " BE |", " BB |", " BQ |", " BW |", " BH |", " BN |", " BD |", " BH |", " BL |", 
+                            " BC |", " BS |", " BG |", " BH |", " BA |", " BF |", " BE |", " BH |", " BM |", 
+                            " BS |", " BE |", " BW |", " BO |", " BG |", " BV |", " BS |", " BE |", " BA |", " BK |", " BH |", " BE |"};
   static char *wsqr = "";
   static char *bsqr = "";
   static char *top = "\t-----------------------------------------\n";
+
   static char *mid = "\t-----------------------------------------\n";
   static char *start = "|";
   static char *end = "";
-  static char *label = "\t  A    B    C    D    E    F    G    H\n";
-  static char *blabel = "\t  H    G    F    E    D    C    B    A\n";
+  static char *label = "\t  A    B    C    D    E    F    G    H    I    J    K    L\n";
+  static char *blabel = "\t  L    K    J    I    H    G    F    E    D    C    B    A\n";
 
   return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);
 }
@@ -522,16 +705,18 @@ static int style6(struct game_state_t *b, struct move_t *ml)
 /* Miniature board */
 static int style7(struct game_state_t *b, struct move_t *ml)
 {
-  static const char *wp[] = {"  ", " P", " N", " B", " R", " Q", " K"};
-  static const char *bp[] = {" -", " p", " n", " b", " r", " q", " k"};
+  static const char *wp[] = {"  ", " P", " N", " B", " R", " A", " C", " M", " Q", " E", " B", " Q", " W", " H", " N", " D", " H", " L", 
+                            " C", " S", " G", " H", " A", " F", " E", " H", " M", " S", " E", " W", " O", " G", " V", " S", " E", " A", " K", " H", " E"};
+  static const char *bp[] = {" -", " p", " n", " b", " r", " a", " c", " m", " q", " e", " b", " q", " w", " h", " n", " d", " h", " l", 
+                            " c", " s", " g", " h", " a", " f", " e", " h", " m", " s", " e", " w", " o", " g", " v", " s", " e", " a", " k", " h", " e"};
   static char *wsqr = "";
   static char *bsqr = "";
   static char *top = "\t:::::::::::::::::::::\n";
   static char *mid = "";
   static char *start = "..";
   static char *end = " ..";
-  static char *label = "\t   a b c d e f g h\n";
-  static char *blabel = "\t   h g f e d c b a\n";
+  static char *label = "\t   a b c d e f g h i j k l\n";
+  static char *blabel = "\t   l k j i h g f e d c b a\n";
 
   return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);
 }
@@ -539,7 +724,7 @@ static int style7(struct game_state_t *b, struct move_t *ml)
 /* ICS interface maker board-- raw data dump */
 static int style8(struct game_state_t *b, struct move_t *ml)
 {
-  char tmp[80];
+  char tmp[160];
   int f, r;
   int ws, bs;
 
@@ -550,8 +735,8 @@ static int style8(struct game_state_t *b, struct move_t *ml)
          game_globals.garray[b->gameNum].black_name,
          (orient == WHITE) ? ":" : "*");
   strcat(bstring, tmp);
-  for (r = 0; r < 8; r++) {
-    for (f = 0; f < 8; f++) {
+  for (r = 0; r < b->ranks; r++) {
+    for (f = 0; f < b->files; f++) {
       if (b->board[f][r] == NOPIECE) {
        strcat(bstring, " ");
       } else {
@@ -583,7 +768,7 @@ static int style8(struct game_state_t *b, struct move_t *ml)
 static int style9(struct game_state_t *b, struct move_t *ml)
 {
   int i, count;
-  char tmp[80];
+  char tmp[160];
   int startmove;
 
   sprintf(tmp, "\nMove     %-23s%s\n",
@@ -616,15 +801,15 @@ static int style9(struct game_state_t *b, struct move_t *ml)
 static int style10(struct game_state_t *b, struct move_t *ml)
 {
   int f, r;
-  char tmp[80];
+  char tmp[160];
   int ws, bs;
 
   board_calc_strength(b, &ws, &bs);
   sprintf(tmp, "<10>\n");
   strcat(bstring, tmp);
-  for (r = 7; r >= 0; r--) {
+  for (r = b->ranks-1; r >= 0; r--) {
     strcat(bstring, "|");
-    for (f = 0; f < 8; f++) {
+    for (f = 0; f < b->files; f++) {
       if (b->board[f][r] == NOPIECE) {
        strcat(bstring, " ");
       } else {
@@ -645,10 +830,10 @@ static int style10(struct game_state_t *b, struct move_t *ml)
   }
   strcat(bstring, tmp);
   sprintf(tmp, "%d %d %d %d %d\n",
-         !(b->wkmoved || b->wkrmoved),
-         !(b->wkmoved || b->wqrmoved),
-         !(b->bkmoved || b->bkrmoved),
-         !(b->bkmoved || b->bqrmoved),
+         (b->wkmoved >= 0 && b->wkrmoved >= 0), // [HGM] castle: inverted the logic, both must have rights
+         (b->wkmoved >= 0 && b->wqrmoved >= 0),
+         (b->bkmoved >= 0 && b->bkrmoved >= 0),
+         (b->bkmoved >= 0 && b->bqrmoved >= 0),
        (game_globals.garray[b->gameNum].numHalfMoves - ((b->lastIrreversable == -1) ? 0 :
                                           b->lastIrreversable)));
   strcat(bstring, tmp);
@@ -683,7 +868,7 @@ static int style10(struct game_state_t *b, struct move_t *ml)
 /* Same as 8, but with verbose moves ("P/e3-e4", instead of "e4") */
 static int style11(struct game_state_t *b, struct move_t *ml)
 {
-  char tmp[80];
+  char tmp[160];
   int f, r;
   int ws, bs;
 
@@ -694,8 +879,8 @@ static int style11(struct game_state_t *b, struct move_t *ml)
          game_globals.garray[b->gameNum].black_name,
          (orient == WHITE) ? ":" : "*");
   strcat(bstring, tmp);
-  for (r = 0; r < 8; r++) {
-    for (f = 0; f < 8; f++) {
+  for (r = 0; r < b->ranks; r++) {
+    for (f = 0; f < b->files; f++) {
       if (b->board[f][r] == NOPIECE) {
        strcat(bstring, " ");
       } else {
@@ -723,17 +908,26 @@ static int style11(struct game_state_t *b, struct move_t *ml)
   return 0;
 }
 
+
+int kludgeFlag = 0; 
 /* Similar to style 10.  See the "style12" help file for information */
 static int style12(struct game_state_t *b, struct move_t *ml)
 {
   int f, r;
-  char tmp[80];
-  int ws, bs;
+  char tmp[160]; // [HGM] 80 caused problems with long login names
+  int ws, bs; 
+  int nhm = kludgeFlag ? 0 : game_globals.garray[b->gameNum].numHalfMoves; 
+  // [HGM] setup: the number of half moves appeared in this routine an enormous number of times,
+  // and had to be dug out of the game_globals, so that this routine could only be used to print
+  // a board from a game, and not just any board given by an isolated game_state_t. This was very
+  // inconvenient for printing initial boards in move lists of shuffle variants, so I added the
+  // global kludgeFlag to signal that we want to print an initial position, and force nhm = 0.
 
   board_calc_strength(b, &ws, &bs);
+
   sprintf(bstring, "<12> ");
-  for (r = 7; r >= 0; r--) {
-    for (f = 0; f < 8; f++) {
+  for (r = b->ranks-1; r >= 0; r--) {
+    for (f = 0; f < b->files; f++) {
       if (b->board[f][r] == NOPIECE) {
        strcat(bstring, "-");
       } else {
@@ -745,20 +939,21 @@ static int style12(struct game_state_t *b, struct move_t *ml)
     }
     strcat(bstring, " ");
   }
+
   strcat(bstring, (b->onMove == WHITE) ? "W " : "B ");
-  if (game_globals.garray[b->gameNum].numHalfMoves) {
+  if (nhm) {
     sprintf(tmp, "%d ",
-           ml[game_globals.garray[b->gameNum].numHalfMoves - 1].doublePawn);
+           ml[nhm - 1].doublePawn);
   } else {
     sprintf(tmp, "-1 ");
   }
   strcat(bstring, tmp);
   sprintf(tmp, "%d %d %d %d %d ",
-         !(b->wkmoved || b->wkrmoved),
-         !(b->wkmoved || b->wqrmoved),
-         !(b->bkmoved || b->bkrmoved),
-         !(b->bkmoved || b->bqrmoved),
-         (game_globals.garray[b->gameNum].numHalfMoves - ((b->lastIrreversable == -1) ? 0 : b->lastIrreversable)));
+         (b->wkmoved >= 0 && b->wkrmoved >= 0), // [HGM] castle: inverted the logic, both must have rights
+         (b->wkmoved >= 0 && b->wqrmoved >= 0),
+         (b->bkmoved >= 0 && b->bkrmoved >= 0),
+         (b->bkmoved >= 0 && b->bqrmoved >= 0),
+         (nhm - ((b->lastIrreversable == -1) ? 0 : b->lastIrreversable)));
   strcat(bstring, tmp);
   sprintf(tmp, "%d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d %d\n",
          b->gameNum + 1,
@@ -771,15 +966,15 @@ static int style12(struct game_state_t *b, struct move_t *ml)
          bs,
          (wTime / 10),
          (bTime / 10),
-         game_globals.garray[b->gameNum].numHalfMoves / 2 + 1,
-         game_globals.garray[b->gameNum].numHalfMoves ?
-         ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString :
+         nhm / 2 + 1,
+         nhm ?
+         ml[nhm - 1].moveString :
          "none",
-         game_globals.garray[b->gameNum].numHalfMoves ?
-         tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) :
+         nhm ?
+         tenth_str(ml[nhm - 1].tookTime, 0) :
          "0:00",
-         game_globals.garray[b->gameNum].numHalfMoves ?
-         ml[game_globals.garray[b->gameNum].numHalfMoves - 1].algString :
+         nhm ?
+         ml[nhm - 1].algString :
          "none", (orient == WHITE) ? 0 : 1,
          b->moveNum > 1 ? 1 : 0); /* ticking */
 
@@ -802,6 +997,7 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs)
     return 1;
 
   board_clear(gs);
+  gs->setup = 1;
   while (!feof(fp)) {
     c = fgetc(fp);
     if (onNewLine) {
@@ -813,6 +1009,65 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs)
        onColor = BLACK;
        if (gs->onMove < 0)
          gs->onMove = BLACK;
+      } else if (c == 'S') { int f=8, r=8;
+       // [HGM] rules: read rule modifiers
+       fscanf(fp, "%dx%d", &f, &r); gs->files=f; gs->ranks = r;
+       while (!feof(fp) && c != '\n') {
+         c = fgetc(fp);
+         switch(c) {
+           case 'r':
+               gs->royalKnight = 1;
+               break;
+           case 'c':
+               gs->capablancaPieces = 1;
+               break;
+           case 'd':
+               gs->drops = 1;
+               break;
+           case 'g':
+               gs->drops = 2;
+               break;
+           case 'h':
+               gs->holdings = -1;     // color-flip holdings
+               break;
+           case 'p':
+               gs->palace = 3;
+               break;
+           case 'P':
+               gs->promoType = 2; // only promote to captured pieces
+               gs->holdings = 1;  // use holdings to hold own captured pieces
+               break;
+           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;
+           case 'w':
+               gs->castlingStyle = 1; // wild castling, from both center files
+               break;
+           case 'n':
+               gs->castlingStyle = 0; // no castling
+               break;
+           case 'f':
+               gs->castlingStyle = 3; // free castling
+               break;
+           case 'D':
+               gs->pawnDblStep = 0; // suppress pawn double step
+               break;
+           case 'b':
+               gs->bareKingLoses = 1; // apply baring rule
+               break;
+           case 's':
+               gs->stalemate = 0; // stalemate loses
+               break;
+         }
+       }       
+       continue;
       } else if (c == '#') {
        while (!feof(fp) && c != '\n')
          c = fgetc(fp);        /* Comment line */
@@ -837,12 +1092,99 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs)
       case 'B':
        onPiece = BISHOP;
        break;
+      case 'A':
+       onPiece = CARDINAL;
+       break;
+      case 'C':
+       onPiece = MARSHALL;
+       break;
+      case 'M':
+       onPiece = MAN;
+       break;
       case 'Q':
        onPiece = QUEEN;
        break;
+      case 'T':
+       onPiece = ELEPHANT;
+       break;
+      case 'E':
+       onPiece = ALFIL;
+       break;
+      case 't':
+       onPiece = ALFIL2;
+       break;
+      case 'q':
+       onPiece = FERZ;
+       break;
+      case 'F':
+       onPiece = FERZ2;
+       break;
+      case 'W':
+       onPiece = WAZIR;
+       break;
+      case 'w':
+       onPiece = WOODY;
+       break;
+      case 'p':
+       onPiece = PRIESTESS;
+       break;
+      case 'r':
+       onPiece = MINISTER;
+       break;
+      case 'z':
+       onPiece = MAN2;
+       break;
+      case 'u':
+       onPiece = NIGHTRIDER;
+       break;
+      case 'o':
+       onPiece = MODERNELEPHANT;
+       break;
+      case 's':
+       onPiece = MASTODON;
+       break;
+      case 'Z':
+       onPiece = AMAZON;
+       break;
+      case 'V':
+       onPiece = CENTAUR;
+       break;
+      case 'H':
+       onPiece = HORSE;
+       break;
+      case 'n':
+       onPiece = HONORABLEHORSE;
+       break;
+      case 'J':
+       onPiece = DRAGONKING;
+       break;
+      case 'I':
+       onPiece = DRAGONHORSE;
+       break;
+      case 'L':
+       onPiece = LANCE;
+       break;
+      case 'O':
+       onPiece = CANNON;
+       break;
+      case 'S':
+       onPiece = SILVER;
+       break;
+      case 'G':
+       onPiece = GOLD;
+       break;
+      case 'm':
+       onPiece = MANDARIN;
+       break;
       case 'K':
        onPiece = KING;
        break;
+      case 'D':
+       onPiece = SELEPHANT;
+       break;
+      case 'U':
+       onPiece = HAWK;
+       break;
       case 'a':
       case 'b':
       case 'c':
@@ -851,9 +1193,18 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs)
       case 'f':
       case 'g':
       case 'h':
+      case 'i':
+      case 'j':
+      case 'k':
+      case 'l':
        onFile = c - 'a';
+        if(onFile >= gs->files) { onFile = -1; break; }
        onRank = -1;
        break;
+      case '@':
+       if (onColor >= 0 && onPiece >= 0) // allow placement in holdings
+         gs->holding[onColor == BLACK][onPiece-1]++;
+       break;
       case '1':
       case '2':
       case '3':
@@ -862,7 +1213,10 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs)
       case '6':
       case '7':
       case '8':
-       onRank = c - '1';
+      case '9':
+      case '0':
+       onRank = c - '1' + (gs->ranks > 9);
+        if(onRank < 0 || onRank >= gs->ranks) { onRank = -1; break; }
        if (onFile >= 0 && onColor >= 0 && onPiece >= 0)
          gs->board[onFile][onRank] = onPiece | onColor;
        break;
@@ -890,8 +1244,8 @@ static int board_read_file(char *category, char *gname, struct game_state_t *gs)
 #define ANY_SQUARE -1
 #define SquareColor(f, r) ((f ^ r) & 1)
 
-static void place_piece(board_t b, int piece, int squareColor)
-{
+static void place_piece(board_t b, int piece, int squareColor, int width)
+{ //[HGM] board: make width a variable
   int r, f;
   int placed = 0;
 
@@ -902,9 +1256,9 @@ static void place_piece(board_t b, int piece, int squareColor)
 
   while (!placed) {
     if (squareColor == ANY_SQUARE) {
-      f = random() % 8;
+      f = random() % width;
     } else {
-      f = (random() % 4) * 2;
+      f = (random() % ((width+1)/2)) * 2; // to not overflow odd-width boards
       if (SquareColor(f, r) != squareColor)
        f++;
     }
@@ -915,12 +1269,11 @@ static void place_piece(board_t b, int piece, int squareColor)
   }
 }
 
-static void wild_update(int style)
+static void wild_update(board_t b, int style)
 {
-  int f, r, i;
-  board_t b;
+  int f, r, i, j;
 
-  for (f = 0; f < 8; f++)
+  for (f = 0; f < BW; f++) // [HGM] board: make sure also works with wider boards
     for (r = 0; r < 8; r++)
       b[f][r] = NOPIECE;
   for (f = 0; f < 8; f++) {
@@ -947,24 +1300,24 @@ static void wild_update(int style)
     b[0][7] = b[7][7] = B_ROOK;
     /* Must do bishops before knights to be sure opposite colored squares are
        available. */
-    place_piece(b, W_BISHOP, WHITE_SQUARE);
-    place_piece(b, W_BISHOP, BLACK_SQUARE);
-    place_piece(b, W_KNIGHT, ANY_SQUARE);
-    place_piece(b, W_KNIGHT, ANY_SQUARE);
-    place_piece(b, B_BISHOP, WHITE_SQUARE);
-    place_piece(b, B_BISHOP, BLACK_SQUARE);
-    place_piece(b, B_KNIGHT, ANY_SQUARE);
-    place_piece(b, B_KNIGHT, ANY_SQUARE);
+    place_piece(b, W_BISHOP, WHITE_SQUARE, 8);
+    place_piece(b, W_BISHOP, BLACK_SQUARE, 8);
+    place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+    place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+    place_piece(b, B_BISHOP, WHITE_SQUARE, 8);
+    place_piece(b, B_BISHOP, BLACK_SQUARE, 8);
+    place_piece(b, B_KNIGHT, ANY_SQUARE, 8);
+    place_piece(b, B_KNIGHT, ANY_SQUARE, 8);
     break;
   case 2:
-    place_piece(b, W_KING, ANY_SQUARE);
-    place_piece(b, W_QUEEN, ANY_SQUARE);
-    place_piece(b, W_ROOK, ANY_SQUARE);
-    place_piece(b, W_ROOK, ANY_SQUARE);
-    place_piece(b, W_BISHOP, ANY_SQUARE);
-    place_piece(b, W_BISHOP, ANY_SQUARE);
-    place_piece(b, W_KNIGHT, ANY_SQUARE);
-    place_piece(b, W_KNIGHT, ANY_SQUARE);
+    place_piece(b, W_KING, ANY_SQUARE, 8);
+    place_piece(b, W_QUEEN, ANY_SQUARE, 8);
+    place_piece(b, W_ROOK, ANY_SQUARE, 8);
+    place_piece(b, W_ROOK, ANY_SQUARE, 8);
+    place_piece(b, W_BISHOP, ANY_SQUARE, 8);
+    place_piece(b, W_BISHOP, ANY_SQUARE, 8);
+    place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+    place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
     /* Black mirrors White */
     for (i = 0; i < 8; i++) {
       b[i][7] = b[i][0] | BLACK;
@@ -972,7 +1325,7 @@ static void wild_update(int style)
     break;
   case 3:
     /* Generate White king on random square plus random set of pieces */
-    place_piece(b, W_KING, ANY_SQUARE);
+    place_piece(b, W_KING, ANY_SQUARE, 8);
     for (i = 0; i < 8; i++) {
       if (b[i][0] != W_KING) {
        b[i][0] = (random() % 4) + 2;
@@ -985,7 +1338,7 @@ static void wild_update(int style)
     break;
   case 4:
     /* Generate White king on random square plus random set of pieces */
-    place_piece(b, W_KING, ANY_SQUARE);
+    place_piece(b, W_KING, ANY_SQUARE, 8);
     for (i = 0; i < 8; i++) {
       if (b[i][0] != W_KING) {
        b[i][0] = (random() % 4) + 2;
@@ -997,15 +1350,47 @@ static void wild_update(int style)
        to be sure there are enough squares left of the correct color. */
     for (i = 0; i < 8; i++) {
       if (b[i][0] == W_BISHOP) {
-       place_piece(b, B_BISHOP, !SquareColor(i, 0));
+       place_piece(b, B_BISHOP, !SquareColor(i, 0), 8);
       }
     }
     for (i = 0; i < 8; i++) {
       if (b[i][0] != W_BISHOP) {
-       place_piece(b, b[i][0] | BLACK, ANY_SQUARE);
+       place_piece(b, b[i][0] | BLACK, ANY_SQUARE, 8);
       }
     }
     break;
+  case 22:
+    /* Chess960 placement: King between R */
+    place_piece(b, W_BISHOP, WHITE_SQUARE, 8);
+    place_piece(b, W_BISHOP, BLACK_SQUARE, 8);
+    place_piece(b, W_QUEEN,  ANY_SQUARE, 8);
+    place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+    place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+    for (i = j = 0; i < 8; i++) {
+      if(b[i][0] == NOPIECE) b[i][0] = (j++ == 1 ? W_KING : W_ROOK);
+    }
+    /* Black mirrors White */
+    for (i = 0; i < 8; i++) {
+      b[i][7] = b[i][0] | BLACK;
+    }
+    break;
+  case 46:
+    /* Chess960 placement: King between R */
+    place_piece(b, W_BISHOP, WHITE_SQUARE, 10);
+    place_piece(b, W_BISHOP, BLACK_SQUARE, 10);
+    place_piece(b, W_QUEEN,  ANY_SQUARE, 10);
+    place_piece(b, W_MARSHALL, ANY_SQUARE, 10);
+    place_piece(b, W_CARDINAL, ANY_SQUARE, 10);
+    place_piece(b, W_KNIGHT, ANY_SQUARE, 10);
+    place_piece(b, W_KNIGHT, ANY_SQUARE, 10);
+    for (i = j = 0; i < 10; i++) {
+      if(b[i][0] == NOPIECE) j++ == 1 ? W_KING : W_ROOK;
+    }
+    /* Black mirrors White */
+    for (i = 0; i < 10; i++) {
+      b[i][7] = b[i][0] | BLACK;
+    }
+    break;
   default:
     return;
     break;
@@ -1048,9 +1433,10 @@ static void wild_update(int style)
 
 void wild_init(void)
 {
-       wild_update(1);
-       wild_update(2);
-       wild_update(3);
-       wild_update(4);
+       board_t b;
+       wild_update(b, 1);
+       wild_update(b, 2);
+       wild_update(b, 3);
+       wild_update(b, 4);
 }