Last active
September 11, 2017 06:09
-
-
Save erantapaa/cb275219ebe931318614e532bdb8e5e7 to your computer and use it in GitHub Desktop.
minichess board positions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* "3x3c.c" - source file of the 3x3 chess solver, version 1.0.0 | |
* | |
* Copyright (c) 2004-2011 Kirill Kryukov | |
* | |
* This software is provided 'as-is', without any express or implied warranty. | |
* In no event will the authors be held liable for any damages arising from | |
* the use of this software. | |
* | |
* Permission is granted to anyone to use this software for any purpose, | |
* including commercial applications, and to alter it and redistribute it | |
* freely, subject to the following restrictions: | |
* | |
* 1. The origin of this software must not be misrepresented; you must | |
* not claim that you wrote the original software. If you use this | |
* software in a product, an acknowledgment in the product | |
* documentation would be appreciated but is not required. | |
* | |
* 2. Altered source versions must be plainly marked as such, and must not | |
* be misrepresented as being the original software. | |
* | |
* 3. This notice may not be removed or altered from any source distribution. | |
*/ | |
/* | |
* 3x3 chess: pawns are allowed on the first rank. No castling, no double pawn | |
* step. | |
* | |
* In drawn positions stalemate is used as a goal (Assuming it's better to | |
* stalemate than to be stalemated). | |
*/ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <time.h> | |
#include "move.c" | |
const int kingw[17] = {0,0,0,0,0,1,1,3,3,3,6,6,6,6,6,7,7}; | |
const int kingb[17] = {2,5,6,7,8,6,7,2,5,8,0,1,2,5,8,0,1}; | |
const int pagenum[81] = | |
{ | |
0, 0, 1, 0, 0, 2, 3, 4, 5, | |
0, 0, 0, 0, 0, 0, 6, 7, -6, | |
-1, 0, 0, -2, 0, 0, -5, -4, -3, | |
0, 0, 8, 0, 0, 9, 0, 0, 10, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, | |
-8, 0, 0, -9, 0, 0,-10, 0, 0, | |
11, 12, 13, 0, 0, 14, 0, 0, 15, | |
16, 17,-16, 0, 0, 0, 0, 0, 0, | |
-13,-12,-11,-14, 0, 0,-15, 0, 0 | |
}; | |
const int location[17][7] = | |
{ | |
{ 1, 3,4,5,6,7,8}, | |
{ 1,2,3,4, 6,7,8}, | |
{ 1,2,3,4,5, 7,8}, | |
{ 1,2,3,4,5,6, 8}, | |
{ 1,2,3,4,5,6,7 }, | |
{0, 2,3,4,5, 7,8}, | |
{0, 2,3,4,5,6, 8}, | |
{0,1, 4,5,6,7,8}, | |
{0,1,2, 4, 6,7,8}, | |
{0,1,2, 4,5,6,7 }, | |
{ 1,2,3,4,5, 7,8}, | |
{0, 2,3,4,5, 7,8}, | |
{0,1, 3,4,5, 7,8}, | |
{0,1,2,3,4, 7,8}, | |
{0,1,2,3,4,5, 7 }, | |
{ 1,2,3,4,5,6, 8}, | |
{0, 2,3,4,5,6, 8} | |
}; | |
const int vflip[9] = {6,7,8,3,4,5,0,1,2}; | |
const int hflip[9] = {2,1,0,5,4,3,8,7,6}; | |
const int pagebytes = 19487171; | |
const int dbsize = 17*19487171; | |
const char piece_to_index[16] = {0,0,1,2,3,4,5,0,0,0,6,7,8,9,10,0}; | |
const char index_to_piece[11] = {0,2,3,4,5,6,10,11,12,13,14}; | |
const char filechar[9]={'a','b','c','a','b','c','a','b','c'}; | |
const char rankchar[9]={'3','3','3','2','2','2','1','1','1'}; | |
const char piece_to_char[16] = {'.','K','Q','R','B','N','P','?','?','k','q','r','b','n','p','?'}; | |
const char char_to_piece[256] = | |
{ | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15, 0,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15, 4,15,15,15,15,15,15,15,15, 1,15,15, 5,15, | |
6, 2, 3,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,12,15,15,15,15,15,15,15,15, 9,15,15,13,15, | |
14,10,11,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, | |
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 | |
}; | |
char* pages[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | |
int wk,bk; | |
int page; | |
char* pagebase; | |
int pieces[7] = {0,0,0,0,0,0,0}; | |
int board[9] = {0,0,0,0,0,0,0,0,0}; | |
int ofs = 0; | |
int wk1,bk1; | |
int board1[9]; | |
int found = 0; | |
int illegal_count = 0; | |
int checkmate_count = 0; | |
int stalemate_count = 0; | |
char* dbname = "db.dat"; | |
FILE *db = 0; | |
int sideswap = 0; | |
#define swap(a,b) { int c=a; a=b; b=c; } | |
static void print_time() { int sec = clock()/CLOCKS_PER_SEC; printf(" (%02d:%02d:%02d)\n",sec/(60*60),(sec%(60*60))/60,sec%60); } | |
static inline void b2w() | |
{ | |
swap(wk1,bk1); | |
for (int i=0; i<9; i++) if (board1[i]) board1[i]^=8; | |
wk1 = vflip[wk1]; | |
bk1 = vflip[bk1]; | |
swap(board1[0],board1[6]); | |
swap(board1[1],board1[7]); | |
swap(board1[2],board1[8]); | |
} | |
static inline int fixpage() | |
{ | |
int p = pagenum[wk1*9+bk1]; | |
if (p<0) | |
{ | |
swap(board1[0],board1[2]); | |
swap(board1[3],board1[5]); | |
swap(board1[6],board1[8]); | |
wk1 = hflip[wk1]; | |
bk1 = hflip[bk1]; | |
return -p-1; | |
} | |
else return p-1; | |
} | |
static inline int getofs() | |
{ | |
int ofs1 = 0; | |
for (int j=0; j<9; j++) if ((board1[j]&7)!=1) ofs1 = ofs1*11 + piece_to_index[board1[j]]; | |
return ofs1; | |
} | |
static inline char lookup() { b2w(); int p = fixpage(); return pages[p][getofs()]; } | |
static inline void push() { wk1 = wk; bk1 = bk; memcpy(board1,board,36); } | |
static inline void pop() { wk = wk1; bk = bk1; memcpy(board,board1,36); } | |
static inline void mark_squares_attacked_by_black(int *a) | |
{ | |
for (int i=0; i<9; i++) | |
if (board[i]>=9) | |
{ | |
const int *am = move[board[i]][i]; | |
for (int t=0; t<9; t++) | |
if (am[t]&2) { int x = am[t]>>2; if (!x || !board[x]) a[t] = 1; } | |
} | |
} | |
static inline void mark_squares_attacked_by_white(int *a) | |
{ | |
for (int i=0; i<9; i++) | |
if (board[i]>=1 && board[i]<=6) | |
{ | |
const int *am = move[board[i]][i]; | |
for (int t=0; t<9; t++) | |
if (am[t]&2) { int x = am[t]>>2; if (!x || !board[x]) a[t] = 1; } | |
} | |
} | |
static int white_safe() | |
{ | |
if (board[0]==6 || board[1]==6 || board[2]==6 || board[6]==14 || board[7]==14 || board[8]==14) return 0; | |
int a[9] = {0,0,0,0,0,0,0,0,0}; | |
mark_squares_attacked_by_black(a); | |
if (a[wk]) { | |
return 0; | |
} | |
return 1; | |
} | |
static int black_safe() | |
{ | |
if (board[0]==6 || board[1]==6 || board[2]==6 || board[6]==14 || board[7]==14 || board[8]==14) return 0; | |
int a[9] = {0,0,0,0,0,0,0,0,0}; | |
mark_squares_attacked_by_white(a); | |
if (a[bk]) { | |
return 0; | |
} | |
return 1; | |
} | |
static int illegal() | |
{ | |
int a[9] = {0,0,0,0,0,0,0,0,0}; | |
mark_squares_attacked_by_white(a); | |
if (a[bk] || board[0]==6 || board[1]==6 || board[2]==6 || board[6]==14 || board[7]==14 || board[8]==14) return -47; | |
return 0; | |
} | |
static int checkmate_or_stalemate() | |
{ | |
int a[9] = {0,0,0,0,0,0,0,0,0}; | |
int attackers = 0; | |
int attacker_location = 0; | |
int pinned[9] = {0,0,0,0,0,0,0,0,0}; | |
int who_is_pinning[9] = {0,0,0,0,0,0,0,0,0}; | |
for (int i=0; i<9; i++) | |
if (board[i]>=9) | |
{ | |
const int *am = move[board[i]][i]; | |
for (int t=0; t<9; t++) | |
{ | |
int m = am[t]; | |
if (!(m&2)) continue; | |
int x = m>>2; | |
if (x && board[x]) { if (t==wk && !(board[x]>>3)) { pinned[x] = 1; who_is_pinning[x] = i; } continue; } | |
a[t] = 1; | |
if (t==wk) { attackers++; attacker_location = i; } | |
} | |
} | |
for (int k=0; k<9; k++) | |
if (move[1][wk][k] && !a[k] && (!board[k] || board[k]>=10)) | |
{ | |
push(); | |
board1[wk1] = 0; | |
wk1 = k; | |
board1[wk1] = 1; | |
char d = lookup(); | |
if (d>=-46) return 0; | |
} | |
if (attackers==1) | |
{ | |
int d = move[board[attacker_location]][attacker_location][wk]>>2; | |
for (int j=0; j<9; j++) | |
if (board[j]>=2 && board[j]<=6 && !pinned[j]) | |
{ | |
int m = move[board[j]][j][attacker_location]; | |
if (m&2) { int x = m>>2; if (!x || !board[x]) return 0; } | |
if (d) { m = move[board[j]][j][d]; if (m&1) { int x = m>>2; if (!x || !board[x]) return 0; } } | |
} | |
} | |
if (attackers==0) | |
for (int j=0; j<9; j++) | |
if (board[j]>=2 && board[j]<=6) | |
{ | |
const int *bm = move[board[j]][j]; | |
if (pinned[j]) { if (bm[who_is_pinning[j]]&2) return 0; } | |
else for (int t=0; t<9; t++) | |
{ | |
int tp = board[t]; | |
int m = bm[t]; | |
if (!m || (tp>=1 && tp<=6)) continue; | |
if (!tp && !(m&1)) continue; | |
if (tp && !(m&2)) continue; | |
int x = m>>2; | |
if (x && board[x]) continue; | |
return 0; | |
} | |
} | |
return a[wk]?-46:-23; | |
} | |
static int analyze() | |
{ | |
int mn = 47, attacked[9] = {0,0,0,0,0,0,0,0,0}; | |
mark_squares_attacked_by_black(attacked); | |
const int *mm = move[1][wk]; | |
for (int t=0; t<9; t++) | |
if (mm[t] && !attacked[t] && (board[t]<1 || board[t]>6)) | |
{ | |
push(); board1[wk1] = 0; wk1 = t; board1[wk1] = 1; | |
char d = lookup(); if (d>-47 && d<mn) mn = d; | |
} | |
for (int s=0; s<9; s++) | |
{ | |
int sp = board[s]; | |
if (sp>=2 && sp<=6) | |
{ | |
mm = move[sp][s]; | |
for (int t=0; t<9; t++) | |
{ | |
int tp = board[t]; | |
int m = mm[t]; | |
if (!m || (tp>=1 && tp<=6)) continue; | |
if (!tp && !(m&1)) continue; | |
if (tp && !(m&2)) continue; | |
int x = m>>2; | |
if (x && board[x]) continue; | |
if (sp==6 && t<=2) | |
for (int pp=2; pp<6; pp++) | |
{ | |
push(); board1[t] = pp; board1[s] = 0; | |
char d = lookup(); if (d>-47 && d<mn) mn = d; | |
} | |
else | |
{ | |
push(); board1[t] = board[s]; board1[s] = 0; | |
char d = lookup(); if (d>-47 && d<mn) mn = d; | |
} | |
} | |
} | |
} | |
int res = (mn==47)?47:((mn>0)?1-mn:-mn); | |
return (res==found)?res:0; | |
} | |
static void cycle_init() | |
{ | |
wk = kingw[page]; bk = kingb[page]; pagebase = pages[page]; | |
memset(pieces,0,28); memset(board,0,36); | |
board[wk] = 1; board[bk] = 9; | |
ofs = 0; | |
} | |
int iterate() | |
{ | |
ofs++; | |
if (ofs>=pagebytes) return 0; | |
int i = 6; | |
while (i>=0 && pieces[i]==10) i--; | |
if (i==-1) return 0; | |
pieces[i]++; | |
board[location[page][i]] = index_to_piece[pieces[i]]; | |
while (i<6) | |
{ | |
i++; | |
pieces[i] = 0; | |
board[location[page][i]] = 0; | |
} | |
return 1; | |
} | |
void one_phase(int start) | |
{ | |
int iteration = 1, changed = 1, analyzed; | |
found = start; | |
while (changed) | |
{ | |
changed = 0; | |
analyzed = 0; | |
printf(" %2d ",iteration); | |
for (page=0; page<17; page++) | |
{ | |
printf("*"); cycle_init(); | |
do { | |
if (!pagebase[ofs]) | |
{ | |
analyzed++; | |
char r = analyze(); | |
if (r) { changed++; pagebase[ofs] = r; } | |
} | |
} while (iterate()); | |
} | |
printf(" %9d %9d",changed,analyzed); print_time(); | |
found = found>0?1-found:-found; | |
iteration++; | |
} | |
} | |
void count_valid() | |
{ | |
for (int a=0; a<17 && (pages[a]=(char*)malloc(pagebytes)); a++) {} | |
if (!pages[16]) { printf("fail\n"); return; } | |
printf("resetting "); | |
for (int s=0; s<17; s++) { printf("."); memset(pages[s],0,pagebytes); } | |
printf(" ok"); print_time(); | |
int total_count = 0; | |
int total_black_safe = 0; | |
int total_both_safe = 0; | |
for (int wk0 = 0; wk0 < 9; ++wk0) { | |
for (int bk0 = 0; bk0 < 9; ++bk0) { | |
int p = pagenum[9*wk0+bk0]; | |
if (p == 0) continue; | |
page = p < 0 ? -p-1 : p-1; | |
int page_total = 0; | |
int page_both_safe = 0; | |
int page_black_safe = 0; | |
cycle_init(); | |
do { | |
page_total++; | |
if (black_safe()) { | |
page_black_safe++; | |
if (white_safe()) { | |
page_both_safe++; | |
} | |
} | |
} while (iterate()); | |
printf("%d %d page: %2d total: %10d black_safe: %10d both_safe: %10d\n", | |
wk0, bk0, page, page_total, page_black_safe, page_both_safe); | |
total_count += page_total; | |
total_black_safe += page_black_safe; | |
total_both_safe += page_both_safe; | |
} | |
} | |
printf(" ok"); print_time(); | |
printf("total : %11d\n", total_count); | |
printf("both : %11d\n", total_both_safe); | |
printf("black : %11d\n", total_black_safe); | |
} | |
void build() | |
{ | |
printf("constructing database\n"); | |
printf("allocating %d bytes .. ",17*pagebytes); | |
for (int a=0; a<17 && (pages[a]=(char*)malloc(pagebytes)); a++) {} | |
if (!pages[16]) { printf("fail\n"); return; } | |
printf("resetting "); | |
for (int s=0; s<17; s++) { printf("."); memset(pages[s],0,pagebytes); } | |
printf(" ok"); print_time(); | |
printf("marking illegal positions "); | |
int total_count = 0; | |
for (page=0; page<17; page++) | |
{ | |
printf("."); cycle_init(); | |
do { total_count++; if (illegal()) { illegal_count++; pagebase[ofs] = -47; } } while (iterate()); | |
} | |
printf(" ok"); print_time(); | |
printf("total: %d, illegal: %d, legal: %d\n", total_count, illegal_count, total_count - illegal_count); | |
return; | |
printf("marking checkmates "); | |
for (page=0; page<17; page++) | |
{ | |
printf("."); cycle_init(); | |
do { if (!pagebase[ofs] && checkmate_or_stalemate()==-46) { checkmate_count++; pagebase[ofs] = -46; } } while (iterate()); | |
} | |
printf(" ok"); print_time(); | |
printf("%d illegal, %d checkmates, %d normal positions\n", | |
illegal_count,checkmate_count,dbsize-illegal_count-checkmate_count); | |
printf(" _________________ changed analyzed\n"); | |
one_phase(46); | |
printf(" "); | |
for (page=0; page<17; page++) | |
{ | |
printf("."); cycle_init(); | |
do if (!pagebase[ofs] && checkmate_or_stalemate()==-23) { stalemate_count++; pagebase[ofs] = -23; } | |
while (iterate()); | |
} | |
printf(" %9d stalemates",stalemate_count); print_time(); | |
one_phase(23); | |
printf("writing the database file \"%s\" (330 MB)",dbname); | |
if (!(db=fopen(dbname,"wb"))) { printf(" - can't create file\n"); } | |
else | |
{ | |
for (int y=0; y<17; y++) | |
for (int z=0; z<pagebytes; z++) | |
pages[y][z] += 79; | |
int w=0; | |
for (int t=0; t<17; t++) { printf("."); w += fwrite(pages[t],1,pagebytes,db); } | |
fclose(db); db = 0; | |
printf(w==dbsize?"ok":"fail"); print_time(); | |
} | |
} | |
char lookup_file(int side) | |
{ | |
if (!db) { db = fopen(dbname,"rb"); if (!db) return 100; } | |
if (side) b2w(); | |
fixpage(); | |
int offset = (pagenum[wk1*9+bk1]-1)*pagebytes + getofs(); | |
char a; | |
fseek(db,offset,SEEK_SET); | |
fread(&a,1,1,db); | |
return a-79; | |
} | |
int load_position(char* s) | |
{ | |
int hexnumber = -1; | |
if (strlen(s)>2 && s[0]=='0' && s[1]=='x') | |
{ | |
hexnumber = strtol(s+2,0,16); | |
if (hexnumber<0 || hexnumber>331281907) { printf(" position index must be in range 0x0..0x13BEF5F3\n"); return 0; } | |
sideswap = 0; | |
int pgnum = hexnumber/pagebytes; | |
wk1 = kingw[pgnum]; | |
bk1 = kingb[pgnum]; | |
printf("%d -> page %d (wk at %d, bk at %d)\n",hexnumber,pgnum,wk1,bk1); | |
board1[wk1] = 1; | |
board1[bk1] = 9; | |
int a = hexnumber - pgnum*pagebytes; | |
for (int i=0; i<7; i++) | |
{ | |
int b = a%11; | |
printf("%d -> %d at %d\n",a,b,location[pgnum][6-i]); | |
board1[location[pgnum][6-i]] = index_to_piece[b]; | |
a = a/11; | |
} | |
} | |
if (hexnumber<0) | |
{ | |
if (strlen(s)!=10 ) { printf(" position description must be 10 characters long\n"); return 0; } | |
if (*s!='w' && *s!='b') { printf(" first character must be 'w' or 'b'\n"); return 0; } | |
sideswap = (*s=='b'); | |
for (int i=0; i<9; i++) board1[i] = char_to_piece[(unsigned char)s[i+1]]; | |
} | |
{ printf(" %c ",sideswap?'b':' '); for (int i=0; i<3; i++) printf(" %c",piece_to_char[board1[i]]); printf("\n"); } | |
{ printf(" "); for (int i=3; i<6; i++) printf(" %c",piece_to_char[board1[i]]); printf("\n"); } | |
{ printf(" %c ",sideswap?' ':'w'); for (int i=6; i<9; i++) printf(" %c",piece_to_char[board1[i]]); printf("\n"); } | |
int wn=0,bn=0,in=0; | |
for (int c=0; c<9; c++) | |
{ if (board1[c]==15) in++; if (board1[c]==1) { wn++; wk1 = c; } if (board1[c]==9) { bn++; bk1 = c; } } | |
if (in) { printf(" illegal characters found (other than .KQRBNPkqrbnp)\n"); return 0; } | |
if (wn!=1 || bn!=1) { printf(" one white and one black king must be present\n"); return 0; } | |
if (!pagenum[wk1*9+bk1]) { printf(" illegal kings placement\n"); return 0; } | |
if (sideswap) b2w(); | |
pop(); | |
int res = lookup_file(0); | |
if (res==100) printf(" can't read file\n"); | |
else if (res==-47) printf(" illegal position\n"); | |
else if (res==0) printf(" draw\n"); | |
else if (res>=1 && res<=23) printf(" draw (stalemate in %d)\n",24-res); | |
else if (res>=24 && res<=46) printf(" win in %d\n",47-res); | |
else if (res>=-22 && res<=-1) printf(" draw (get stalemated in %d)\n",res+23); | |
else if (res==-23) printf(" stalemate\n"); | |
else if (res>=-45 && res<=-24) printf(" lose in %d\n",res+46); | |
else if (res==-46) printf(" checkmate\n"); | |
else printf(" unknown\n"); | |
return 1; | |
} | |
void print_move(int from,int to,char promote,int res) | |
{ | |
printf(" %c",piece_to_char[board[from]]); | |
char mc = board[to]?'x':'-'; | |
if (sideswap) { from = vflip[from]; to = vflip[to]; } | |
printf("%c%c%c%c%c",filechar[from],rankchar[from],mc,filechar[to],rankchar[to]); | |
if (promote) printf("%c",promote); | |
printf(" -> "); | |
if (res==-47) printf("illegal\n"); | |
else if (res==0) printf("draw\n"); | |
else if (res==-46) printf("checkmate\n"); | |
else if (res==-23) printf("stalemate\n"); | |
else if (res>=1 && res<=23) printf("draw (stalemated in %d)\n",24-res); | |
else if (res>=-22 && res<=-1) printf("draw (stalemate in %d)\n",res+24); | |
else if (res>=24 && res<=46) printf("loss in %d\n",47-res); | |
else if (res>=-45 && res<=-24) printf("win in %d\n",res+47); | |
} | |
void tell() | |
{ | |
int attacked[9]={0,0,0,0,0,0,0,0,0}; | |
mark_squares_attacked_by_black(attacked); | |
const int *mm = move[1][wk]; | |
for (int t=0; t<9; t++) | |
if (mm[t] && !attacked[t] && !(board[t]>=2 && board[t]<=6)) | |
{ | |
push(); board1[wk1] = 0; wk1 = t; board1[wk1] = 1; | |
print_move(wk,t,0,lookup_file(1)); | |
} | |
for (int s=0; s<9; s++) | |
{ | |
int sp = board[s]; | |
if (sp>=2 && sp<=6) | |
{ | |
mm = move[sp][s]; | |
for (int t=0; t<9; t++) | |
{ | |
int m = mm[t]; | |
if (!m) continue; | |
int tp = board[t]; | |
if (tp && !(tp>>3)) continue; | |
if (!tp && !(m&1)) continue; | |
if (tp && !(m&2)) continue; | |
int x = m>>2; | |
if (x && board[x]) continue; | |
if (sp==6 && t<=2) | |
for (int pp=2; pp<6; pp++) | |
{ | |
push(); board1[t] = pp; board1[s] = 0; | |
print_move(s,t,piece_to_char[pp],lookup_file(1)); | |
} | |
else | |
{ | |
push(); board1[t] = board[s]; board1[s] = 0; | |
print_move(s,t,0,lookup_file(1)); | |
} | |
} | |
} | |
} | |
} | |
void done() | |
{ | |
for (int d=0; d<17; d++) if (pages[d]) free(pages[d]); | |
if (db) fclose(db); | |
} | |
static char* helpstr = | |
"3x3 chess solver by Kirill Kryukov\n" | |
"\n" | |
" To build the database: 3x3c -build\n" | |
" To query a position: 3x3c <position>\n" | |
" To enter query mode: 3x3c\n" | |
"\n" | |
"You need 330 MB of RAM to construct the database\n" | |
"You need same amount of disk space to save it\n" | |
"\n" | |
"Position format = 10 characters:\n" | |
" First character: 'w' or 'b' (side to move).\n" | |
" The other nine characters describe the board.\n" | |
" Order of squares is: 1 2 3\n" | |
" 4 5 6\n" | |
" 7 8 9\n" | |
" Empty square is '.', piece are K,Q,R,B,N,P.\n" | |
" Capital letters for white pieces, small - for black.\n" | |
" Example position: wK.k..NqRn\n" | |
"\n" | |
"Without parameters solver enters the query mode, if the database is already built.\n" | |
"In the query mode it just waits for you to type positions.\n" | |
"Type 'quit' to finish."; | |
int main(int argc,char **argv) | |
{ | |
clock(); | |
atexit(done); | |
setbuf(stdout,0); | |
if (argc==2 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"-help"))) { puts(helpstr); return 0; } | |
if (argc==2 && !strcmp(argv[1],"-count")) { count_valid(); return 0; } | |
if (argc==2 && !strcmp(argv[1],"-build")) { build(); return 0; } | |
if (argc>2) { puts(helpstr); return 1; } | |
if (!(db=fopen(dbname,"rb"))) { printf("database is not constructed yet\ntype \"3x3c -h\" for help\n"); return 1; } | |
if (argc==2) { if (load_position(argv[1])) { tell(); return 0; } else return 1; } | |
if (argc>1) { printf("type \"3x3c -h\" for help\n"); return 1; } | |
printf("input a position, or type 'help' or 'exit'\n"); | |
char s[150]; printf("> "); | |
while (gets(s)) | |
{ | |
if (!strcmp(s,"quit")) break; | |
if (!strcmp(s,"help")) puts(helpstr); | |
else if (*s && load_position(s)) tell(); | |
printf("> "); | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
resetting ................. ok (00:00:00) | |
0 2 page: 0 total: 19487171 black_safe: 4942080 both_safe: 1644672 | |
0 5 page: 1 total: 19487171 black_safe: 3128832 both_safe: 1147608 | |
0 6 page: 2 total: 19487171 black_safe: 5559840 both_safe: 1931580 | |
0 7 page: 3 total: 19487171 black_safe: 4105728 both_safe: 1586304 | |
0 8 page: 4 total: 19487171 black_safe: 5559840 both_safe: 1966300 | |
1 6 page: 5 total: 19487171 black_safe: 6040320 both_safe: 1586304 | |
1 7 page: 6 total: 19487171 black_safe: 3779136 both_safe: 823543 | |
1 8 page: 5 total: 19487171 black_safe: 6040320 both_safe: 1586304 | |
2 0 page: 0 total: 19487171 black_safe: 4942080 both_safe: 1644672 | |
2 3 page: 1 total: 19487171 black_safe: 3128832 both_safe: 1147608 | |
2 6 page: 4 total: 19487171 black_safe: 5559840 both_safe: 1966300 | |
2 7 page: 3 total: 19487171 black_safe: 4105728 both_safe: 1586304 | |
2 8 page: 2 total: 19487171 black_safe: 5559840 both_safe: 1931580 | |
3 2 page: 7 total: 19487171 black_safe: 4818528 both_safe: 937916 | |
3 5 page: 8 total: 19487171 black_safe: 2612736 both_safe: 420175 | |
3 8 page: 9 total: 19487171 black_safe: 5436288 both_safe: 1147608 | |
5 0 page: 7 total: 19487171 black_safe: 4818528 both_safe: 937916 | |
5 3 page: 8 total: 19487171 black_safe: 2612736 both_safe: 420175 | |
5 6 page: 9 total: 19487171 black_safe: 5436288 both_safe: 1147608 | |
6 0 page: 10 total: 19487171 black_safe: 4928040 both_safe: 1348956 | |
6 1 page: 11 total: 19487171 black_safe: 3244032 both_safe: 1002064 | |
6 2 page: 12 total: 19487171 black_safe: 4942080 both_safe: 1404500 | |
6 5 page: 13 total: 19487171 black_safe: 3128832 both_safe: 937916 | |
6 8 page: 14 total: 19487171 black_safe: 5575680 both_safe: 1644672 | |
7 0 page: 15 total: 19487171 black_safe: 5353920 both_safe: 1002064 | |
7 1 page: 16 total: 19487171 black_safe: 2985984 both_safe: 420175 | |
7 2 page: 15 total: 19487171 black_safe: 5353920 both_safe: 1002064 | |
8 0 page: 12 total: 19487171 black_safe: 4942080 both_safe: 1404500 | |
8 1 page: 11 total: 19487171 black_safe: 3244032 both_safe: 1002064 | |
8 2 page: 10 total: 19487171 black_safe: 4928040 both_safe: 1348956 | |
8 3 page: 13 total: 19487171 black_safe: 3128832 both_safe: 937916 | |
8 6 page: 14 total: 19487171 black_safe: 5575680 both_safe: 1644672 | |
ok (00:02:45) | |
total : 623589472 | |
both : 40660996 | |
black : 145518672 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment