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 = "";
363 	char *blue = "";
364 	char *normal = "";
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