int test_scout() { Board b, orig; Move *moves, *omoves; int status, i, j, n, m; status = WIN; printf("testing scout\n"); setup(&b); setup(&orig); printb(&b); moves = gen_moves(&b, &n); for(i=0; i<n && i<5; i++) { printf("=============================================\napplying move %d\n", i+1); apply_move(&b, moves[i]); omoves = gen_moves(&b, &m); for(j=0; j<m && j<5; j++) { printf("second move %d\n", j+1); apply_move(&b, omoves[j]); printb(&b); printf("eval = %d\n", eval(&b)); undo_move(&b, omoves[j]); } free(omoves); undo_move(&b, moves[i]); } free(moves); return status; }
void perft_divide(int depth) { char str[10]; unsigned moves[256], count, i; double timespan; uint64_t total, perft; clock_t start, end; printf("Divide (depth %02i)\n", depth); printf("--------------------\n"); start = clock(); count = gen_moves(moves); total = 0, perft = 0; for(i = 0; i < count; i++) { if(board_add(moves[i])) { perft = perft_perft(depth-1); board_subtract(); total += perft; move_to_string(moves[i], str); printf("%-5s %10llu\n", str, (long long unsigned int)perft); } } end = clock(); timespan = (double)(end - start) / CLOCKS_PER_SEC; printf("\nTotal %10llu\n", (long long unsigned int)total); printf("Time %9.3fs\n", timespan); printf("Moves/s %12.1f\n", total/timespan); }
unsigned long long perft(Board *board, int depth) { if (is_illegal(board)) { return 0L; } if (depth == 0) { return 1L; } int index = board->hash & MASK; Entry *entry = &TABLE[index]; if (entry->key == board->hash && entry->depth == depth) { hits += entry->value; return entry->value; } unsigned long long result = 0; Undo undo; Move moves[MAX_MOVES]; int count = gen_moves(board, moves); for (int i = 0; i < count; i++) { do_move(board, &moves[i], &undo); result += perft(board, depth - 1); undo_move(board, &moves[i], &undo); } entry->key = board->hash; entry->value = result; entry->depth = depth; return result; }
static char* print_san_move_from(const struct position *pos, move m, char *str, enum player turn) { move moves[MOVE_ARRAY_LENGTH]; uint64_t ambig_pieces = UINT64_C(0); enum piece p = pos_piece_at(pos, mfrom(m)); (void) gen_moves(pos, moves); for (move *im = moves; *im != 0; ++im) { if ((mfrom(*im) != mfrom(m)) && (mto(*im) == mto(m)) && (pos_piece_at(pos, mfrom(*im)) == p)) ambig_pieces |= mfrom64(*im); } if ((p == pawn) && is_capture(m)) { *(str++) = index_to_file_ch(mfrom(m)); } else if (is_nonempty(ambig_pieces)) { if (is_nonempty(ambig_pieces & file64(mfrom(m)))) { if (is_nonempty(ambig_pieces & rank64(mfrom(m)))) { *(str++) = index_to_file_ch(mfrom(m)); } *(str++) = index_to_rank_ch(mfrom(m), turn); } else { *(str++) = index_to_file_ch(mfrom(m)); } } return str; }
/* Check the validity of the move */ BOOL check_validity(void) { char s[256]; int i; BOOL found; if (to != 999) { /* loop through the moves to see if it's legal */ found = FALSE; for (i = 0; i < first_move[1]; ++i) { if (gen_dat[i].m.b.from == from && gen_dat[i].m.b.to == to) { found = TRUE; /* get the promotion piece right */ if (gen_dat[i].m.b.bits & 32) { switch (s[4]) { case 'N': break; case 'B': i += 1; break; case 'R': i += 2; break; default: i += 3; break; } } break; } } if (!found || !makemove(gen_dat[i].m.b)) { printf("Illegal move.\n"); if (is_mini) { draw_message(" ","Nope"); } else { pz_draw_header("Illegal move !"); } return FALSE; } else { ply = 0; gen_moves(); print_board(); print_result(); to = 999; return TRUE; } } /* if to != 999 */ else { return FALSE; } }
static bool is_checkmate(struct node *node) { // TODO move this function to move_gen.c, or to position.c if (!is_in_check(node->pos)) return false; return gen_moves(node->pos, node->mo->moves) == 0; }
bool move_is_pseudo(int move, const board_t * board) { list_t list[1]; ASSERT(move_is_ok(move)); ASSERT(board_is_ok(board)); gen_moves(list,board); return list_contain(list,move); }
/* Returns a move if it exists. Otherwise results EMPTY */ unsigned find_move(char* move_string) { unsigned i, move_count, moves[256]; char str[6]; move_count = gen_moves(moves); for(i = 0; i < move_count; i++) { move_to_string(moves[i], str); if(strncmp(str, move_string, strlen(str)) == 0) return moves[i]; } return EMPTY; }
bool is_possibly_legal(const board& b, piece_colour pc, const move& m) { move movelist[200]; int n = 0; gen_moves(b, pc, movelist, n); for (int i = 0; i < n; i++) { if (same_squares(m, movelist[i])) return true; } return false; }
static bool move_is_pseudo_debug(int move, board_t * board) { list_t list[1]; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); gen_moves(list,board); return list_contain(list,move); }
/* Returns a move if it exists. Otherwise results EMPTY */ unsigned find_short_algebraic_move(char* move_string) { unsigned i, count, moves[256]; char str[10]; count = gen_moves(moves); for(i = 0; i < count; i++) { move_to_short_algebraic(moves[i], str); if(strncmp(str, move_string, strlen(str)) == 0) return moves[i]; } return EMPTY; }
bool board_can_play(const board_t * board) { list_t list[1]; int i, move; ASSERT(board_is_ok(board)); gen_moves(list,board); for (i = 0; i < list_size(list); i++) { move = list_move(list,i); if (pseudo_is_legal(move,board)) return true; } return false; // no legal move }
static char* print_san_check(const struct position *pos, move m, char *str) { struct position child; setup_registers(); make_move(&child, pos, m); if (is_in_check(&child)) { move moves[MOVE_ARRAY_LENGTH]; if (gen_moves(&child, moves) == 0) *str++ = '#'; else *str++ = '+'; } return str; }
/* Get a list of available book moves. The book can be a tree (AvlNode *book), or a file if <book> is NULL. Returns the combined score of all the moves if successfull. */ static int get_book_move_list(Board *board, MoveLst *move_list, const AvlNode *book) { int i, npos, tot_score; FILE *fp = NULL; ASSERT(1, board != NULL); ASSERT(1, move_list != NULL); npos = 0; tot_score = 0; if (book == NULL) { if ((fp = fopen(settings.book_file, "rb")) == NULL) { my_perror("Can't open file %s", settings.book_file); return -1; } npos = get_pos_count(fp); if (npos <= 0) { fprintf(stderr, "The opening book is empty\n"); return -1; } } gen_moves(board, move_list); for (i = 0; i < move_list->nmoves; i++) { U32 move = move_list->move[i]; int *score = &move_list->score[i]; make_move(board, move); if (get_nrepeats(board, 1) == 0) { U64 key = board->posp->key; if (book == NULL) *score = find_disk_pos(fp, key, npos); else *score = find_ram_pos(key, book); } else *score = VAL_NONE; if (*score != VAL_NONE) tot_score += *score; undo_move(board); } if (book == NULL) my_close(fp, settings.book_file); return tot_score; }
bool can_take_opponent_king(const board& b, piece_colour pc) { move movelist[200]; int n = 0; gen_moves(b, pc, movelist, n); for (int i = 0; i < n; i++) { const move& m = movelist[i]; piece_type pt = get_piece_type(m.to_sq); if (pt == KING) return true; } return false; }
static MateType get_mate_type(const Board *board) { MoveLst move_list; ASSERT(1, board != NULL); gen_moves(board, &move_list); if (move_list.nmoves > 0) return NO_MATE; if (board->posp->in_check) { if (board->color == BLACK) return WHITE_MATES; return BLACK_MATES; } return STALEMATE; }
/* Set up a new game */ void new_game() { end = 0; pz_close_window(end_wid); init(); gen_moves(); max_time = 100000;//1 << 25; max_depth = 1; init_historic(); print_board(); if (!is_mini) { draw_historic(); } else { draw_message("", ""); } }
static void test_tree_walk(const struct position *pos, unsigned depth) { move moves[MOVE_ARRAY_LENGTH]; if (!pos_has_ep_target(pos) && !is_in_check(pos)) check_eval_symmetry(pos); if (depth == 0) return; gen_moves(pos, moves); for (unsigned i = 0; moves[i] != 0; ++i) { struct position child[1]; make_move(child, pos, moves[i]); test_tree_walk(child, depth - 1); } }
void gen_legal_moves(list_t * list) { attack_t attack[1]; ASSERT(list!=NULL); attack_set(attack); if (ATTACK_IN_CHECK(attack)) { gen_evasions(list,attack); } else { gen_moves(list); list_filter(list,&pseudo_is_legal,true); } }
/* Let's make the iPod think about ;-) */ void computer_play(void) { if (!is_mini) { pz_draw_header("computer play"); } /* think about the move and make it */ //sleep(1); printf("think\n"); think(2); //sleep(1); if (!pv[0][0].u) { printf("No legal moves\n"); if (!is_mini) { pz_draw_header ("No legal moves"); } } sprintf(cpu_move,"%s", move_str(pv[0][0].b)); makemove(pv[0][0].b); ply = 0; gen_moves(); if (in_check(LIGHT)) { if (is_mini) { draw_message(" ", "Check"); } else { pz_draw_header("Check"); } } else { if (is_mini) { draw_message(" ", "Play"); } else { pz_draw_header("Your Turn"); } } }
static void pick_legal_moves(struct search *search, const struct position *position, enum player side, move moves[]) { move legal_moves[MOVE_ARRAY_LENGTH]; (void) gen_moves(position, legal_moves); for (unsigned ri = 0; ri < search->count; ++ri) { uint16_t m = search->entries[ri].move; for (unsigned i = 0; legal_moves[i] != 0; ++i) { if (pmove_match(m, legal_moves[i], side == white)) { *moves++ = legal_moves[i]; break; } } } *moves = 0; }
bool mate_test(board& b, piece_colour pc) { move movelist[200]; int n = 0; gen_moves(b, pc, movelist, n); piece_colour opp = flip(pc); for (int i = 0; i < n; i++) { const move& m = movelist[i]; b.do_move(m); bool tk = can_take_opponent_king(b, opp); b.undo_move(); if (!tk) return false; // we found a position where king can't be taken } // No move found where the opponent cannot take the king: this is // check mate! return true; }
void gen_legal_moves(list_t * list, board_t * board) { attack_t attack[1]; ASSERT(list!=NULL); ASSERT(board!=NULL); attack_set(attack,board); if (ATTACK_IN_CHECK(attack)) { gen_legal_evasions(list,board,attack); } else { gen_moves(list,board); list_filter(list,board,&pseudo_is_legal,true); } // debug ASSERT(list_is_ok(list)); }
static void perft(const board_t * board, int depth) { int me; list_t list[1]; int i, move; board_t new_board[1]; ASSERT(board_is_ok(board)); ASSERT(depth_is_ok(depth)); ASSERT(!is_in_check(board,colour_opp(board->turn))); // init NodeNb++; // leaf if (depth == 0) { LeafNb++; return; } // more init me = board->turn; // move loop gen_moves(list,board); for (i = 0; i < list_size(list); i++) { move = list_move(list,i); board_copy(new_board,board); move_do(new_board,move); if (!is_in_check(new_board,me)) perft(new_board,depth-1); } }
bool board_is_stalemate(board_t * board) { list_t list[1]; int i, move; ASSERT(board!=NULL); // init if (IS_IN_CHECK(board,board->turn)) return false; // in check => not stalemate // move loop gen_moves(list,board); for (i = 0; i < LIST_SIZE(list); i++) { move = LIST_MOVE(list,i); if (pseudo_is_legal(move,board)) return false; // legal move => not stalemate } return true; // in check and no legal move => mate }
int test_apply_move() { int status, num_moves, i; Board board; Move *moves; status = WIN; num_moves = 0; setup(&board); printb(&board); moves = gen_moves(&board, &num_moves); printf("found %d moves\n", num_moves); for(i=0; i<35 && i<num_moves; i++) { printf("move %d: %d is moving from %d to %d, capturing %d\n", i, moving_type(moves[i]), moves[i].from, moves[i].to, capturing_type(moves[i])); printf("board after move %d looks like:\n", i+1); apply_move(&board, moves[i]); printb(&board); undo_move(&board, moves[i]); } return status; }
uint64_t perft_perft(int depth) { unsigned moves[256], count, i; hash_node* node; uint64_t total; if(depth == 0) return 1; node = hash_find(table, zobrist); if(node != NULL && node->depth == depth) return node->sub_nodes; count = gen_moves(moves); total = 0; for(i = 0; i < count; i++) { if(board_add(moves[i])) { total += perft_perft(depth - 1); board_subtract(); } } hash_add_perft(table, zobrist, depth, total); return total; }
int test_moves() { Board b; Move *moves; int status, num_moves, expected; status = WIN; /* on startup, there shouldn't be any king moves */ setup(&b); moves = gen_moves(&b, &num_moves); expected = 20; if(num_moves != expected) { if(!QUIET) { if(to_play(&b) == WHITE) printf("\t>> WHITE to play, "); else printf("\t>> BLACK to play, "); printf("expected %d moves, but saw %d\n", expected, num_moves); printb(&b); } status = FAIL; } free(moves); /* try this config (black moves) */ initf(&b, "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2"); moves = gen_moves(&b, &num_moves); expected = 22; if(num_moves != expected) { if(!QUIET) { if(to_play(&b) == WHITE) printf("\t>> WHITE to play, "); else printf("\t>> BLACK to play, "); printf("expected %d moves, but saw %d\n", expected, num_moves); printb(&b); } status = FAIL; } free(moves); /* try this config (white moves) */ initf(&b, "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2"); set_play(&b, WHITE); moves = gen_moves(&b, &num_moves); expected = 13 + 7 + 1 + 1 + 5; /* pawns, knights, king, queen, bishop */ if(num_moves != expected) { if(!QUIET) { if(to_play(&b) == WHITE) printf("\t>> WHITE to play, "); else printf("\t>> BLACK to play, "); printf("expected %d moves, but saw %d\n", expected, num_moves); printb(&b); } status = FAIL; } free(moves); /* here is one with only rook moves */ initf(&b, "8/8/8/2r5/8/5R2/8/8 b KQkq - 1 2"); moves = gen_moves(&b, &num_moves); expected = 14; if(num_moves != expected) { if(!QUIET) { if(to_play(&b) == WHITE) printf("\t>> WHITE to play, "); else printf("\t>> BLACK to play, "); printf("expected %d moves, but saw %d\n", expected, num_moves); printb(&b); } status = FAIL; } free(moves); /* here is one with only rook moves */ initf(&b, "8/2p5/8/2r5/8/5R2/8/8 b KQkq - 1 2"); moves = gen_moves(&b, &num_moves); expected = 13; if(num_moves != expected) { if(!QUIET) { if(to_play(&b) == WHITE) printf("\t>> WHITE to play, "); else printf("\t>> BLACK to play, "); printf("expected %d moves, but saw %d\n", expected, num_moves); printb(&b); } status = FAIL; } free(moves); /* here is another one with only rook moves */ initf(&b, "8/2p5/8/2rp4/8/5R2/8/8 b KQkq - 1 2"); moves = gen_moves(&b, &num_moves); expected = 9; if(num_moves != expected) { if(!QUIET) { if(to_play(&b) == WHITE) printf("\t>> WHITE to play, "); else printf("\t>> BLACK to play, "); printf("expected %d moves, but saw %d\n", expected, num_moves); printb(&b); } status = FAIL; } free(moves); /* here is one last one with only rook moves */ initf(&b, "8/2p5/8/2rp4/8/2p2R2/8/8 b KQkq - 1 2"); moves = gen_moves(&b, &num_moves); expected = 7; if(num_moves != expected) { if(!QUIET) { if(to_play(&b) == WHITE) printf("\t>> WHITE to play, "); else printf("\t>> BLACK to play, "); printf("expected %d moves, but saw %d\n", expected, num_moves); printb(&b); } status = FAIL; } free(moves); /* and again for white... */ initf(&b, "8/2p5/8/2rp4/8/2p2R2/8/8 w KQkq - 1 2"); moves = gen_moves(&b, &num_moves); expected = 12; if(num_moves != expected) { if(!QUIET) { if(to_play(&b) == WHITE) printf("\t>> WHITE to play, "); else printf("\t>> BLACK to play, "); printf("expected %d moves, but saw %d\n", expected, num_moves); printb(&b); } status = FAIL; } free(moves); /* try to figure out bishop issue */ initf(&b, "8/3/8/2B5/8/8/8/8 w KQkq - 1 2"); moves = gen_moves(&b, &num_moves); expected = 11; if(num_moves != expected) { if(!QUIET) { if(to_play(&b) == WHITE) printf("\t>> WHITE to play, "); else printf("\t>> BLACK to play, "); printf("expected %d moves, but saw %d\n", expected, num_moves); printb(&b); } status = FAIL; } free(moves); return status; }
/* Converts a move to short algebraic notation. */ void move_to_short_algebraic(unsigned move, char* str) { unsigned from, to, promote, loc, count, moves[256], i, check; unsigned other_from, other_to, add_row, add_column; char to_square[3], from_square[3]; loc = 0; from = MOVE2FROM(move); to = MOVE2TO(move); promote = MOVE2PROMOTE(move); if(move & BITS_CASTLE) { if(to == 2 || to == 114) strcpy(str, "O-O-O"); else strcpy(str, "O-O"); return; } /* Assumed knowledge */ index_to_piece(to, to_square); index_to_piece(from, from_square); count = gen_moves(moves); add_row = 0; add_column = 0; /* Initial piece */ if(pieces[from] != PAWN && pieces[from] != EMPTY) str[loc++] = toupper(piece_value_to_name(pieces[from])); /* Source square is ambigious */ if(move & BITS_CAPTURE && pieces[from] == PAWN) { str[loc++] = from_square[0]; } else { for(i = 0; i < count; i++) { /* Skip identical move */ if(move == moves[i] || move & BITS_PROMOTE) continue; other_from = MOVE2FROM(moves[i]); other_to = MOVE2TO(moves[i]); /* Add file or rank information if other moves have the same destination and piece type. */ if(pieces[from] == pieces[other_from] && to == other_to) { if(INDEX2COLUMN(from) != INDEX2COLUMN(other_from)) add_column = 1; else if(INDEX2ROW(from) != INDEX2ROW(other_from)) add_row = 1; else { add_row = 1; add_column = 1; } } } } /* Add flags. This is so we can scale with 3 or more identical pieces attacking the same square */ if(add_column) str[loc++] = from_square[0]; if(add_row) str[loc++] = from_square[1]; /* Capture squares */ if(move & BITS_CAPTURE) str[loc++] = 'x'; /* Destination square */ str[loc++] = to_square[0]; str[loc++] = to_square[1]; /* Promotions */ if(move & BITS_PROMOTE) { str[loc++] = '='; str[loc++] = toupper(piece_value_to_name(promote)); } /* Board status (checkmate/stalemate) */ if(board_add(move)) { count = gen_moves(moves); /* 2nd ply moves */ check = is_in_check(turn); board_subtract(); if(count == 0 && check) str[loc++] = '#'; else if(count == 0) str[loc++] = '='; else if(check) str[loc++] = '+'; } str[loc++] = '\0'; }
/* ***********************************************************/ void open_tuxchess_window (void) { tuxchess_gc = pz_get_gc(1); /* Get the graphics context */ is_mini = (screen_info.cols == 138); if (is_mini) { /* Open the window for the board: */ tuxchess_wid = pz_new_window(0, 2, 104, screen_info.rows, tuxchess_do_draw, tuxchess_handle_event); /* Open the window for the message on the left : */ message_wid = pz_new_window(104, 0, screen_info.cols, screen_info.rows, tuxchess_do_draw, tuxchess_handle_event); GrSelectEvents(tuxchess_wid, GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP); GrSelectEvents(message_wid, GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP); } else { /* Open the window for the board: */ tuxchess_wid = pz_new_window(0, HEADER_TOPLINE + 1, 104, screen_info.rows - HEADER_TOPLINE - 1, tuxchess_do_draw, tuxchess_handle_event); /* Open the window for the historic : */ historic_wid = pz_new_window(104, HEADER_TOPLINE + 1, screen_info.cols, screen_info.rows - HEADER_TOPLINE - 1, tuxchess_do_draw, tuxchess_handle_event); GrSelectEvents(tuxchess_wid, GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP); GrSelectEvents(historic_wid, GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP); } /* Display the windows : */ if (is_mini) { GrMapWindow(message_wid); draw_message("A1-","Play"); } else { GrMapWindow(historic_wid); } GrMapWindow(tuxchess_wid); tuxchess_do_draw(); /* Clear the window */ GrClearWindow(tuxchess_wid, GR_FALSE); gen_moves(); max_time = 100000;//1 << 25; max_depth = 1; end = 0; print_board(); if (!is_mini) { draw_historic(); } /* make sure the right window has focus so we get input events */ // GrSetFocus(tuxchess_wid); }