1 #include "includes.h"
2 #include "knightcap.h"
3
4 extern struct state *state;
5
beep(int n)6 void beep(int n)
7 {
8 while (n--) {
9 putc(7,stdout);
10 fflush(stdout);
11 sleep(1);
12 }
13 }
14
simple_merge(Move * m1,Move * m2,Move * d,int n1,int n2)15 static inline void simple_merge(Move *m1,Move *m2,Move *d,int n1,int n2)
16 {
17 while (n1 > 0 && n2 > 0) {
18 if (m1->v >= m2->v) {
19 *d++ = *m1++;
20 --n1;
21 } else {
22 *d++ = *m2++;
23 --n2;
24 }
25 }
26 while (n1--) {
27 *d++ = *m1++;
28 }
29 while (n2--) {
30 *d++ = *m2++;
31 }
32 }
33
sort_moves(Move * m,int n)34 void sort_moves(Move *m, int n)
35 {
36 static Move tmp[MAX_MOVES];
37 Move *p1, *p2, *p3;
38 int l, i;
39
40 p1 = m;
41 p2 = tmp;
42
43 for (l=1; l<n; l*=2) {
44 for (i=0; i<=(n-2*l); i += 2*l) {
45 simple_merge(p1+i,p1+(i+l),p2+i, l, l);
46 }
47 if (i < n) {
48 simple_merge(p1+i,p1+(i+l),p2+i,
49 i+l>=n?n-i:l,
50 i+l>=n?0:(n-i)-l);
51 }
52 p3 = p1;
53 p1 = p2;
54 p2 = p3;
55 }
56
57 if (p2 == m) {
58 for (i=0;i<n;i++) {
59 m[i] = tmp[i];
60 }
61 }
62 }
63
64
posstr(Square s)65 char *posstr(Square s)
66 {
67 static char ret[4][3];
68 static int i;
69 char *p;
70
71 p = ret[i];
72 i = (i+1)%4;
73
74 sprintf(p, "%c%c", XPOS(s) + 'a', YPOS(s) + '1');
75 return p;
76 }
77
piecestr(Piece p)78 char *piecestr(Piece p)
79 {
80 static char *names[7] = {"NONE", "PAWN", "KNIGHT", "BISHOP",
81 "ROOK", "QUEEN", "KING"};
82 return names[abs(p)];
83 }
84
85
piecechar(Piece p)86 char piecechar(Piece p)
87 {
88 static char names[2*KING+1] = "kqrbnp PNBRQK";
89 return names[p + KING];
90 }
91
92
short_movestr(Position * p,Move * move)93 char *short_movestr(Position *p, Move *move)
94 {
95 static char reti[4][10];
96 static int nexti;
97 char *ret = reti[nexti];
98
99 nexti = (nexti+1) % 4;
100
101 sprintf(ret, "%s%s", posstr(move->from), posstr(move->to));
102
103 if (p && abs(p->board[move->from]) == PAWN &&
104 (YPOS(move->to) == 0 || YPOS(move->to) == 7)) {
105 /* assume a queen */
106 sprintf(ret+strlen(ret),"=q");
107 }
108
109 return ret;
110 }
111
movestr(Position * p,Move * move)112 char *movestr(Position *p, Move *move)
113 {
114 static char ret[80];
115
116 ret[0] = 0;
117
118 if (next_to_play(&state->position) == state->computer) {
119 sprintf(ret, "%d. ... %s",
120 1+(p->move_num/2),
121 short_movestr(p, move));
122 }
123 #if 0
124 else {
125 sprintf(ret, "%d. %s",
126 1+(p->move_num/2),
127 short_movestr(p, move));
128 }
129 #endif
130 return ret;
131 }
132
print_move(Position * p,Move * move)133 void print_move(Position *p, Move *move)
134 {
135 printf("%s\n", movestr(p, move));
136 fflush(stdout);
137 }
138
colorstr(Piece p)139 char *colorstr(Piece p)
140 {
141 static char *b = "B";
142 static char *w = "W";
143 if (p < 0)
144 return b;
145 return w;
146 }
147
is_sliding(Piece p)148 int is_sliding(Piece p)
149 {
150 static const int sliding[KING+1] = {0, 0, 0, 1, 1, 1, 0};
151 return sliding[abs(p)];
152 }
153
charpiece(char c)154 int charpiece(char c)
155 {
156 switch (tolower(c)) {
157 case 'p': return PAWN;
158 case 'n': return KNIGHT;
159 case 'r': return ROOK;
160 case 'b': return BISHOP;
161 case 'q': return QUEEN;
162 case 'k': return KING;
163 }
164 return 0;
165 }
166
isrank(char c)167 static int isrank(char c)
168 {
169 return (c >= '1' && c <= '8');
170 }
171
isfile(char c)172 static int isfile(char c)
173 {
174 return (c >= 'a' && c <= 'h');
175 }
176
parse_square(char * s,int * sq)177 int parse_square(char *s, int *sq)
178 {
179 if (s[0] < 'a' || s[0] > 'h' ||
180 s[1] < '1' || s[1] > '8')
181 return 0;
182
183 *sq = POSN(s[0]-'a', s[1] - '1');
184 return 1;
185 }
186
187
parse_algebraic(char * s,Position * b,Move * move)188 int parse_algebraic(char *s, Position *b, Move *move)
189 {
190 int capture = 0;
191 int piece = -1;
192 int from = -1, to = -1, file = -1, rank = -1;
193 int n, i;
194 Move moves[MAX_MOVES];
195
196 if (isdigit(s[1]) && isfile(s[0])) {
197 /* it must be a pawn move */
198 if (!parse_square(s, &to))
199 return 0;
200 file = XPOS(to);
201 piece = PAWN;
202 } else if (isupper(s[0])) {
203 /* its a piece move */
204 piece = charpiece(s[0]);
205 if (s[1] == 'x') {
206 capture = 1;
207 if (!parse_square(s+2, &to))
208 return 0;
209 } else if (s[2] == 'x') {
210 capture = 1;
211 if (isfile(s[1])) {
212 file = s[1] - 'a';
213 } else if (isrank(s[1])) {
214 rank = s[1] - '1';
215 } else {
216 return 0;
217 }
218 if (!parse_square(s+3, &to))
219 return 0;
220 } else if (s[3] == 'x') {
221 capture = 1;
222 if (!parse_square(s+1, &from))
223 return 0;
224 if (isupper(s[4])) {
225 if (!parse_square(s+5, &to))
226 return 0;
227 } else {
228 if (!parse_square(s+4, &to))
229 return 0;
230 }
231 } else {
232 /* its not a capture! */
233 if (parse_square(s+3, &to)) {
234 if (!parse_square(s+1, &from))
235 return 0;
236 } else if (parse_square(s+2, &to)) {
237 if (isfile(s[1])) {
238 file = s[1] - 'a';
239 } else if (isrank(s[1])) {
240 rank = s[1] - '1';
241 } else {
242 return 0;
243 }
244 } else if (!parse_square(s+1, &to)) {
245 return 0;
246 }
247 }
248 } else {
249 /* it must be a pawn capture */
250 piece = PAWN;
251 capture = 1;
252 if (s[1] != 'x' || !parse_square(s+2, &to))
253 return 0;
254 }
255
256 if (blacks_move(b)) piece = -piece;
257
258 /* now generate all the moves and see which one matches */
259 n = generate_moves(b, moves);
260
261 for (i=0;i<n;i++) {
262 if (b->board[moves[i].from] != piece) continue;
263 if (to != -1 && moves[i].to != to) continue;
264 if (from != -1 && moves[i].from != from) continue;
265 if (file != -1 && XPOS(moves[i].from) != file) continue;
266 if (rank != -1 && YPOS(moves[i].from) != rank) continue;
267 break;
268 }
269
270 if (i == n) return 0;
271
272 (*move) = moves[i];
273 return 1;
274 }
275
parse_move(char * s,Position * b,Move * move)276 int parse_move(char *s, Position *b, Move *move)
277 {
278 char x1, x2, y1, y2, becomes;
279 int ret;
280
281 b->promotion = 0;
282
283 /* maybe its castling */
284 if (strcasecmp(s, "o-o")==0) {
285 if (whites_move(b)) {
286 move->from = E1;
287 move->to = G1;
288 return 1;
289 } else {
290 move->from = E8;
291 move->to = G8;
292 return 1;
293 }
294 }
295 if (strcasecmp(s, "o-o-o")==0) {
296 if (whites_move(b)) {
297 move->from = E1;
298 move->to = C1;
299 return 1;
300 } else {
301 move->from = E8;
302 move->to = C8;
303 return 1;
304 }
305 }
306
307 if (s[2] == '-')
308 ret = sscanf(s,"%c%c-%c%c%c", &x1, &y1, &x2, &y2, &becomes);
309 else
310 ret = sscanf(s,"%c%c%c%c%c", &x1, &y1, &x2, &y2, &becomes);
311
312 if (ret < 4 ||
313 x1 < 'a' || x1 > 'h' ||
314 x2 < 'a' || x2 > 'h' ||
315 y1 < '1' || y1 > '8' ||
316 y2 < '1' || y2 > '8') {
317 return parse_algebraic(s, b, move);
318 }
319
320 move->from = POSN(x1-'a', y1-'1');
321 move->to = POSN(x2-'a', y2-'1');
322
323 if (ret == 5 && (y1 == '2' || y1 == '7') && (y2 == '1' || y2 == '8')) {
324 b->promotion = charpiece(becomes);
325 }
326
327 return 1;
328 }
329
330
Realloc(void * p,int size)331 void *Realloc(void *p, int size)
332 {
333 void *ret;
334
335 if (p) {
336 ret = (void *)realloc(p, size);
337 } else {
338 ret = (void *)malloc(size);
339 }
340
341 if (!ret) {
342 lprintf(0, "Realloc %d failed\n", size);
343 return NULL;
344 }
345
346 return ret;
347 }
348
349
ring_bell(void)350 void ring_bell(void)
351 {
352 putchar(7);
353 fflush(stdout);
354 }
355
356
357
358 /* this assumes a color_xterm */
print_board(Piece * board)359 void print_board(Piece *board)
360 {
361 extern int color_display;
362 char *yellow = "[35m";
363 char *blue = "[34m";
364 char *normal = "[m";
365 char piece[KING+1] = " pNBRQK";
366 Piece p;
367 int x,y;
368
369 printf("---------------------------------\n");
370
371 for (y=7;y>=0;y--) {
372 for (x=0;x<8;x++) {
373 p = board[POSN(x,y)];
374 if (color_display) {
375 printf("| %s%c%s ",
376 p > 0 ? yellow : blue,
377 piece[abs(p)],
378 normal);
379 } else {
380 if (p >= 0)
381 printf("| %c ", piece[abs(p)]);
382 else
383 printf("|*%c ", piece[abs(p)]);
384 }
385 }
386 if (y != 0) {
387 printf("|\n|---+---+---+---+---+---+---+---|\n");
388 }
389 }
390
391 printf("|\n---------------------------------\n");
392 }
393
print_bitboard(uint64 bitboard)394 void print_bitboard(uint64 bitboard)
395 {
396 int x,y;
397 uint64 mask;
398
399 printf("---------------------------------\n");
400
401 for (y=7;y>=0;y--) {
402 for (x=0;x<8;x++) {
403 mask = ((uint64)1<<POSN(x,y));
404 printf("| %c ", (bitboard & mask)?'*':' ');
405 }
406 if (y != 0)
407 printf("|\n|---+---+---+---+---+---+---+---|\n");
408 }
409
410 printf("|\n---------------------------------\n");
411 }
412
process_exists(int pid)413 int process_exists(int pid)
414 {
415 return (pid == getpid() || kill(pid,0) == 0 || errno != ESRCH);
416 }
417
418
419 /* an alternative to strtok. This one can be used recursively */
next_token(char ** ptr,char * buff,char * sep)420 int next_token(char **ptr,char *buff,char *sep)
421 {
422 static char *last_ptr;
423 char *s;
424 int quoted;
425
426 if (!ptr) ptr = &last_ptr;
427 if (!ptr) return 0;
428
429 s = *ptr;
430
431 /* default to simple separators */
432 if (!sep) sep = " \t\n\r";
433
434 /* find the first non sep char */
435 while(*s && strchr(sep,*s)) s++;
436
437 /* nothing left? */
438 if (! *s) return 0;
439
440 /* copy over the token */
441 for (quoted = 0; *s && (quoted || !strchr(sep,*s)); s++)
442 {
443 if (*s == '\"')
444 quoted = !quoted;
445 else
446 *buff++ = *s;
447 }
448
449 *ptr = (*s) ? s+1 : s;
450 *buff = 0;
451 last_ptr = *ptr;
452
453 return 1;
454 }
455
null_func(Position * b)456 void null_func(Position *b)
457 {
458
459 }
460
461
position_to_ppn(Position * b)462 char *position_to_ppn(Position *b)
463 {
464 int x, y, count;
465 char *p;
466 static char ppn[200];
467
468 p = ppn;
469
470 memset(ppn, 0, sizeof(ppn));
471
472 for (y=7;y>=0;y--) {
473 count = 0;
474
475 for (x=0;x<8;x++) {
476 if (b->board[POSN(x,y)] == 0) {
477 count++;
478 continue;
479 }
480 if (count) {
481 *p++ = '0' + count;
482 count = 0;
483 }
484 *p++ = piecechar(b->board[POSN(x,y)]);
485 }
486 if (count)
487 *p++ = '0' + count;
488 if (y > 0)
489 *p++ = '/';
490 }
491
492 *p++ = ' ';
493
494 if (whites_move(b))
495 *p++ = 'w';
496 else
497 *p++ = 'b';
498
499 *p++ = ' ';
500
501 if (!(b->flags & FLAG_CAN_CASTLE)) {
502 *p++ = '-';
503 } else {
504 if (b->flags & WHITE_CASTLE_SHORT)
505 *p++ = 'K';
506 if (b->flags & WHITE_CASTLE_LONG)
507 *p++ = 'Q';
508 if (b->flags & BLACK_CASTLE_SHORT)
509 *p++ = 'k';
510 if (b->flags & BLACK_CASTLE_LONG)
511 *p++ = 'q';
512 }
513
514 *p++ = ' ';
515
516 if (b->enpassent) {
517 strcat(p, posstr(b->enpassent));
518 } else {
519 *p++ = '-';
520 }
521
522 return ppn;
523 }
524
525
526
527 /* convert a ppn to a position, returning a pointer to the char after
528 the ppn ends (which often has "best move" etc in it) */
ppn_to_position(char * ppn,Position * b)529 char *ppn_to_position(char *ppn, Position *b)
530 {
531 int x, y;
532 char *p = ppn;
533
534 memset(b, 0, sizeof(*b));
535
536 for (y=7;y>=0;y--) {
537 for (x=0;x<8;) {
538 if (isdigit(*p)) {
539 x += (*p) - '0';
540 p++;
541 continue;
542 }
543
544 b->board[POSN(x,y)] = charpiece(*p);
545 if (islower(*p))
546 b->board[POSN(x,y)] = -b->board[POSN(x,y)];
547 p++;
548 x++;
549 }
550 p++;
551 }
552
553 b->move_num = 30; /* arbitrary */
554 if ((*p) == 'b')
555 b->move_num++;
556
557 p += 2;
558
559 b->flags = 0;
560 if ((*p) == '-') {
561 p++;
562 } else {
563 while ((*p) && (*p) != ' ') {
564 if ((*p) == 'k')
565 b->flags |= BLACK_CASTLE_SHORT;
566 if ((*p) == 'q')
567 b->flags |= BLACK_CASTLE_LONG;
568 if ((*p) == 'K')
569 b->flags |= WHITE_CASTLE_SHORT;
570 if ((*p) == 'Q')
571 b->flags |= WHITE_CASTLE_LONG;
572 p++;
573 }
574 }
575
576 p++;
577
578 if ((*p) == '-') {
579 p++;
580 b->enpassent = 0;
581 } else {
582 x = p[0] - 'a';
583 y = p[1] - '1';
584 b->enpassent = POSN(x,y);
585 p += 2;
586 }
587
588 p++;
589
590 create_pboard(b);
591
592 return p;
593 }
594
swapu16(uint16 x)595 uint16 swapu16(uint16 x)
596 {
597 char *s = (char *)&x;
598 char t;
599 t = s[0];
600 s[0] = s[1];
601 s[1] = t;
602 return x;
603 }
604
swap16(int16 x)605 int16 swap16(int16 x)
606 {
607 char *s = (char *)&x;
608 char t;
609 t = s[0];
610 s[0] = s[1];
611 s[1] = t;
612 return x;
613 }
614
swapu32(uint32 x)615 uint32 swapu32(uint32 x)
616 {
617 char *s = (char *)&x;
618 char t;
619 t = s[0];
620 s[0] = s[3];
621 s[3] = t;
622 t = s[1];
623 s[1] = s[2];
624 s[2] = t;
625 return x;
626 }
627
swap32(int x)628 int swap32(int x)
629 {
630 char *s = (char *)&x;
631 char t;
632 t = s[0];
633 s[0] = s[3];
634 s[3] = t;
635 t = s[1];
636 s[1] = s[2];
637 s[2] = t;
638 return x;
639 }
640
Write(int fd,char * buf,size_t count)641 int Write(int fd, char *buf, size_t count)
642 {
643 int r,total;
644
645 total = 0;
646
647 while (count) {
648 r = write(fd, buf, count);
649 if (r == -1) {
650 if (errno == EINTR) continue;
651 if (total) return total;
652 return -1;
653 }
654 total += r;
655 count -= r;
656 buf += r;
657 }
658
659 return total;
660 }
661
Read(int fd,char * buf,size_t count)662 int Read(int fd, char *buf, size_t count)
663 {
664 int r,total;
665
666 total = 0;
667
668 while (count) {
669 r = read(fd, buf, count);
670 if (r == -1) {
671 if (errno == EINTR) continue;
672 if (total) return total;
673 return -1;
674 }
675 total += r;
676 count -= r;
677 buf += r;
678 }
679
680 return total;
681 }
682
result()683 int result()
684 {
685
686 if (state->won == UNKNOWN || (state->auto_exit && state->won == STALEMATE)) {
687 /* haven't heard from ICS who won so determine it from
688 board and colour. Need to fix this */
689 if (state->position.winner == STALEMATE) {
690 state->won = STALEMATE;
691 } else if (state->position.winner ==
692 (state->ics_robot||state->auto_exit?state->colour:state->computer)) {
693 state->won = 1;
694 } else if (state->position.winner ==
695 (state->ics_robot||state->auto_exit?-state->colour:-state->computer)) {
696 state->won = 0;
697 } else {
698 state->won = TIME_FORFEIT;
699 }
700 }
701
702 return (state->won);
703 }
704
p_coeff_vboard(etype * p)705 void p_coeff_vboard(etype *p)
706 {
707 int x, y;
708
709 for (y=0; y<8; y++) {
710 for (x=0; x<8; x++) {
711 lprintf(0,"%9.3f", *(p + x + y*8));
712 }
713 printf("\n");
714 }
715 }
716
evalstr(etype v)717 char *evalstr(etype v)
718 {
719 static char ret[50];
720 if (v >= INFINITY-1) {
721 sprintf(ret, "Inf");
722 } else if (v <= -INFINITY+1) {
723 sprintf(ret, "-Inf");
724 } else if (v > FORCED_WIN) {
725 sprintf(ret,"Mate%02d", (int)((WIN-v)/2 + 1));
726 } else if (v < -FORCED_WIN) {
727 sprintf(ret,"-Mate%02d", (int)((v + WIN)/2 + 1));
728 } else {
729 sprintf(ret,"%3.2f", ((double)v)/STATIC_PAWN_VALUE);
730 }
731 return ret;
732 }
733
dump_ppn(Position * b)734 void dump_ppn(Position *b)
735 {
736 static int initialised;
737 static FILE *f;
738
739 if (!initialised) {
740 initialised = 1;
741 #if USE_APPLET
742 f = fopen("/export/pasiphae/position.txt", "w");
743 #else
744 f = fopen("position.txt", "w");
745 #endif
746 }
747
748 rewind(f);
749
750 fprintf(f, "%s * %d %s %d %d %s %d %d %s %d %d ", position_to_ppn(b),
751 state->mulling,
752 state->white_player, state->colour==1?state->krating:state->orating,
753 state->wtime,
754 state->black_player, state->colour==1?state->orating:state->krating,
755 state->btime,
756 state->game_type, state->game_time, state->increment);
757 fflush(f);
758 }
759
760
dump_history()761 void dump_history()
762 {
763 static int initialised;
764 static FILE *bullet, *blitz, *standard, *f;
765
766 if (!initialised) {
767 initialised = 1;
768 #if USE_APPLET
769 bullet = fopen("/export/pasiphae/bullet.txt", "a");
770 blitz = fopen("/export/pasiphae/blitz.txt", "a");
771 standard = fopen("/export/pasiphae/standard.txt", "a");
772 #else
773 bullet = fopen("bullet.txt", "a");
774 blitz = fopen("blitz.txt", "a");
775 standard = fopen("standard.txt", "a");
776 #endif
777 }
778
779 if (strstr(state->game_type,"bullet") || strstr(state->game_type,"lightning")) {
780 f = bullet;
781 } else if (strstr(state->game_type,"blitz")) {
782 f = blitz;
783 } else if (strstr(state->game_type, "standard")) {
784 f = standard;
785 } else {
786 return;
787 }
788
789 fprintf(f, "%d %d\n", state->total_rounds, state->krating);
790 fflush(f);
791 }
792