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 }