#include "includes.h" #include "knightcap.h" extern struct state *state; void beep(int n) { while (n--) { putc(7,stdout); fflush(stdout); sleep(1); } } static inline void simple_merge(Move *m1,Move *m2,Move *d,int n1,int n2) { while (n1 > 0 && n2 > 0) { if (m1->v >= m2->v) { *d++ = *m1++; --n1; } else { *d++ = *m2++; --n2; } } while (n1--) { *d++ = *m1++; } while (n2--) { *d++ = *m2++; } } void sort_moves(Move *m, int n) { static Move tmp[MAX_MOVES]; Move *p1, *p2, *p3; int l, i; p1 = m; p2 = tmp; for (l=1; l=n?n-i:l, i+l>=n?0:(n-i)-l); } p3 = p1; p1 = p2; p2 = p3; } if (p2 == m) { for (i=0;ifrom), posstr(move->to)); if (p && abs(p->board[move->from]) == PAWN && (YPOS(move->to) == 0 || YPOS(move->to) == 7)) { /* assume a queen */ sprintf(ret+strlen(ret),"=q"); } return ret; } char *movestr(Position *p, Move *move) { static char ret[80]; ret[0] = 0; if (next_to_play(&state->position) == state->computer) { sprintf(ret, "%d. ... %s", 1+(p->move_num/2), short_movestr(p, move)); } #if 0 else { sprintf(ret, "%d. %s", 1+(p->move_num/2), short_movestr(p, move)); } #endif return ret; } void print_move(Position *p, Move *move) { printf("%s\n", movestr(p, move)); fflush(stdout); } char *colorstr(Piece p) { static char *b = "B"; static char *w = "W"; if (p < 0) return b; return w; } int is_sliding(Piece p) { static const int sliding[KING+1] = {0, 0, 0, 1, 1, 1, 0}; return sliding[abs(p)]; } int charpiece(char c) { switch (tolower(c)) { case 'p': return PAWN; case 'n': return KNIGHT; case 'r': return ROOK; case 'b': return BISHOP; case 'q': return QUEEN; case 'k': return KING; } return 0; } static int isrank(char c) { return (c >= '1' && c <= '8'); } static int isfile(char c) { return (c >= 'a' && c <= 'h'); } int parse_square(char *s, int *sq) { if (s[0] < 'a' || s[0] > 'h' || s[1] < '1' || s[1] > '8') return 0; *sq = POSN(s[0]-'a', s[1] - '1'); return 1; } int parse_algebraic(char *s, Position *b, Move *move) { int capture = 0; int piece = -1; int from = -1, to = -1, file = -1, rank = -1; int n, i; Move moves[MAX_MOVES]; if (isdigit(s[1]) && isfile(s[0])) { /* it must be a pawn move */ if (!parse_square(s, &to)) return 0; file = XPOS(to); piece = PAWN; } else if (isupper(s[0])) { /* its a piece move */ piece = charpiece(s[0]); if (s[1] == 'x') { capture = 1; if (!parse_square(s+2, &to)) return 0; } else if (s[2] == 'x') { capture = 1; if (isfile(s[1])) { file = s[1] - 'a'; } else if (isrank(s[1])) { rank = s[1] - '1'; } else { return 0; } if (!parse_square(s+3, &to)) return 0; } else if (s[3] == 'x') { capture = 1; if (!parse_square(s+1, &from)) return 0; if (isupper(s[4])) { if (!parse_square(s+5, &to)) return 0; } else { if (!parse_square(s+4, &to)) return 0; } } else { /* its not a capture! */ if (parse_square(s+3, &to)) { if (!parse_square(s+1, &from)) return 0; } else if (parse_square(s+2, &to)) { if (isfile(s[1])) { file = s[1] - 'a'; } else if (isrank(s[1])) { rank = s[1] - '1'; } else { return 0; } } else if (!parse_square(s+1, &to)) { return 0; } } } else { /* it must be a pawn capture */ piece = PAWN; capture = 1; if (s[1] != 'x' || !parse_square(s+2, &to)) return 0; } if (blacks_move(b)) piece = -piece; /* now generate all the moves and see which one matches */ n = generate_moves(b, moves); for (i=0;iboard[moves[i].from] != piece) continue; if (to != -1 && moves[i].to != to) continue; if (from != -1 && moves[i].from != from) continue; if (file != -1 && XPOS(moves[i].from) != file) continue; if (rank != -1 && YPOS(moves[i].from) != rank) continue; break; } if (i == n) return 0; (*move) = moves[i]; return 1; } int parse_move(char *s, Position *b, Move *move) { char x1, x2, y1, y2, becomes; int ret; b->promotion = 0; /* maybe its castling */ if (strcasecmp(s, "o-o")==0) { if (whites_move(b)) { move->from = E1; move->to = G1; return 1; } else { move->from = E8; move->to = G8; return 1; } } if (strcasecmp(s, "o-o-o")==0) { if (whites_move(b)) { move->from = E1; move->to = C1; return 1; } else { move->from = E8; move->to = C8; return 1; } } if (s[2] == '-') ret = sscanf(s,"%c%c-%c%c%c", &x1, &y1, &x2, &y2, &becomes); else ret = sscanf(s,"%c%c%c%c%c", &x1, &y1, &x2, &y2, &becomes); if (ret < 4 || x1 < 'a' || x1 > 'h' || x2 < 'a' || x2 > 'h' || y1 < '1' || y1 > '8' || y2 < '1' || y2 > '8') { return parse_algebraic(s, b, move); } move->from = POSN(x1-'a', y1-'1'); move->to = POSN(x2-'a', y2-'1'); if (ret == 5 && (y1 == '2' || y1 == '7') && (y2 == '1' || y2 == '8')) { b->promotion = charpiece(becomes); } return 1; } void *Realloc(void *p, int size) { void *ret; if (p) { ret = (void *)realloc(p, size); } else { ret = (void *)malloc(size); } if (!ret) { lprintf(0, "Realloc %d failed\n", size); return NULL; } return ret; } void ring_bell(void) { putchar(7); fflush(stdout); } /* this assumes a color_xterm */ void print_board(Piece *board) { extern int color_display; char *yellow = ""; char *blue = ""; char *normal = ""; char piece[KING+1] = " pNBRQK"; Piece p; int x,y; printf("---------------------------------\n"); for (y=7;y>=0;y--) { for (x=0;x<8;x++) { p = board[POSN(x,y)]; if (color_display) { printf("| %s%c%s ", p > 0 ? yellow : blue, piece[abs(p)], normal); } else { if (p >= 0) printf("| %c ", piece[abs(p)]); else printf("|*%c ", piece[abs(p)]); } } if (y != 0) { printf("|\n|---+---+---+---+---+---+---+---|\n"); } } printf("|\n---------------------------------\n"); } void print_bitboard(uint64 bitboard) { int x,y; uint64 mask; printf("---------------------------------\n"); for (y=7;y>=0;y--) { for (x=0;x<8;x++) { mask = ((uint64)1<=0;y--) { count = 0; for (x=0;x<8;x++) { if (b->board[POSN(x,y)] == 0) { count++; continue; } if (count) { *p++ = '0' + count; count = 0; } *p++ = piecechar(b->board[POSN(x,y)]); } if (count) *p++ = '0' + count; if (y > 0) *p++ = '/'; } *p++ = ' '; if (whites_move(b)) *p++ = 'w'; else *p++ = 'b'; *p++ = ' '; if (!(b->flags & FLAG_CAN_CASTLE)) { *p++ = '-'; } else { if (b->flags & WHITE_CASTLE_SHORT) *p++ = 'K'; if (b->flags & WHITE_CASTLE_LONG) *p++ = 'Q'; if (b->flags & BLACK_CASTLE_SHORT) *p++ = 'k'; if (b->flags & BLACK_CASTLE_LONG) *p++ = 'q'; } *p++ = ' '; if (b->enpassent) { strcat(p, posstr(b->enpassent)); } else { *p++ = '-'; } return ppn; } /* convert a ppn to a position, returning a pointer to the char after the ppn ends (which often has "best move" etc in it) */ char *ppn_to_position(char *ppn, Position *b) { int x, y; char *p = ppn; memset(b, 0, sizeof(*b)); for (y=7;y>=0;y--) { for (x=0;x<8;) { if (isdigit(*p)) { x += (*p) - '0'; p++; continue; } b->board[POSN(x,y)] = charpiece(*p); if (islower(*p)) b->board[POSN(x,y)] = -b->board[POSN(x,y)]; p++; x++; } p++; } b->move_num = 30; /* arbitrary */ if ((*p) == 'b') b->move_num++; p += 2; b->flags = 0; if ((*p) == '-') { p++; } else { while ((*p) && (*p) != ' ') { if ((*p) == 'k') b->flags |= BLACK_CASTLE_SHORT; if ((*p) == 'q') b->flags |= BLACK_CASTLE_LONG; if ((*p) == 'K') b->flags |= WHITE_CASTLE_SHORT; if ((*p) == 'Q') b->flags |= WHITE_CASTLE_LONG; p++; } } p++; if ((*p) == '-') { p++; b->enpassent = 0; } else { x = p[0] - 'a'; y = p[1] - '1'; b->enpassent = POSN(x,y); p += 2; } p++; create_pboard(b); return p; } uint16 swapu16(uint16 x) { char *s = (char *)&x; char t; t = s[0]; s[0] = s[1]; s[1] = t; return x; } int16 swap16(int16 x) { char *s = (char *)&x; char t; t = s[0]; s[0] = s[1]; s[1] = t; return x; } uint32 swapu32(uint32 x) { char *s = (char *)&x; char t; t = s[0]; s[0] = s[3]; s[3] = t; t = s[1]; s[1] = s[2]; s[2] = t; return x; } int swap32(int x) { char *s = (char *)&x; char t; t = s[0]; s[0] = s[3]; s[3] = t; t = s[1]; s[1] = s[2]; s[2] = t; return x; } int Write(int fd, char *buf, size_t count) { int r,total; total = 0; while (count) { r = write(fd, buf, count); if (r == -1) { if (errno == EINTR) continue; if (total) return total; return -1; } total += r; count -= r; buf += r; } return total; } int Read(int fd, char *buf, size_t count) { int r,total; total = 0; while (count) { r = read(fd, buf, count); if (r == -1) { if (errno == EINTR) continue; if (total) return total; return -1; } total += r; count -= r; buf += r; } return total; } int result() { if (state->won == UNKNOWN || (state->auto_exit && state->won == STALEMATE)) { /* haven't heard from ICS who won so determine it from board and colour. Need to fix this */ if (state->position.winner == STALEMATE) { state->won = STALEMATE; } else if (state->position.winner == (state->ics_robot||state->auto_exit?state->colour:state->computer)) { state->won = 1; } else if (state->position.winner == (state->ics_robot||state->auto_exit?-state->colour:-state->computer)) { state->won = 0; } else { state->won = TIME_FORFEIT; } } return (state->won); } void p_coeff_vboard(etype *p) { int x, y; for (y=0; y<8; y++) { for (x=0; x<8; x++) { lprintf(0,"%9.3f", *(p + x + y*8)); } printf("\n"); } } char *evalstr(etype v) { static char ret[50]; if (v >= INFINITY-1) { sprintf(ret, "Inf"); } else if (v <= -INFINITY+1) { sprintf(ret, "-Inf"); } else if (v > FORCED_WIN) { sprintf(ret,"Mate%02d", (int)((WIN-v)/2 + 1)); } else if (v < -FORCED_WIN) { sprintf(ret,"-Mate%02d", (int)((v + WIN)/2 + 1)); } else { sprintf(ret,"%3.2f", ((double)v)/STATIC_PAWN_VALUE); } return ret; } void dump_ppn(Position *b) { static int initialised; static FILE *f; if (!initialised) { initialised = 1; #if USE_APPLET f = fopen("/export/pasiphae/position.txt", "w"); #else f = fopen("position.txt", "w"); #endif } rewind(f); fprintf(f, "%s * %d %s %d %d %s %d %d %s %d %d ", position_to_ppn(b), state->mulling, state->white_player, state->colour==1?state->krating:state->orating, state->wtime, state->black_player, state->colour==1?state->orating:state->krating, state->btime, state->game_type, state->game_time, state->increment); fflush(f); } void dump_history() { static int initialised; static FILE *bullet, *blitz, *standard, *f; if (!initialised) { initialised = 1; #if USE_APPLET bullet = fopen("/export/pasiphae/bullet.txt", "a"); blitz = fopen("/export/pasiphae/blitz.txt", "a"); standard = fopen("/export/pasiphae/standard.txt", "a"); #else bullet = fopen("bullet.txt", "a"); blitz = fopen("blitz.txt", "a"); standard = fopen("standard.txt", "a"); #endif } if (strstr(state->game_type,"bullet") || strstr(state->game_type,"lightning")) { f = bullet; } else if (strstr(state->game_type,"blitz")) { f = blitz; } else if (strstr(state->game_type, "standard")) { f = standard; } else { return; } fprintf(f, "%d %d\n", state->total_rounds, state->krating); fflush(f); }