960pos.c: program to generate or lookup chess960 starting position - 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
       ---
 (DIR) commit ccfd3b75fd9368ff84c604a337e094038fdcd4d3
 (DIR) parent 7710dbd1b1784adeffe118b15282fd05cb1b31d1
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Tue, 23 Jan 2024 20:22:52 +0100
       
       960pos.c: program to generate or lookup chess960 starting position
       
       Diffstat:
         A 960pos.c                            |     186 +++++++++++++++++++++++++++++++
       
       1 file changed, 186 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/960pos.c b/960pos.c
       @@ -0,0 +1,186 @@
       +/* generate chess960 position by number or list all the positions.
       +   see: https://en.wikipedia.org/wiki/Fischer_random_chess_numbering_scheme */
       +
       +#include <stdio.h>
       +#include <stdlib.h>
       +
       +void
       +ranktofen(char *buf, size_t bufsiz, const char *rank)
       +{
       +        int i;
       +
       +        snprintf(buf, bufsiz, "%s/pppppppp/8/8/8/8/PPPPPPPP/%s w KQkq - 0 1", rank, rank);
       +
       +        for (i = 0; i < 8; i++)
       +                buf[i] = ((buf[i] - 'A') + 'a'); /* lower-case */
       +}
       +
       +/* simpler method, using 2 tables */
       +void
       +postab(int n, char *rank)
       +{
       +        /* Scharnagl's NQ-skeleton Table */
       +        char *ktab[] = {
       +                "QNNRKR", "NQNRKR", "NNQRKR", "NNRQKR", "NNRKQR", "NNRKRQ",
       +                "QNRNKR", "NQRNKR", "NRQNKR", "NRNQKR", "NRNKQR", "NRNKRQ",
       +                "QNRKNR", "NQRKNR", "NRQKNR", "NRKQNR", "NRKNQR", "NRKNRQ",
       +                "QNRKRN", "NQRKRN", "NRQKRN", "NRKQRN", "NRKRQN", "NRKRNQ",
       +                "QRNNKR", "RQNNKR", "RNQNKR", "RNNQKR", "RNNKQR", "RNNKRQ",
       +                "QRNKNR", "RQNKNR", "RNQKNR", "RNKQNR", "RNKNQR", "RNKNRQ",
       +                "QRNKRN", "RQNKRN", "RNQKRN", "RNKQRN", "RNKRQN", "RNKRNQ",
       +                "QRKNNR", "RQKNNR", "RKQNNR", "RKNQNR", "RKNNQR", "RKNNRQ",
       +                "QRKNRN", "RQKNRN", "RKQNRN", "RKNQRN", "RKNRQN", "RKNRNQ",
       +                "QRKRNN", "RQKRNN", "RKQRNN", "RKRQNN", "RKRNQN", "RKRNNQ"
       +        };
       +
       +        /* Bishop's table */
       +        unsigned char btab[] = {
       +                0, 0, 0, 2, 0, 4, 0, 6, 1, 0, 2, 0, 2, 2, 2, 4,
       +                1, 2, 3, 0, 4, 0, 4, 2, 1, 4, 3, 2, 5, 0, 6, 0
       +        };
       +
       +        char *s;
       +        int i, t1, t2;
       +
       +        t2 = n % 16;
       +        t1 = (n - t2) / 16;
       +
       +        for (i = 0; i < 8; i++)
       +                rank[i] = 0;
       +
       +        /* bishops */
       +        rank[btab[t2 * 2]] = 'B';
       +        rank[btab[t2 * 2] + btab[t2 * 2 + 1] + 1] = 'B';
       +
       +        s = ktab[t1];
       +        for (i = 0; i < 8 && *s; i++) {
       +                if (rank[i])
       +                        continue;
       +                rank[i] = *s;
       +                s++;
       +        }
       +                
       +        rank[8] = '\0'; /* NUL */
       +}
       +
       +/* more computation way to generate the position */
       +void
       +poscomp(int n, char *rank)
       +{
       +        int n1, n2, n3, n4, b1, b2, q, i;
       +        int ntab[] = { 0, 0, 0, 1, 0, 2, 0, 3, 1, 0, 1, 1, 1, 2, 2, 0, 2, 1, 3, 0 };
       +
       +        for (q = 0; q < 8; q++)
       +                rank[q] = 0;
       +
       +        /* bishop (white square) */
       +        b1 = n % 4;
       +        n2 = (n - b1) / 4;
       +
       +        /* b, d, f, h */
       +        rank[b1 * 2 + 1] = 'B'; /* b */
       +
       +        /* bishop (dark square) */
       +        b2 = n2 % 4;
       +        n3 = (n2 - b2) / 4;
       +        /* a, c, e, g */
       +        rank[b2 * 2] = 'B';
       +
       +        /* queen */
       +        q = n3 % 6;
       +        n4 = (n3 - q) / 6;
       +        for (i = 0; i < 8; i++) {
       +                if (rank[i])
       +                        continue;
       +                if (q == 0) {
       +                        rank[i] = 'Q';
       +                        break;
       +                }
       +                q--;
       +        }
       +
       +        /* knights */
       +        n1 = ntab[n4 * 2]; /* skip for first knight */
       +        n2 = ntab[n4 * 2 + 1]; /* skip for second knight */
       +
       +        for (i = 0; i < 8; i++) {
       +                if (rank[i])
       +                        continue;
       +                if (n1) {
       +                        n1--;
       +                        continue;
       +                }
       +                rank[i] = 'N';
       +                break;
       +        }
       +
       +        for (; ; i++) {
       +                if (i >= 8)
       +                        i = 0; /* wrap around */
       +                if (rank[i])
       +                        continue;
       +                if (n2) {
       +                        n2--;
       +                        continue;
       +                }
       +                rank[i] = 'N';
       +                break;
       +        }
       +
       +        /* there are three blank squares remaining; place a rook in each of the
       +           outer two and the king in the middle one. */
       +        for (i = 0; i < 8; i++) {
       +                if (rank[i])
       +                        continue;
       +                rank[i] = 'R';
       +                break;
       +        }
       +
       +        for (i = 7; i >= 0; i--) {
       +                if (rank[i])
       +                        continue;
       +                rank[i] = 'R';
       +                break;
       +        }
       +
       +        for (i = 0; i < 8; i++) {
       +                if (rank[i])
       +                        continue;
       +                rank[i] = 'K';
       +                break;
       +        }
       +
       +        rank[8] = '\0'; /* NUL */
       +}
       +
       +int
       +main(int argc, char *argv[])
       +{
       +        char fen[92], rank[9];
       +        long l;
       +        int i;
       +
       +        if (argc > 2) {
       +usage:
       +                fprintf(stderr, "usage: %s <0-959>\n", argv[0]);
       +                return 1;
       +        }
       +
       +        if (argc == 2) {
       +                l = strtol(argv[1], NULL, 10);
       +                if (l < 0 || l > 959)
       +                        goto usage;
       +                postab(l, rank);
       +                ranktofen(fen, sizeof(fen), rank);
       +                printf("%s\n", fen);
       +        } else {
       +                /* 518 is classical */
       +                for (i = 0; i < 960; i++) {
       +                        postab(i, rank);
       +                        ranktofen(fen, sizeof(fen), rank);
       +                        printf("%d\t%s\n", i, fen);
       +                }
       +        }
       +
       +        return 0;
       +}