960pos.c - randomcrap - random crap programs of varying quality
 (HTM) git clone git://git.codemadness.org/randomcrap
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       960pos.c (3681B)
       ---
            1 /* generate chess960 position by number or list all the positions.
            2    see: https://en.wikipedia.org/wiki/Fischer_random_chess_numbering_scheme */
            3 
            4 #include <stdio.h>
            5 #include <stdlib.h>
            6 
            7 void
            8 ranktofen(char *buf, size_t bufsiz, const char *rank)
            9 {
           10         int i;
           11 
           12         snprintf(buf, bufsiz, "%s/pppppppp/8/8/8/8/PPPPPPPP/%s w KQkq - 0 1",
           13                  rank, rank);
           14 
           15         for (i = 0; i < 8; i++)
           16                 buf[i] = (buf[i] - 'A') + 'a'; /* to lower-case */
           17 }
           18 
           19 /* simpler method, using 2 tables */
           20 void
           21 postab(int n, char *rank)
           22 {
           23         /* Scharnagl's NQ-skeleton Table */
           24         char *ktab[] = {
           25                 "QNNRKR", "NQNRKR", "NNQRKR", "NNRQKR", "NNRKQR", "NNRKRQ",
           26                 "QNRNKR", "NQRNKR", "NRQNKR", "NRNQKR", "NRNKQR", "NRNKRQ",
           27                 "QNRKNR", "NQRKNR", "NRQKNR", "NRKQNR", "NRKNQR", "NRKNRQ",
           28                 "QNRKRN", "NQRKRN", "NRQKRN", "NRKQRN", "NRKRQN", "NRKRNQ",
           29                 "QRNNKR", "RQNNKR", "RNQNKR", "RNNQKR", "RNNKQR", "RNNKRQ",
           30                 "QRNKNR", "RQNKNR", "RNQKNR", "RNKQNR", "RNKNQR", "RNKNRQ",
           31                 "QRNKRN", "RQNKRN", "RNQKRN", "RNKQRN", "RNKRQN", "RNKRNQ",
           32                 "QRKNNR", "RQKNNR", "RKQNNR", "RKNQNR", "RKNNQR", "RKNNRQ",
           33                 "QRKNRN", "RQKNRN", "RKQNRN", "RKNQRN", "RKNRQN", "RKNRNQ",
           34                 "QRKRNN", "RQKRNN", "RKQRNN", "RKRQNN", "RKRNQN", "RKRNNQ"
           35         };
           36         /* Bishop's table: encoded squares between them */
           37         unsigned char btab[] = {
           38                 0, 0, 0, 2, 0, 4, 0, 6, 1, 0, 2, 0, 2, 2, 2, 4,
           39                 1, 2, 3, 0, 4, 0, 4, 2, 1, 4, 3, 2, 5, 0, 6, 0
           40         };
           41         char *s;
           42         int i, t1, t2;
           43 
           44         t2 = n % 16;
           45         t1 = (n - t2) / 16;
           46 
           47         for (i = 0; i < 8; i++)
           48                 rank[i] = 0;
           49 
           50         /* bishops */
           51         rank[btab[t2 * 2]] = 'B';
           52         rank[btab[t2 * 2] + btab[t2 * 2 + 1] + 1] = 'B';
           53 
           54         s = ktab[t1];
           55         for (i = 0; i < 8 && *s; i++) {
           56                 if (rank[i])
           57                         continue;
           58                 rank[i] = *s;
           59                 s++;
           60         }
           61 
           62         rank[8] = '\0'; /* NUL */
           63 }
           64 
           65 /* more computational way to generate the position */
           66 void
           67 poscomp(int n, char *rank)
           68 {
           69         int n1, n2, n3, n4, b1, b2, q, i;
           70         /* knights table: encoded squares between them */
           71         unsigned char ntab[] = { 0, 0, 0, 1, 0, 2, 0, 3, 1, 0, 1, 1, 1, 2, 2, 0, 2, 1, 3, 0 };
           72 
           73         for (i = 0; i < 8; i++)
           74                 rank[i] = 0;
           75 
           76         /* bishop (white square) */
           77         b1 = n % 4;
           78         n2 = (n - b1) / 4;
           79 
           80         /* b, d, f, h */
           81         rank[b1 * 2 + 1] = 'B';
           82 
           83         /* bishop (dark square) */
           84         b2 = n2 % 4;
           85         n3 = (n2 - b2) / 4;
           86         /* a, c, e, g */
           87         rank[b2 * 2] = 'B';
           88 
           89         /* queen */
           90         q = n3 % 6;
           91         n4 = (n3 - q) / 6;
           92         for (i = 0; i < 8; i++) {
           93                 if (rank[i])
           94                         continue;
           95                 if (q == 0) {
           96                         rank[i] = 'Q';
           97                         break;
           98                 }
           99                 q--;
          100         }
          101 
          102         /* knights */
          103         n1 = ntab[n4 * 2]; /* skip for first knight */
          104         n2 = ntab[n4 * 2 + 1]; /* skip for second knight */
          105 
          106         for (i = 0; i < 8; i++) {
          107                 if (rank[i])
          108                         continue;
          109                 if (n1) {
          110                         n1--;
          111                         continue;
          112                 }
          113                 rank[i] = 'N';
          114                 break;
          115         }
          116 
          117         for (; ; i++) {
          118                 if (i >= 8)
          119                         i = 0; /* wrap around */
          120                 if (rank[i])
          121                         continue;
          122                 if (n2) {
          123                         n2--;
          124                         continue;
          125                 }
          126                 rank[i] = 'N';
          127                 break;
          128         }
          129 
          130         /* there are three blank squares remaining; place a rook in each of the
          131            outer two and the king in the middle one. */
          132         for (i = 0; i < 8; i++) {
          133                 if (rank[i])
          134                         continue;
          135                 rank[i] = 'R';
          136                 break;
          137         }
          138 
          139         for (i = 7; i >= 0; i--) {
          140                 if (rank[i])
          141                         continue;
          142                 rank[i] = 'R';
          143                 break;
          144         }
          145 
          146         for (i = 0; i < 8; i++) {
          147                 if (rank[i])
          148                         continue;
          149                 rank[i] = 'K';
          150                 break;
          151         }
          152 
          153         rank[8] = '\0'; /* NUL */
          154 }
          155 
          156 int
          157 main(int argc, char *argv[])
          158 {
          159         char fen[92], rank[9];
          160         long l;
          161         int i;
          162 
          163         if (argc > 2) {
          164 usage:
          165                 fprintf(stderr, "usage: %s <0-959>\n", argv[0]);
          166                 return 1;
          167         }
          168 
          169         if (argc == 2) {
          170                 l = strtol(argv[1], NULL, 10);
          171                 if (l < 0 || l > 959)
          172                         goto usage;
          173                 postab(l, rank);
          174                 ranktofen(fen, sizeof(fen), rank);
          175                 printf("%s\n", fen);
          176         } else {
          177                 /* 518 is classical */
          178                 for (i = 0; i < 960; i++) {
          179                         postab(i, rank);
          180                         ranktofen(fen, sizeof(fen), rank);
          181                         printf("%d\t%s\n", i, fen);
          182                 }
          183         }
          184 
          185         return 0;
          186 }