void unmake_move(Move move) { turn_to_move = not_turn_to_move; ply -= 1; int direction_of_pawns = turn_to_move == WHITE? -10: 10; int from = move_from(move); int to = move_to(move); int figure = board[move_to(move)]; int broken = move_broken(move); int turn = move_turn(move); if(turn) board[from] = create_figure(turn_to_move, PAWN); else board[from] = figure; if(get_value(figure) == PAWN && to == ply->en_passant) { board[to] = EMPTY; board[to - direction_of_pawns] = create_figure(not_turn_to_move, PAWN); } else board[to] = broken; if(get_value(figure) == KING) { int horizontal; if(turn_to_move == WHITE) { place_of_white_king = from; horizontal = 90; } else { place_of_black_king = from; horizontal = 20; } if(from - to == 2) { board[horizontal + 1] = board[horizontal + 4]; board[horizontal + 4] = EMPTY; } else if(to - from == 2) { board[horizontal + 8] = board[horizontal + 6]; board[horizontal + 6] = EMPTY; } } }
Move str_to_move(char *string) { for(int i = 0; i < 4; i += 1) if(string[i] == '\0') return 0; if(!((string[0] >= 'a' && string[0] <= 'h') && (string[1] >= '1' && string[1] <= '8') && (string[2] >= 'a' && string[2] <= 'h') && (string[3] >= '1' && string[3] <= '8'))) return 0; int from = ('8' - string[1] + 2) * 10 + (string[0] - 'a' + 1); int to = ('8' - string[3] + 2) * 10 + (string[2] - 'a' + 1); int broken = board[to]; int turn = 0; switch(string[4]) { case 'q': turn = create_figure(turn_to_move, QUEEN); break; case 'r': turn = create_figure(turn_to_move, ROOK); break; case 'b': turn = create_figure(turn_to_move, BISHOP); break; case 'n': turn = create_figure(turn_to_move, KNIGHT); break; } return create_move(from, to, broken, turn); }
int in_check(int turn_to_move) { int direction_of_pawns = turn_to_move == WHITE? -10: 10; int captures_of_pawns[2] = {direction_of_pawns + 1, direction_of_pawns - 1}; int place_of_king = turn_to_move == WHITE? place_of_white_king: place_of_black_king; for(int i = 0; i < 2; i += 1) { int tmp = place_of_king + captures_of_pawns[i]; if(board[tmp] == create_figure(not_turn_to_move, PAWN)) return 1; } for(int i = 0; i < 8; i += 1) { int tmp = place_of_king + moves_of_king[i]; if(board[tmp] == create_figure(not_turn_to_move, KING)) return 1; } for(int i = 0; i < 8; i += 1) { int tmp = place_of_king + moves_of_knight[i]; if(board[tmp] == create_figure(not_turn_to_move, KNIGHT)) return 1; } for(int i = 0; i < 4; i += 1) { int inc = directions_of_bishop[i]; int x = place_of_king + inc; while(board[x] == EMPTY) x += inc; if(board[x] == create_figure(not_turn_to_move, QUEEN) || board[x] == create_figure(not_turn_to_move, BISHOP)) return 1; } for(int i = 0; i < 4; i += 1) { int inc = directions_of_rook[i]; int x = place_of_king + inc; while(board[x] == EMPTY) x += inc; if(board[x] == create_figure(not_turn_to_move, QUEEN) || board[x] == create_figure(not_turn_to_move, ROOK)) return 1; } return 0; }
void main() { char c; int gata = 0; double xx1[DIM], xx2[DIM], yy1[DIM], yy2[DIM]; initialize_graphic_mode(); initialize_variable_spaces(); create_figure(); draw_figure(); draw_axes(); draw_line(); do { c = getch(); for (int i = 0; i < DIM; i++) { xx1[i] = x1[i]; xx2[i] = x2[i]; yy1[i] = y1[i]; yy2[i] = y2[i]; } switch (c) { case 9: idx++; if (idx == 9) idx = 1; variable_space(1); break; case '+': modify_variable(1); break; case '-': modify_variable(0); break; case 't': draw_figure(); translate(transX, transY); draw_figure(); break; case 's': draw_figure(); scale(scaleX, scaleY); draw_figure(); break; case 'c': draw_figure(); center_rotate(rotA); draw_figure(); break; case 'r': draw_figure(); origin_rotate(rotA); draw_figure(); break; case 'x': draw_figure(); Ox_simetry(); draw_figure(); break; case 'y': draw_figure(); Oy_simetry(); draw_figure(); break; case 'o': draw_figure(); origin_simetry(); draw_figure(); break; case 'd': draw_figure(); random_line_simetry(simX, simY, simA); draw_figure(); break; case 27: gata = 1; break; case 0: c = getch(); switch (c) { case 15: idx--; if (idx == 0) idx = 8; variable_space(0); break; case 80: draw_axes(); if (y < 427) y++; draw_axes(); break; case 72: draw_axes(); if (y > 0) y--; draw_axes(); break; case 77: draw_axes(); if (x < 638) x++; draw_axes(); break; case 75: draw_axes(); if (x > 0) x--; draw_axes(); break; } } if (not_on_the_screen()) { draw_figure(); for (int i = 0; i < DIM; i++) { x1[i] = xx1[i]; x2[i] = xx2[i]; y1[i] = yy1[i]; y2[i] = yy2[i]; } draw_figure(); } } while (!gata); closegraph(); }
int generate_moves(Move *movelist) { int horizontal2 = turn_to_move == WHITE? 8 : 3; int horizontal7 = turn_to_move == WHITE? 3 : 8; int direction_of_pawns = turn_to_move == WHITE? -10: 10; int captures_of_pawns[2] = {direction_of_pawns + 1, direction_of_pawns - 1}; int place_of_king = turn_to_move == WHITE? place_of_white_king: place_of_black_king; int n = 0; int king_castling, queen_castling; if(turn_to_move == WHITE) { king_castling = ply->castlings & K_castling; queen_castling = ply->castlings & Q_castling; } else { king_castling = ply->castlings & k_castling; queen_castling = ply->castlings & q_castling; } int is_in_check = in_check(turn_to_move); for(int i = 0; i < 8; i += 1) { int i_move = moves_of_king[i]; int tmp = place_of_king + i_move; if(board[tmp] == EMPTY || get_color(board[tmp]) == not_turn_to_move) { int i_move_is_possible = 0; Move tmp_move = create_move(place_of_king, tmp, board[tmp], 0); make_move(tmp_move); if(!in_check(not_turn_to_move)) { i_move_is_possible = 1; movelist[n] = tmp_move; n += 1; } unmake_move(tmp_move); if(is_in_check || !i_move_is_possible || board[tmp] != EMPTY) continue; if(i_move == 1 && king_castling && board[place_of_king + 2] == EMPTY) { movelist[n] = create_move(place_of_king, place_of_king + 2, 0, 0); n += 1; } if(i_move == -1 && queen_castling && board[place_of_king - 2] == EMPTY && board[place_of_king - 3] == EMPTY) { movelist[n] = create_move(place_of_king, place_of_king - 2, 0, 0); n += 1; } } } if(ply->en_passant) { for(int i = 0; i < 2; i += 1) { int tmp = ply->en_passant - captures_of_pawns[i]; if(board[tmp] == create_figure(turn_to_move, PAWN)) { movelist[n] = create_move(tmp, ply->en_passant, 0, 0); n += 1; } } } for(int i64 = 0; i64 < 64; i64 += 1) { int current_cell = board64[i64]; int figure = board[current_cell]; if(get_color(figure) != turn_to_move) continue; switch(get_value(figure)) { case QUEEN: for(int i = 0; i < 8; i += 1) { int inc = directions_of_queen[i]; int x = current_cell + inc; while(board[x] == EMPTY) { movelist[n] = create_move(current_cell, x, 0, 0); n += 1; x += inc; } if(get_color(board[x]) == not_turn_to_move ) { movelist[n] = create_move(current_cell, x, board[x], 0); n += 1; } } break; case ROOK: for(int i = 0; i < 4; i += 1) { int inc = directions_of_rook[i]; int x = current_cell + inc; while(board[x] == EMPTY) { movelist[n] = create_move(current_cell, x, 0, 0); n += 1; x += inc; } if(get_color(board[x]) == not_turn_to_move) { movelist[n] = create_move(current_cell, x, board[x], 0); n += 1; } } break; case BISHOP: for(int i = 0; i < 4; i += 1) { int inc = directions_of_bishop[i]; int x = current_cell + inc; while(board[x] == EMPTY) { movelist[n] = create_move(current_cell, x, 0, 0); n += 1; x += inc; } if(get_color(board[x]) == not_turn_to_move) { movelist[n] = create_move(current_cell, x, board[x], 0); n += 1; } } break; case KNIGHT: for(int i = 0; i < 8; i += 1) { int tmp = current_cell + moves_of_knight[i]; if(board[tmp] == EMPTY || get_color(board[tmp]) == not_turn_to_move) { movelist[n] = create_move(current_cell, tmp, board[tmp], 0); n += 1; } } break; case PAWN: ;int tmp = current_cell + direction_of_pawns; if(board[tmp] == EMPTY) { if(current_cell/10 == horizontal7) { for(int j = 0; j < 4; j += 1) { movelist[n] = create_move(current_cell, tmp, 0, create_figure(turn_to_move, turn_figures[j])); n += 1; } } else { movelist[n] = create_move(current_cell, tmp, 0, 0); n += 1; } tmp += direction_of_pawns; if(board[tmp] == EMPTY && current_cell/10 == horizontal2) { movelist[n] = create_move(current_cell, tmp, 0, 0); n += 1; } } for(int i = 0; i < 2; i += 1) { int tmp = current_cell + captures_of_pawns[i]; if(get_color(board[tmp]) == not_turn_to_move) { if(current_cell/10 == horizontal7) { for(int j = 0; j < 4; j += 1) { movelist[n] = create_move(current_cell, tmp, board[tmp], create_figure(turn_to_move, turn_figures[j])); n += 1; } } else { movelist[n] = create_move(current_cell, tmp, board[tmp], 0); n += 1; } } } } } for(int i = 0; i < n; i += 1) { Move i_move = movelist[i]; make_move(i_move); if(in_check(not_turn_to_move)) { movelist[i] = movelist[n - 1]; n -= 1; i -= 1; } unmake_move(i_move); } return n; }
void make_move(Move move) { U64 hash = ply->hash; int direction_of_pawns = turn_to_move == WHITE? -10: 10; int from = move_from(move); int figure = board[from]; int to = move_to(move); int turn = move_turn(move); int broken = move_broken(move); board[from] = EMPTY; hash ^= zobrist_piecesquare[figure][from]; if(turn) { board[to] = turn; hash ^= zobrist_piecesquare[turn][to]; } else { board[to] = figure; hash ^= zobrist_piecesquare[figure][to]; } if(get_value(figure) == PAWN && to == ply->en_passant) { int tmp = to - direction_of_pawns; board[tmp] = EMPTY; hash ^= zobrist_piecesquare[create_figure(not_turn_to_move, PAWN)][tmp]; } else if(broken) { hash ^= zobrist_piecesquare[broken][to]; } if(ply->en_passant) { hash ^= zobrist_en_passant[ply->en_passant]; } ply += 1; if(get_value(figure) == PAWN && to - from == direction_of_pawns * 2) { ply->en_passant = from + direction_of_pawns; hash ^= zobrist_en_passant[ply->en_passant]; } else { ply->en_passant = 0; } ply->castlings = (ply - 1)->castlings; if(get_value(figure) == KING) { int horizontal; if(turn_to_move == WHITE) { place_of_white_king = to; make_white_castlings_is_incorrect(); horizontal = 90; } else { place_of_black_king = to; make_black_castlings_is_incorrect(); horizontal = 20; } if(from - to == 2) { board[horizontal + 4] = board[horizontal + 1]; board[horizontal + 1] = EMPTY; } else if(to - from == 2) { board[horizontal + 6] = board[horizontal + 8]; board[horizontal + 8] = EMPTY; } } if(board[98] != create_figure(WHITE, ROOK)) make_K_castling_is_incorrect(); if(board[91] != create_figure(WHITE, ROOK)) make_Q_castling_is_incorrect(); if(board[28] != create_figure(BLACK, ROOK)) make_k_castling_is_incorrect(); if(board[21] != create_figure(BLACK, ROOK)) make_q_castling_is_incorrect(); if(broken || get_value(figure) == PAWN) ply->number_of_insignificant_plies = 0; else ply->number_of_insignificant_plies = (ply - 1)->number_of_insignificant_plies + 1; turn_to_move = not_turn_to_move; hash ^= zobrist_color; hash ^= zobrist_castlings[(ply - 1)->castlings]; hash ^= zobrist_castlings[ply->castlings]; ply->hash = hash; }
void setup_position(char* fen) { ply = begin_ply; turn_to_move = WHITE; ply->en_passant = 0; ply->castlings = 0; ply->number_of_insignificant_plies = 0; for(int i = 0; i < 120; i += 1) board[i] = BORDER; for(int i = 0; i < 64; i += 1) board[board64[i]] = EMPTY; int i = 0; int current_cell = 0; for(; fen[i] != ' ' && fen[i] != '\0'; i += 1, current_cell += 1) { int index_of_figure = board64[current_cell]; switch(fen[i]) { case '/': current_cell -= 1; break; case 'K': place_of_white_king = index_of_figure; board[index_of_figure] = create_figure(WHITE, KING); break; case 'Q': board[index_of_figure] = create_figure(WHITE, QUEEN); break; case 'R': board[index_of_figure] = create_figure(WHITE, ROOK); break; case 'B': board[index_of_figure] = create_figure(WHITE, BISHOP); break; case 'N': board[index_of_figure] = create_figure(WHITE, KNIGHT); break; case 'P': board[index_of_figure] = create_figure(WHITE, PAWN); break; case 'k': place_of_black_king = index_of_figure; board[index_of_figure] = create_figure(BLACK, KING); break; case 'q': board[index_of_figure] = create_figure(BLACK, QUEEN); break; case 'r': board[index_of_figure] = create_figure(BLACK, ROOK); break; case 'b': board[index_of_figure] = create_figure(BLACK, BISHOP); break; case 'n': board[index_of_figure] = create_figure(BLACK, KNIGHT); break; case 'p': board[index_of_figure] = create_figure(BLACK, PAWN); break; default: current_cell += fen[i] - '0' - 1; } } if(fen[i] == '\0') { setup_hash(); return; } i += 1; if(fen[i] == 'w') turn_to_move = WHITE; else if(fen[i] == 'b') turn_to_move = BLACK; i += 1; if(fen[i] == '\0') { setup_hash(); return; } i += 1; for(; fen[i] != ' ' && fen[i] != '\0'; i += 1) { switch(fen[i]) { case 'K': ply->castlings |= K_castling; break; case 'Q': ply->castlings |= Q_castling; break; case 'k': ply->castlings |= k_castling; break; case 'q': ply->castlings |= q_castling; break; } } if(fen[i] == '\0') { setup_hash(); return; } i += 1; if(fen[i] == '-') i += 1; else { ply->en_passant = ('8' - fen[i + 1] + 2) * 10 + fen[i] - 'a' + 1; i += 2; } if(fen[i] == '\0') { setup_hash(); return; } i += 1; if(fen[i + 1] == ' ' || fen[i + 1] == '\0') ply->number_of_insignificant_plies = fen[i] - '0'; else ply->number_of_insignificant_plies = ((fen[i] - '0') * 10 + fen[i + 1] - '0'); setup_hash(); }
void print_position(int is_reversed) { for(int i = 0; i < 8; i += 1) { for(int j = 0; j < 8; j += 1) { int index = is_reversed ? (7 - i) * 8 + 7 - j: i * 8 + j; switch(board[board64[index]]) { case EMPTY: printf("."); break; case create_figure(WHITE, KING) : printf("K"); break; case create_figure(WHITE, QUEEN) : printf("Q"); break; case create_figure(WHITE, ROOK) : printf("R"); break; case create_figure(WHITE, BISHOP): printf("B"); break; case create_figure(WHITE, KNIGHT): printf("N"); break; case create_figure(WHITE, PAWN) : printf("P"); break; case create_figure(BLACK, KING) : printf("k"); break; case create_figure(BLACK, QUEEN) : printf("q"); break; case create_figure(BLACK, ROOK) : printf("r"); break; case create_figure(BLACK, BISHOP): printf("b"); break; case create_figure(BLACK, KNIGHT): printf("n"); break; case create_figure(BLACK, PAWN) : printf("p"); } } printf("\n"); } printf("\n"); }
int evaluate(int alpha, int beta) { Entry *entry = hash_get_entry(); if(entry != NULL) { int eval = entry->eval, flag = entry->flag; if(flag != LESS_THAN_ALPHA && eval >= beta) return beta; if(flag != MORE_THAN_BETA && eval <= alpha) return alpha; if(flag == BETWEEN_ALPHA_AND_BETA) return eval; } int white_pawns_in_verticals[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int black_pawns_in_verticals[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int evaluation = 0; int current_figure_material = 0; int white_king_tropism = 0; int black_king_tropism = 0; for(int i = 0; i < 64; i += 1) { int current_cell = board64[i]; int figure = board[current_cell]; int color = get_color(figure); int value = get_value(figure); if(figure == EMPTY || value == KING) continue; int material_value = get_material_value(color, value); if(value != PAWN) current_figure_material += abs(material_value); evaluation += material_value; evaluation += get_PST_value(figure, i); if(color == BLACK) { white_king_tropism += get_distance_bonus(current_cell, figure, place_of_white_king); } else { black_king_tropism += get_distance_bonus(current_cell, figure, place_of_black_king); } if(value == PAWN) { int vertical = current_cell % 10; if(color == WHITE) white_pawns_in_verticals[vertical] += 1; else black_pawns_in_verticals[vertical] += 1; } } int white_pawn_shield = 0; if (place_of_white_king == H1 || place_of_white_king == H2 || place_of_white_king == G1 || place_of_white_king == G2 || place_of_white_king == F1) { if(board[H2] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_2; else if(board[H3] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_3; if(board[G2] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_2; else if(board[G3] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_3; if(board[F2] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_2 / 2; if(board[H1] == create_figure(WHITE, ROOK) || board[H2] == create_figure(WHITE, ROOK) || board[G1] == create_figure(WHITE, ROOK)) { evaluation += UNDEVELOPED_ROOK_PENALTY; } } else if(place_of_white_king == A1 || place_of_white_king == A2 || place_of_white_king == B1 || place_of_white_king == B2 || place_of_white_king == C1) { if(board[A2] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_2; else if(board[A3] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_3; if(board[B2] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_2; else if(board[B3] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_3; if(board[C2] == create_figure(WHITE, PAWN)) white_pawn_shield += PAWN_ON_HORIONTAL_2 / 2; if(board[A1] == create_figure(WHITE, ROOK) || board[A2] == create_figure(WHITE, ROOK) || board[B1] == create_figure(WHITE, ROOK)) { evaluation += UNDEVELOPED_ROOK_PENALTY; } } else { white_pawn_shield = KING_IN_CENTER_PENALTY; } int black_pawn_shield = 0; if (place_of_black_king == H8 || place_of_black_king == H7 || place_of_black_king == G8 || place_of_black_king == G7 || place_of_black_king == F8) { if(board[H7] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_2; else if(board[H6] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_3; if(board[G7] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_2; else if(board[G6] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_3; if(board[F7] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_2 / 2; if(board[H8] == create_figure(BLACK, ROOK) || board[H7] == create_figure(BLACK, ROOK) || board[G8] == create_figure(BLACK, ROOK)) { evaluation += -UNDEVELOPED_ROOK_PENALTY; } } else if(place_of_black_king == A8 || place_of_black_king == A8 || place_of_black_king == B8 || place_of_black_king == B8 || place_of_black_king == C8) { if(board[A7] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_2; else if(board[A6] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_3; if(board[B7] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_2; else if(board[B6] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_3; if(board[C7] == create_figure(BLACK, PAWN)) black_pawn_shield += PAWN_ON_HORIONTAL_2 / 2; if(board[A8] == create_figure(BLACK, ROOK) || board[A7] == create_figure(BLACK, ROOK) || board[B8] == create_figure(BLACK, ROOK)) { evaluation += -UNDEVELOPED_ROOK_PENALTY; } } else { black_pawn_shield = KING_IN_CENTER_PENALTY; } int white_king_safety = (white_pawn_shield - white_king_tropism); int black_king_safety = (black_pawn_shield - black_king_tropism); evaluation += ((white_king_safety - black_king_safety) * current_figure_material / MAX_FIGURE_MATERIAL); int white_isolated = 0, black_isolated = 0; int white_doubled = 0, black_doubled = 0; for(int i = 1; i <= 8; i += 1) { if(white_pawns_in_verticals[i - 1] == 0 && white_pawns_in_verticals[i + 1] == 0) { white_isolated += white_pawns_in_verticals[i]; } else if(white_pawns_in_verticals[i] > 1) { white_doubled += white_pawns_in_verticals[i]; } if(black_pawns_in_verticals[i - 1] == 0 && black_pawns_in_verticals[i + 1] == 0) { black_isolated += white_pawns_in_verticals[i]; } else if(white_pawns_in_verticals[i] > 1) { black_doubled += white_pawns_in_verticals[i]; } } evaluation += (white_isolated - black_isolated) * PAWN_ISOLATED_PENALTY; evaluation += (white_doubled - black_doubled) * PAWN_DOUBLED_PENALTY; return turn_to_move == WHITE? evaluation: -evaluation; }