diff options
| -rwxr-xr-x | .gitignore | 2 | ||||
| -rw-r--r-- | include/bitboard.h | 1 | ||||
| -rw-r--r-- | src/bitboard.c | 46 | ||||
| -rw-r--r-- | src/engine/moves.c | 75 | ||||
| -rw-r--r-- | src/engine/moves/knight.c | 6 | ||||
| -rw-r--r-- | src/engine/moves/pawn.c | 16 | ||||
| -rw-r--r-- | tests/generated.c | 8 |
7 files changed, 105 insertions, 49 deletions
@@ -3,3 +3,5 @@ build generated opt __pycache__ + +fuck* diff --git a/include/bitboard.h b/include/bitboard.h index ecd8c35..3e1118d 100644 --- a/include/bitboard.h +++ b/include/bitboard.h @@ -82,6 +82,7 @@ bool check_valid_position(position_t position); position.bitboards[BLACK_PAWN] +void print_position(position_t position); void print_bitboard(bitboard_t bitboard); #endif // BITBOARD_H diff --git a/src/bitboard.c b/src/bitboard.c index 9df3855..1c3ed28 100644 --- a/src/bitboard.c +++ b/src/bitboard.c @@ -47,6 +47,52 @@ bool check_valid_position(position_t position) { return true; } +char get_piece_char(size_t piece_type) { + assert(piece_type < PIECE_TYPE_COUNT); + if (WHITE_KING == piece_type) return 'K'; + if (WHITE_QUEEN == piece_type) return 'Q'; + if (WHITE_ROOK == piece_type) return 'R'; + if (WHITE_BISHOP == piece_type) return 'B'; + if (WHITE_KNIGHT == piece_type) return 'N'; + if (WHITE_PAWN == piece_type) return 'P'; + if (BLACK_KING == piece_type) return 'k'; + if (BLACK_QUEEN == piece_type) return 'q'; + if (BLACK_ROOK == piece_type) return 'r'; + if (BLACK_BISHOP == piece_type) return 'b'; + if (BLACK_KNIGHT == piece_type) return 'n'; + if (BLACK_PAWN == piece_type) return 'p'; +} + +char get_piece_char_from_sqr(position_t position, size_t square) { + assert(square < 64); + for (int i = 0; i < PIECE_TYPE_COUNT; i++) { + if ((position.bitboards[i] >> square) & (bitboard_t)1) { + return get_piece_char(i); + } + } + return ' '; +} + +void print_position(position_t position) { + for (int i = 8; i > 0; i--) { + printf("+---+---+---+---+---+---+---+---+\n"); + printf( + "| %c | %c | %c | %c | %c | %c | %c | %c | %d\n", + get_piece_char_from_sqr(position, 8 * i - 8), + get_piece_char_from_sqr(position, 8 * i - 7), + get_piece_char_from_sqr(position, 8 * i - 6), + get_piece_char_from_sqr(position, 8 * i - 5), + get_piece_char_from_sqr(position, 8 * i - 4), + get_piece_char_from_sqr(position, 8 * i - 3), + get_piece_char_from_sqr(position, 8 * i - 2), + get_piece_char_from_sqr(position, 8 * i - 1), + i + ); + } + printf("+---+---+---+---+---+---+---+---+\n"); + printf(" a b c d e f g h\n"); +} + void print_bitboard(bitboard_t bitboard) { printf("Bitboard(%" PRIu64 ")\n", bitboard); for (int i = 7; i >= 0; i--) { diff --git a/src/engine/moves.c b/src/engine/moves.c index 3aff11e..0c923a1 100644 --- a/src/engine/moves.c +++ b/src/engine/moves.c @@ -221,14 +221,17 @@ void perft_divide(position_t position, int depth) { moves_t moves; moves_init(&moves); get_legal_moves(&moves, position); + int nodes = 0; for (int i = 0; i < moves.length; i++) { position_t copy = position; position_make_move(©, moves.moves[i]); int c = count_positions(copy, depth - 1); + nodes += c; printf(" %c%d%c%d: %d\n", 'a' + (moves.moves[i].from % 8), 1 + (moves.moves[i].from / 8), 'a' + (moves.moves[i].to % 8), 1 + (moves.moves[i].to / 8), c); } + printf("\nNodes: %d\n", nodes); moves_deinit(moves); } @@ -238,19 +241,17 @@ bool test_perft_starting_position() { "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" ).position; int d; - d = count_positions(position, 0); printf("d0: %d\n", d); if (d != 1) return false; - d = count_positions(position, 1); printf("d1: %d\n", d); if (d != 20) return false; - d = count_positions(position, 2); printf("d2: %d\n", d); if (d != 400) return false; - d = count_positions(position, 3); printf("d3: %d\n", d); if (d != 8902) return false; - d = count_positions(position, 4); printf("d4: %d\n", d); if (d != 197281) return false; + d = count_positions(position, 0); if (d != 1) return false; + d = count_positions(position, 1); if (d != 20) return false; + d = count_positions(position, 2); if (d != 400) return false; + d = count_positions(position, 3); if (d != 8902) return false; + d = count_positions(position, 4); if (d != 197281) return false; position_t castle_pos = load_fen( "r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1" ).position; - int cp = count_positions(castle_pos, 1); - printf("R3K2R d1: %d (expected 26)\n", cp); - - d = count_positions(position, 5); printf("d5: %d\n", d); if (d != 4865609) return false; + d = count_positions(castle_pos, 1); if (d != 26) return false; + d = count_positions(position, 5); if (d != 4865609) return false; return true; } @@ -259,37 +260,33 @@ bool test_perft_kiwipete_position() { "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1" ).position; int d; - d = count_positions(position, 1); printf("d1: %d (expected 48)\n", d); if (d != 48) return false; - printf("--- Kiwipete d2 divide ---\n"); perft_divide(position, 2); - d = count_positions(position, 2); printf("d2: %d (expected 2039)\n", d); if (d != 2039) return false; + d = count_positions(position, 1); if (d != 48) return false; + d = count_positions(position, 2); if (d != 2039) return false; + d = count_positions(position, 3); if (d != 97862) return false; + d = count_positions(position, 4); if (d != 4085603) return false; - printf("\n--- Debug: investigate e5g6 ---\n"); - { - moves_t moves; - moves_init(&moves); - get_legal_moves(&moves, position); - for (int i = 0; i < moves.length; i++) { - if (moves.moves[i].from == 36 && moves.moves[i].to == 46) { - position_t copy = position; - position_make_move(©, moves.moves[i]); - printf("After Nxe5g6, turn=%d, is e8 attacked by white? %d\n", - copy.turn, square_attacked(copy, 60, WHITE_TURN)); - moves_t black_moves; - moves_init(&black_moves); - get_legal_moves(&black_moves, copy); - printf("Black has %d legal moves:\n", black_moves.length); - for (int j = 0; j < black_moves.length; j++) { - printf(" %c%d%c%d flags=%d\n", - 'a' + (black_moves.moves[j].from % 8), 1 + (black_moves.moves[j].from / 8), - 'a' + (black_moves.moves[j].to % 8), 1 + (black_moves.moves[j].to / 8), - black_moves.moves[j].flags); - } - moves_deinit(black_moves); - break; - } - } - moves_deinit(moves); - } + // my move gen too slow to verify this + // d = count_positions(position, 5); if (d != 193690690) return false; + + return true; +} + +bool test_perft_position3() { + position_t position = load_fen( + "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1" + ).position; + int d; + d = count_positions(position, 1); if (d != 14) return false; + d = count_positions(position, 2); if (d != 191) return false; + d = count_positions(position, 3); if (d != 2812) return false; + d = count_positions(position, 4); if (d != 43238) return false; + d = count_positions(position, 5); if (d != 674624) return false; + perft_divide(position, 6); + d = count_positions(position, 6); + printf("%d\n", d); + if (d != 11030083) return false; + d = count_positions(position, 7); if (d != 178633661) return false; + d = count_positions(position, 8); if (d != 3009794393) return false; return true; } diff --git a/src/engine/moves/knight.c b/src/engine/moves/knight.c index 64e44ed..4aca3ac 100644 --- a/src/engine/moves/knight.c +++ b/src/engine/moves/knight.c @@ -68,9 +68,9 @@ bitboard_t knight_moves[64] = { 1128098930098176ULL, 2257297371824128ULL, 4796069720358912ULL, - 4796069720358912ULL >> 1, - 4796069720358912ULL >> 2, - 4796069720358912ULL >> 3, + 4796069720358912ULL << 1, + 4796069720358912ULL << 2, + 4796069720358912ULL << 3, 4679521487814656ULL, 9077567998918656ULL, }; diff --git a/src/engine/moves/pawn.c b/src/engine/moves/pawn.c index 66b1d06..bc97fb7 100644 --- a/src/engine/moves/pawn.c +++ b/src/engine/moves/pawn.c @@ -34,6 +34,12 @@ bitboard_t get_black_pawn_forwardmoves(moves_t* moves, position_t position) { return x; } +bool pawn_in_range(int to, int next_from, int ub_escape, int turn) { + if (next_from == ub_escape) return false; + if (turn == WHITE_TURN) return to > next_from && to - next_from <= 16; + return to < next_from && next_from - to <= 16; +} + void get_pawn_moves(moves_t* moves, position_t position) { assert_valid_position(position); @@ -65,20 +71,23 @@ void get_pawn_moves(moves_t* moves, position_t position) { bitboard_t item = file_masks[i] & forward_moves; bitboard_t pawns = file_masks[i] & friendly_pawns; + int UB_ESCAPE = position.turn == WHITE_TURN ? 64 : -1; + int from = __builtin_ctzll(pawns); pawns &= (pawns - 1); int next_from = __builtin_ctzll(pawns); - if (pawns == 0) next_from = 64; // to work around UB + if (pawns == 0) next_from = UB_ESCAPE; while (item) { int to = __builtin_ctzll(item); - if (to > next_from) { + if (pawn_in_range(to, next_from, UB_ESCAPE, position.turn)) { from = next_from; pawns &= (pawns - 1); next_from = __builtin_ctzll(pawns); - if (pawns == 0) next_from = 64; + if (pawns == 0) next_from = UB_ESCAPE; } item &= (item - 1); + if (to >= 56 || to <= 7) { add_promote_moves(0); } else add_move(moves, from, to); @@ -128,7 +137,6 @@ void get_pawn_moves(moves_t* moves, position_t position) { } } - bitboard_t ATTACK_MASK; int shift; if (position.turn == WHITE_TURN) { diff --git a/tests/generated.c b/tests/generated.c index 43145e0..f2ee156 100644 --- a/tests/generated.c +++ b/tests/generated.c @@ -3,13 +3,14 @@ #include "../src/engine/moves/king.c" #include "../src/uci/command.c" -int total_test_count = 9; -bool (*tests[9])(void) = { +int total_test_count = 10; +bool (*tests[10])(void) = { test_fen_no_passant, test_fen_passant, test_starting_position, test_perft_starting_position, test_perft_kiwipete_position, + test_perft_position3, test_white_king_corners, test_black_king_corners, test_uci_cmd_t, @@ -17,12 +18,13 @@ bool (*tests[9])(void) = { }; int max_test_name_size = 23; -char test_names[9][100] = { +char test_names[10][100] = { "fen_no_passant", "fen_passant", "starting_position", "perft_starting_position", "perft_kiwipete_position", + "perft_position3", "white_king_corners", "black_king_corners", "uci_cmd_t", |
