#include "includes.h" #include "knightcap.h" #define ADD_GEN(to) \ { \ b->topieces[to] |= mask; \ } #if USE_SLIDING_CONTROL #define XRAY_ADD_GEN(to) \ { \ b->xray_topieces[to] |= mask; \ } /* returns a mask of all the pieces that have an xray attack on sq2 through sq1 */ static inline uint32 xray_attack(Position *b, Square sq1, Square sq2) { uint32 mask; unsigned dir = sliding_map[sq1][sq2]; if (dir == 0) return 0; /* first look for all pieces that directly attack sq1 and xray attack sq2. to be sure in the case of queens, you need to check for xray attacks on 2 adjacent squares when sq1 and sq2 are not themselves adjacent */ if (sq2 - dir != sq1) { mask = (b->topieces[sq1] & b->xray_topieces[sq2] & b->xray_topieces[sq2-dir]); } else { mask = (b->topieces[sq1] & b->xray_topieces[sq2]); } /* the next bit is a hack for R---Q---R(sq1)--sq2 type combinations. The signature we use for this is sq2 being xrayed by a major piece through sq1 (which has already been detected in mask). Then we just include any other major piece of the same colour that xray attacks square 2. */ if (mask & MAJOR_MASK) { if (is_white(b->board[sq1])) { mask |= b->xray_topieces[sq2] & WMAJOR_MASK; } else { mask |= b->xray_topieces[sq2] & BMAJOR_MASK; } } return mask; } /* this tells us whether there is a piece at sq2 that would block a sliding xray coming from sq1. if either suqare doesn't have a piece we just answer "no" */ static inline int xray_through(Position *b, Square sq1, Square sq2) { Piece piece1 = b->board[sq1], piece2 = b->board[sq2]; if (!piece1 || !piece2) return 1; return ((b->sliding_mask & (1<pboard[sq2])) && same_color(piece1, piece2) && capture_map[KING+piece2][sq2][sq1]); } #else static void old_bishop_generate(Position *b, int pi) { uint32 mask = (1<pieces[pi]; Square from = p->pos; int x = XPOS(from); int y = YPOS(from); int l; Square to; l = imin(7-x, 7-y); to = from + NORTH_EAST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += NORTH_EAST; } l = imin(x, 7-y); to = from + NORTH_WEST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += NORTH_WEST; } l = imin(x, y); to = from + SOUTH_WEST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += SOUTH_WEST; } l = imin(7-x, y); to = from + SOUTH_EAST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += SOUTH_EAST; } } static void old_rook_generate(Position *b, int pi) { uint32 mask = (1<pieces[pi]; Square from = p->pos; int x = XPOS(from); int y = YPOS(from); int l; Square to; l = 7-y; to = from + NORTH; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += NORTH; } l = x; to = from + WEST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += WEST; } l = y; to = from + SOUTH; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += SOUTH; } l = 7-x; to = from + EAST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += EAST; } } #endif static void pawn_generate(Position *b, int pi) { uint32 mask = (1<pieces[pi]; Square from = p->pos; int x = XPOS(from); if (p->p > 0) { /* white pawns */ if (x != 0) { ADD_GEN(from + NORTH_WEST); } if (x != 7) { ADD_GEN(from + NORTH_EAST); } } else { /* black panws */ if (x != 0) { ADD_GEN(from + SOUTH_WEST); } if (x != 7) { ADD_GEN(from + SOUTH_EAST); } } } static void bishop_generate(Position *b, int pi) { #if !USE_SLIDING_CONTROL old_bishop_generate(b, pi); return; #else uint32 mask = (1<pieces[pi]; Square from = p->pos; int x = XPOS(from); int y = YPOS(from); int l; Square to; l = imin(7-x, 7-y); to = from + NORTH_EAST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += NORTH_EAST; } if (l>0) { while (l-- && xray_through(b,from,to)) { to += NORTH_EAST; XRAY_ADD_GEN(to); } } l = imin(x, 7-y); to = from + NORTH_WEST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += NORTH_WEST; } if (l>0) { while (l-- && xray_through(b,from,to)) { to += NORTH_WEST; XRAY_ADD_GEN(to); } } l = imin(x, y); to = from + SOUTH_WEST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += SOUTH_WEST; } if (l>0) { while (l-- && xray_through(b,from,to)) { to += SOUTH_WEST; XRAY_ADD_GEN(to); } } l = imin(7-x, y); to = from + SOUTH_EAST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += SOUTH_EAST; } if (l>0) { while (l-- && xray_through(b,from,to)) { to += SOUTH_EAST; XRAY_ADD_GEN(to); } } #endif } static void rook_generate(Position *b, int pi) { #if !USE_SLIDING_CONTROL old_rook_generate(b, pi); return; #else uint32 mask = (1<pieces[pi]; Square from = p->pos; int x = XPOS(from); int y = YPOS(from); int l; Square to; l = 7-y; to = from + NORTH; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += NORTH; } if (l>0) { while (l-- && xray_through(b, from, to)) { to += NORTH; XRAY_ADD_GEN(to); } } l = x; to = from + WEST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += WEST; } if (l>0) { while (l-- && xray_through(b, from, to)) { to += WEST; XRAY_ADD_GEN(to); } } l = y; to = from + SOUTH; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += SOUTH; } if (l>0) { while (l-- && xray_through(b, from, to)) { to += SOUTH; XRAY_ADD_GEN(to); } } l = 7-x; to = from + EAST; while (l--) { ADD_GEN(to); if (b->board[to]) break; to += EAST; } if (l>0) { while (l-- && xray_through(b, from, to)) { to += EAST; XRAY_ADD_GEN(to); } } #endif } static void knight_generate(Position *b, int pi) { uint32 mask = (1<pieces[pi]; Square from = p->pos; int x = XPOS(from); int y = YPOS(from); Square to; if (x == 7) goto west; if (y<6) { to = from + 2*NORTH + EAST; ADD_GEN(to); } if (y>1) { to = from + EAST + 2*SOUTH; ADD_GEN(to); } if (x == 6) goto west; if (y<7) { to = from + NORTH + 2*EAST; ADD_GEN(to); } if (y>0) { to = from + SOUTH + 2*EAST; ADD_GEN(to); } west: if (x == 0) return; if (y>1) { to = from + WEST + 2*SOUTH; ADD_GEN(to); } if (y<6) { to = from + WEST + 2*NORTH; ADD_GEN(to); } if (x == 1) return; if (y>0) { to = from + 2*WEST + SOUTH; ADD_GEN(to); } if (y<7) { to = from + 2*WEST + NORTH; ADD_GEN(to); } } static void king_generate(Position *b, int pi) { uint32 mask = (1<pieces[pi]; Square from = p->pos; int x = XPOS(from); int y = YPOS(from); Square to; if (x != 0) { to = from + WEST; ADD_GEN(to); } if (x != 7) { to = from + EAST; ADD_GEN(to); } if (y == 7) goto south; if (x != 0) { to = from + NORTH_WEST; ADD_GEN(to); } if (x != 7) { to = from + NORTH_EAST; ADD_GEN(to); } to = from + NORTH; ADD_GEN(to); south: if (y == 0) return; if (x != 0) { to = from + SOUTH_WEST; ADD_GEN(to); } if (x != 7) { to = from + SOUTH_EAST; ADD_GEN(to); } to = from + SOUTH; ADD_GEN(to); } static void queen_generate(Position *b, int pi) { rook_generate(b, pi); bishop_generate(b, pi); } static void piece_generate(Position *b, int pi) { b->piece_change |= (1<pieces[pi].p)) { case PAWN: pawn_generate(b, pi); break; case BISHOP: bishop_generate(b, pi); break; case KNIGHT: knight_generate(b, pi); break; case ROOK: rook_generate(b, pi); break; case QUEEN: queen_generate(b, pi); break; case KING: king_generate(b, pi); break; default: lprintf(0, "unknown pi %d p=%d pos=%s in piece_generate\n", pi, b->pieces[pi].p, posstr(b->pieces[pi].pos)); break; } } void old_update_moves(Position *b, Position *oldb, Move *move) { unsigned pi, dir; uint32 mask_from, mask_to, mask; Square pos, p2; /* wipe the piece that is moving */ mask = (1<pboard[move->from]); /* a piece being captured - always wipe */ if (oldb->pboard[move->to] != -1) { mask |= (1<pboard[move->to]); } mask = ~mask; for (pos=A1;pos<=H8;pos+=4) { b->topieces[pos] = oldb->topieces[pos] & mask; b->topieces[pos+1] = oldb->topieces[pos+1] & mask; b->topieces[pos+2] = oldb->topieces[pos+2] & mask; b->topieces[pos+3] = oldb->topieces[pos+3] & mask; } mask_from = b->topieces[move->from] & b->sliding_mask; mask_to = b->topieces[move->to] & b->sliding_mask; /* sliding pieces that can move to the from square */ mask = mask_from; while (mask) { pi = ff_one(mask); mask &= ~(1<pieces[pi].pos; if (same_line(move->from, move->to, pos)) { /* if we are moving towards this piece then it removes some topieces elements */ dir = sliding_map[move->from][move->to]; p2 = move->from; while (p2 != move->to) { b->topieces[p2] &= ~(1<from, move->to)) { /* if we are moving away from this piece then it adds some topieces elements */ dir = sliding_map[move->from][move->to]; p2 = move->from; while (p2 != move->to) { p2 += dir; b->topieces[p2] |= (1<from]; p2 = move->from; while (!off_board(p2, dir) && !b->board[p2]) { p2 += dir; b->topieces[p2] |= (1<pieces[pi].pos; dir = sliding_map[pos][move->to]; p2 = move->to; while (!off_board(p2, dir)) { p2 += dir; b->topieces[p2] &= ~(1<board[p2]) break; } } /* finally regenerate the piece that is moving */ piece_generate(b, b->pboard[move->to]); /* ugly. we need to recalc pawns because of changes in doubled, isolated or passed pawns */ { int minx=0, maxx=0, i; if (abs(oldb->board[move->from]) == PAWN) { minx = XPOS(move->from) - 1; maxx = XPOS(move->from) + 1; if (XPOS(move->to) != XPOS(move->from)) { minx = imin(minx, XPOS(move->to) - 1); maxx = imax(maxx, XPOS(move->to) + 1); } } else if (abs(oldb->board[move->to]) == PAWN) { minx = XPOS(move->to) - 1; maxx = XPOS(move->to) + 1; } if (maxx != 0) { for (i=8;i<16;i++) { if (b->pieces[i].p == PAWN && XPOS(b->pieces[i].pos) >= minx && XPOS(b->pieces[i].pos) <= maxx) b->piece_change |= (1<pieces[i].p == -PAWN && XPOS(b->pieces[i].pos) >= minx && XPOS(b->pieces[i].pos) <= maxx) b->piece_change |= (1<board[move->from]; /* wipe the piece that is moving */ mask = (1<pboard[move->from]); /* a piece being captured - always wipe */ if (oldb->pboard[move->to] != -1) { mask |= (1<pboard[move->to]); } mask = ~mask; for (pos=A1;pos<=H8;pos+=4) { b->topieces[pos] = oldb->topieces[pos] & mask; b->topieces[pos+1] = oldb->topieces[pos+1] & mask; b->topieces[pos+2] = oldb->topieces[pos+2] & mask; b->topieces[pos+3] = oldb->topieces[pos+3] & mask; b->xray_topieces[pos] = oldb->xray_topieces[pos] & mask; b->xray_topieces[pos+1] = oldb->xray_topieces[pos+1] & mask; b->xray_topieces[pos+2] = oldb->xray_topieces[pos+2] & mask; b->xray_topieces[pos+3] = oldb->xray_topieces[pos+3] & mask; } mask_from = b->topieces[move->from] & b->sliding_mask; mask_to = b->topieces[move->to] & b->sliding_mask; /* sliding pieces that can move to the from square */ mask = mask_from; while (mask) { pi = ff_one(mask); mask &= ~(1<pieces[pi].pos; piece2 = b->pieces[pi].p; sc = same_color(piece1,piece2); if (same_line(move->from, move->to, pos)) { /* if we are moving towards this piece then it removes some topieces elements */ dir = sliding_map[move->from][move->to]; p2 = move->from; xray_mask = ~xray_attack(oldb, pos, move->to); while (p2 != move->to) { b->topieces[p2] &= ~(1<xray_topieces[p2] |= (1<xray_topieces[p2] &= xray_mask; } p2 += dir; } } else if (same_line(pos, move->from, move->to)) { /* if we are moving away from this piece then it adds some topieces elements */ dir = sliding_map[move->from][move->to]; p2 = move->from; xray_mask = xray_attack(oldb, pos, move->from); while (p2 != move->to) { p2 += dir; b->topieces[p2] |= (1<xray_topieces[p2] &= ~(1<xray_topieces[p2] |= xray_mask; } /* If a piece has been captured it may open up some more xray_attacks on the other side of the to square */ if (oldb->pboard[move->to] != -1) { xray_mask |= (1<xray_topieces[p2] |= xray_mask; } } } else { /* we are moving off the line of this piece. we add some topieces elements. */ /* This is complicated for xray attacks. Here is the logic: 1) any xray attacks through piece2 and the from square get extended along that line. 2) any xray attacks originating at piece2 and propagating through a piece on the other side of the from square get included. 3) any xray attacks on the other side of the from square by piece2 are removed (up to the next piece). */ dir = sliding_map[pos][move->from]; p2 = move->from; xray_mask = xray_attack(oldb, pos, move->from); while (!off_board(p2, dir)) { p2 += dir; b->topieces[p2] |= (1<xray_topieces[p2] |= xray_mask; /* 1 */ b->xray_topieces[p2] &= ~(1<board[p2]) break; } /* if we stopped because of a piece, we might have to add xray attacks to the squares on the other side of that piece. */ xray_mask |= (1<xray_topieces[p2] |= xray_mask; /* 2 */ } } } /* sliding pieces that can move to the to square - their moves along that line might get truncated. */ /* This is complicated for xray attacks. Here is the logic: 1) if the pieces are different colours, or they are the same colour but piece1 does not attack piece2 or piece1 is not a sliding piece: 1a) any xray attacks through piece2 and the to square get truncated at the to square. 1b) any xray attacks originating at piece2 and propagating through a piece on the other side of the to square get truncated at that piece (i.e. removed altogether). 2) if not 1) then the pieces are the same colour and they mutually attack: 2a) piece2 and any xray attacks through piece2 now xray-attack the squares on the other side of the to square. */ mask = mask_to; while (mask) { pi = ff_one(mask); mask &= ~(1<pieces[pi].pos; piece2 = b->pieces[pi].p; sc = same_color(piece1,piece2); case2 = sc && capture_map[KING + piece1][move->to][pos] && (b->sliding_mask & (1<pboard[move->from])); dir = sliding_map[pos][move->to]; xray_mask = xray_attack(oldb, pos, move->to) | (1<to; while (!off_board(p2, dir)) { p2 += dir; b->topieces[p2] &= ~(1<xray_topieces[p2] |= xray_mask; /* 2a */ } else { b->xray_topieces[p2] &= ~xray_mask; /* 1a */ } if (b->board[p2]) break; } /* if we stopped becuase of a piece we need to check that xray attacks don't go through that piece */ while (!off_board(p2, dir) && xray_through(b, pos, p2)) { p2 += dir; if (case2) { b->xray_topieces[p2] |= xray_mask; /* 2a */ } else { b->xray_topieces[p2] &= ~xray_mask; /* 1b */ } } } /* finally regenerate the piece that is moving */ piece_generate(b, b->pboard[move->to]); /* ugly. we need to recalc pawns because of changes in doubled, isolated or passed pawns */ { int minx=0, maxx=0, i; if (abs(oldb->board[move->from]) == PAWN) { minx = XPOS(move->from) - 1; maxx = XPOS(move->from) + 1; if (XPOS(move->to) != XPOS(move->from)) { minx = imin(minx, XPOS(move->to) - 1); maxx = imax(maxx, XPOS(move->to) + 1); } } else if (abs(oldb->board[move->to]) == PAWN) { minx = XPOS(move->to) - 1; maxx = XPOS(move->to) + 1; } if (maxx != 0) { for (i=8;i<16;i++) { if (b->pieces[i].p == PAWN && XPOS(b->pieces[i].pos) >= minx && XPOS(b->pieces[i].pos) <= maxx) b->piece_change |= (1<pieces[i].p == -PAWN && XPOS(b->pieces[i].pos) >= minx && XPOS(b->pieces[i].pos) <= maxx) b->piece_change |= (1<topieces[i] != b1.topieces[i]) { lprintf(0,"%s %08x %08x\n", posstr(i), b->topieces[i], b1.topieces[i]); bad++; } #if USE_SLIDING_CONTROL if (b->xray_topieces[i] != b1.xray_topieces[i]) { lprintf(0,"%s %08x %08x %08x\n", posstr(i), b->xray_topieces[i], b1.xray_topieces[i], oldb->xray_topieces[i]); xray_bad++; } #endif } if (bad) { lprintf(0,"%s %d bad\n", short_movestr(oldb, move), bad); print_board(oldb->board); } #if USE_SLIDING_CONTROL if (xray_bad) { lprintf(0,"%s %d xray bad\n", short_movestr(oldb, move), xray_bad); print_board(oldb->board); } #endif } /* this is called when the topieces[] array needs to be completely redone */ void regen_moves(Position *b) { int pi; memset(b->topieces, 0, sizeof(b->topieces)); #if USE_SLIDING_CONTROL memset(b->xray_topieces, 0, sizeof(b->xray_topieces)); #endif b->oldb = NULL; for (pi=0;pi<32;pi++) { if (!b->pieces[pi].p) continue; piece_generate(b, pi); } b->flags &= ~FLAG_EVAL_DONE; b->flags &= ~FLAG_DONE_TACTICS; b->piece_change = b->material_mask; eval(b, INFINITY, MAX_DEPTH); } /* return the number of moves, and put all the moves in moves[]. This assumes that moves[] is big enough to hold all the moves */ int generate_moves(Position *b, Move *moves) { int n, i; PieceStruct *p; uint32 pieces; Square to; n = 0; if (whites_move(b)) { p = WHITEPIECES(b); for (to=A1;to<=H8;to++) { if (b->board[to]>0) continue; pieces = b->topieces[to] & WHITE_MASK; if (b->board[to]==0) pieces &= b->piece_mask; while (pieces) { i = ff_one(pieces); moves->from = p[i].pos; moves->to = to; moves++; n++; pieces &= ~(1<enpassent) && (b->topieces[to] & WPAWN_MASK)) { if (XPOS(to) != 0 && b->board[to+SOUTH_WEST] == PAWN) { moves->from = to+SOUTH_WEST; moves->to = to; moves++; n++; } if (XPOS(to) != 7 && b->board[to+SOUTH_EAST] == PAWN) { moves->from = to+SOUTH_EAST; moves->to = to; moves++; n++; } } if (b->flags & WHITE_CASTLE_SHORT) { if (b->board[F1] == 0 && b->board[G1] == 0 && !(b->topieces[E1] & BLACK_MASK) && !(b->topieces[F1] & BLACK_MASK) && !(b->topieces[G1] & BLACK_MASK)) { moves->from = E1; moves->to = G1; moves++; n++; } } if (b->flags & WHITE_CASTLE_LONG) { if (b->board[D1] == 0 && b->board[C1] == 0 && b->board[B1] == 0 && !(b->topieces[E1] & BLACK_MASK) && !(b->topieces[D1] & BLACK_MASK) && !(b->topieces[C1] & BLACK_MASK)) { moves->from = E1; moves->to = C1; moves++; n++; } } p = &WHITEPIECES(b)[8]; for (i=0;i<8;i++, p++) { if (p->p != PAWN) continue; if (b->board[p->pos+NORTH]) continue; moves->from = p->pos; moves->to = p->pos+NORTH; moves++; n++; if (YPOS(p->pos) != 1 || b->board[p->pos+2*NORTH]) continue; moves->from = p->pos; moves->to = p->pos+2*NORTH; moves++; n++; } } else { p = WHITEPIECES(b); for (to=A1;to<=H8;to++) { if (b->board[to]<0) continue; pieces = b->topieces[to] & BLACK_MASK; if (b->board[to]==0) pieces &= b->piece_mask; while (pieces) { i = ff_one(pieces); moves->from = p[i].pos; moves->to = to; moves++; n++; pieces &= ~(1<enpassent) && (b->topieces[to] & BPAWN_MASK)) { if (XPOS(to) != 0 && b->board[to+NORTH_WEST] == -PAWN) { moves->from = to+NORTH_WEST; moves->to = to; moves++; n++; } if (XPOS(to) != 7 && b->board[to+NORTH_EAST] == -PAWN) { moves->from = to+NORTH_EAST; moves->to = to; moves++; n++; } } if (b->flags & BLACK_CASTLE_SHORT) { if (b->board[F8] == 0 && b->board[G8] == 0 && !(b->topieces[E8] & WHITE_MASK) && !(b->topieces[F8] & WHITE_MASK) && !(b->topieces[G8] & WHITE_MASK)) { moves->from = E8; moves->to = G8; moves++; n++; } } if (b->flags & BLACK_CASTLE_LONG) { if (b->board[D8] == 0 && b->board[C8] == 0 && b->board[B8] == 0 && !(b->topieces[E8] & WHITE_MASK) && !(b->topieces[D8] & WHITE_MASK) && !(b->topieces[C8] & WHITE_MASK)) { moves->from = E8; moves->to = C8; moves++; n++; } } p = &BLACKPIECES(b)[8]; for (i=0;i<8;i++, p++) { if (p->p != -PAWN) continue; if (b->board[p->pos+SOUTH]) continue; moves->from = p->pos; moves->to = p->pos+SOUTH; moves++; n++; if (YPOS(p->pos) != 6 || b->board[p->pos+2*SOUTH]) continue; moves->from = p->pos; moves->to = p->pos+2*SOUTH; moves++; n++; } } return n; } int generate_check_avoidance(Position *b, Move *moves) { int n=0; int kpos, pos, pi, pi2, dx, dy, to, dir; int x1, x2, y1, y2, x, y; uint32 giving_check, pieces; if (whites_move(b)) { kpos = WHITEPIECES(b)[IKING].pos; giving_check = b->topieces[kpos] & BLACK_MASK; } else { kpos = BLACKPIECES(b)[IKING].pos; giving_check = b->topieces[kpos] & WHITE_MASK; } pos = kpos; /* which piece is giving check? */ pi = ff_one(giving_check); if (giving_check & ~(1<pieces[pi].pos; /* try to capture it */ pieces = b->topieces[pos]; /* a special case - if its a pawn and enpassent is possible then take enpassent */ if (b->enpassent && !(giving_check & b->piece_mask)) { pieces |= b->topieces[b->enpassent] & ~b->piece_mask; } if (whites_move(b)) { pieces &= WHITE_MASK; } else { pieces &= BLACK_MASK; } while (pieces) { pi2 = ff_one(pieces); moves->from = b->pieces[pi2].pos; if (abs(b->board[moves->from]) == PAWN && YPOS(pos) == YPOS(moves->from)) moves->to = b->enpassent; else moves->to = pos; moves++; n++; pieces &= ~(1<sliding_mask)) goto king_moves; dx = XPOS(kpos) - XPOS(pos); dy = YPOS(kpos) - YPOS(pos); dir = 0; if (dy > 0) dir += SOUTH; else if (dy < 0) dir += NORTH; if (dx > 0) dir += WEST; else if (dx < 0) dir += EAST; to = kpos + dir; while (to != pos) { if (whites_move(b)) { pieces = (b->topieces[to] & WHITE_MASK) & ~WKING_MASK; pieces &= b->piece_mask; if (b->board[to+SOUTH] == PAWN) { pieces |= (1<pboard[to+SOUTH]); } else if (YPOS(to) == 3 && b->board[to+SOUTH] == 0 && b->board[to+2*SOUTH] == PAWN) { pieces |= (1<pboard[to+2*SOUTH]); } } else { pieces = (b->topieces[to] & BLACK_MASK) & ~BKING_MASK; pieces &= b->piece_mask; if (b->board[to+NORTH] == -PAWN) { pieces |= (1<pboard[to+NORTH]); } else if (YPOS(to) == 4 && b->board[to+NORTH] == 0 && b->board[to+2*NORTH] == -PAWN) { pieces |= (1<pboard[to+2*NORTH]); } } while (pieces) { pi2 = ff_one(pieces); moves->from = b->pieces[pi2].pos; moves->to = to; moves++; n++; pieces &= ~(1<topieces[pos2]; if (whites_move(b)) { if (pieces & BLACK_MASK) continue; if (b->board[pos2] > 0) continue; } else { if (pieces & WHITE_MASK) continue; if (b->board[pos2] < 0) continue; } /* the king can't move to any square that is in the capture map of the pieces giving check */ pieces = giving_check & b->sliding_mask; while (pieces) { Square ppos; pi = ff_one(pieces); ppos = b->pieces[pi].pos; if (same_line(ppos, kpos, pos2)) break; pieces &= ~(1<from = kpos; moves->to = pos2; if (pieces) { #if 0 Position b1; if (do_move(&b1, b, moves)) { lprintf(0, "legal move %s\n", short_movestr(b, moves)); print_board(b->board); } #endif continue; } #if 0 { Position b1; if (!do_move(&b1, b, moves)) { lprintf(0, "illegal move %s\n", short_movestr(b, moves)); print_board(b->board); } } #endif moves++; n++; } return n; } /* this is used to make sure the player didn't make an illegal move - it is not speed critical */ int legal_move(Position *b, Move *move) { Move moves[MAX_MOVES]; int num_moves; int m; Position b1; num_moves = generate_moves(b, moves); for (m=0;mfrom && moves[m].to == move->to) break; if (m == num_moves) return 0; if (!do_move(&b1, b, move)) return 0; return 1; } static Move *get_move_list(int ply) { static int num_move_lists; static Move **move_lists; int j; if (num_move_lists > ply) { return move_lists[ply]; } move_lists = (Move **)Realloc(move_lists, (num_move_lists+30)*sizeof(Move *)); for (j=num_move_lists;jmoves) { lprintf(0,"already has a moves list\n"); } b->moves = get_move_list(ply); moves = b->moves; if (b->flags & FLAG_CHECK) { n = generate_check_avoidance(b, moves); } else { n = generate_moves(b, moves); } b->num_moves = n; order_moves(b, moves, n, ply, m1, testv); } int possible_move(Position *b, int ply, Move *m) { int n, i; Move *moves; moves = get_move_list(ply+1); n = generate_moves(b, moves); for (i=0;i