diff options
author | boa <boa@pm.me> | 2021-02-01 15:58:50 +0100 |
---|---|---|
committer | boa <boa@pm.me> | 2021-02-01 15:58:50 +0100 |
commit | f4adaa2c550382ae2149078ccfe70d4941fee6c0 (patch) | |
tree | 6d46b933204776b0a84e96abfac9e9913e392422 | |
parent | 21f0a88245e244a7183509fdd5e7499eea13829b (diff) | |
download | ajedrez-f4adaa2c550382ae2149078ccfe70d4941fee6c0.tar.gz |
refactoring
-rwxr-xr-x | chess | bin | 0 -> 37712 bytes | |||
-rw-r--r-- | sakkom.c | 344 |
2 files changed, 205 insertions, 139 deletions
Binary files differ @@ -45,31 +45,52 @@ typedef struct pos { int y; } pos; -typedef struct move { - pos f; - pos t; - piece p; -} move; - typedef struct piece { piece_type p; color c; } piece; +typedef struct move { + pos f; // from + pos t; // to + piece p; // piece moved + piece e; // enemy taken +} move; + +typedef struct en_passant { + bool valid; + pos p; + piece *to_remove; +} en_passant; +en_passant enp; + piece table[8][8]; int w_fd = -1, b_fd = -1; int *c_fd = &w_fd; // current fd bool moved_king[2] = {false, false}; bool moved_rook_l[2] = {false, false}; bool moved_rook_r[2] = {false, false}; -int pawnx = -1, pawny = -1; +void do_move(move m); +bool is_move_legal(color c, move m); bool in_check(color c, int cx, int cy); -bool is_valid(int from_x, int from_y, int to_x, int to_y); void print_table(); void setup_table(); void play_game(); +bool is_same_pos(pos p1, pos p2) { return p1.x == p2.x && p1.y == p2.y; } + +bool is_empty(piece p) { return p.p == p_no; } +bool is_friend_of(color c, piece p) { return !is_empty(p) && p.c == c; } +bool is_enemy_of(color c, piece p) { return !is_empty(p) && p.c != c; } + +bool is_inside(int i) { return i >= 0 && i < 8; } + +bool is_move_inside(move m) { + return is_inside(m.f.x) && is_inside(m.f.y) && is_inside(m.t.x) && + is_inside(m.t.y); +} + void print_table() { dprintf(w_fd, "\n \e[43m\x1B[30m\033[1m BLACK \x1B[0m\n\n "); dprintf(b_fd, "\n \e[43m\x1B[39m\033[1m WHITE \x1B[0m\n\n "); @@ -120,11 +141,18 @@ void print_table() { bool in_check(color c, int cx, int cy) { printf("c: %d, %d, %d\n", c, cx, cy); + move m; + m.t.x = cx; + m.t.y = cy; + m.e = table[cx][cy]; for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { if (cx == x && cy == y) continue; - if (table[x][y].c != c && is_valid(x, y, cx, cy)) { + m.f.x = x; + m.f.y = y; + m.p = table[x][y]; + if (table[x][y].c != c && is_move_legal(m.p.c, m)) { printf("true check\n"); return true; } @@ -133,22 +161,20 @@ bool in_check(color c, int cx, int cy) { return false; } -bool in_check_sim(int from_x, int from_y, int to_x, int to_y) { - piece tmp = table[to_x][to_y]; - table[to_x][to_y] = table[from_x][from_y]; - table[from_x][from_y].p = p_no; +bool in_check_sim(move m) { + do_move(m); bool res = false; for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { - if (table[x][y].p == p_king && table[x][y].c == table[to_x][to_y].c) { + if (table[x][y].p == p_king && table[x][y].c == m.p.c) { res = in_check(table[x][y].c, x, y); - goto finish; + goto out; } } } -finish: - table[from_x][from_y] = table[to_x][to_y]; - table[to_x][to_y] = tmp; +out: + table[m.f.x][m.f.y] = m.p; + table[m.t.x][m.t.y] = m.e; return res; } @@ -169,15 +195,13 @@ void setup_table() { // table[2][7] = (piece){p_bishop, c_b}; table[3][7] = (piece){p_king, c_b}; // table[4][7] = (piece){p_queen, c_b}; - // table[5][7] = (piece){p_bishop, c_b}; + table[5][7] = (piece){p_bishop, c_b}; // table[6][7] = (piece){p_knight, c_b}; // table[7][7] = (piece){p_rook, c_b}; // for (int x = 0; x < 8; x++) // table[x][6] = (piece){p_pawn, c_b}; } -int is_inside(int i) { return i >= 0 && i < 8; } - result is_checkmate(color c) { int kx = -1, ky = -1; for (int y = 0; y < 8; y++) { @@ -198,55 +222,125 @@ out: return r_no; } printf("k in check\n"); + move m; + m.f.x = kx; + m.f.y = ky; + m.p = table[kx][ky]; for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; - if (is_valid(kx, ky, kx + x, ky + y) && is_inside(ky + y) && - is_inside(kx + x) && !in_check(c, kx + x, ky + y)) { + m.t.x = kx + x; + m.t.y = ky + y; + m.e = table[kx + x][ky + y]; + if (is_move_legal(c, m) && is_inside(ky + y) && is_inside(kx + x) && + !in_check(c, kx + x, ky + y)) { return r_no; } } } color ic = c == c_w ? c_b : c_w; + m.t.x = kx; + m.t.y = ky; + m.e = table[kx][ky]; for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { - if (table[x][y].c != c && is_valid(x, y, kx, ky)) { + m.f.x = x; + m.f.y = y; + m.p = table[x][y]; + if (table[x][y].c != c && is_move_legal(c, m)) { int dx = kx - x, dy = ky - y; if (table[x][y].p == p_rook || table[x][y].p == p_queen || table[x][y].p == p_bishop) { int v_x = dx ? ((dx > 0) ? 1 : -1) : 0; int v_y = dy ? ((dy > 0) ? 1 : -1) : 0; - for (int n = 1; n < abs(dx); n++) + bool possible = false; + for (int n = 0; n < abs(dx); n++) if (table[x + n * v_x][y + n * v_y].p == p_no) if (in_check(ic, x + n * v_x, y + n * v_y)) - return r_no; + possible = true; + if (!possible) { + return r_win; + } } + return r_no; } } } return r_win; } -bool is_valid(int from_x, int from_y, int to_x, int to_y) { - piece p = table[from_x][from_y]; - int dx = to_x - from_x, dy = to_y - from_y; +void print_move(move m) { + char buf[20]; + int n = 0; + buf[n++] = table[m.f.x][m.f.y].p; + buf[n++] = m.f.x + 'a'; + buf[n++] = m.f.y + '0'; + buf[n++] = ' '; + if (table[m.t.x][m.t.y].p != p_no) + buf[n++] = table[m.t.x][m.t.y].p; + buf[n++] = m.t.x + 'a'; + buf[n++] = m.t.y + '0'; + buf[n++] = '\n'; + buf[n++] = '\0'; + printf("%s", buf); + if (m.p.c == c_w) + dprintf(b_fd, buf); + else + dprintf(w_fd, buf); +} + +bool print_result(color c) { + result r; + if ((r = is_checkmate(c)) != r_no) { + if (r == r_stalemate) { + PRINT_ALL("\ndöntetlen\n"); + } else { + if (c == c_w) + PRINT_ALL("\na fekete nyert!\n"); + else + PRINT_ALL("\na fehér nyert!\n"); + } + return true; + } + return false; +} + +move parse_move(char buf[50]) { + move m; + + m.f.x = buf[0] - 'a'; + m.f.y = buf[1] - '1'; + m.t.x = buf[3] - 'a'; + m.t.y = buf[4] - '1'; + + m.p = table[m.f.x][m.f.y]; + m.e = table[m.t.x][m.t.y]; + + return m; +} + +bool is_move_legal(color c, move m) { + if (!is_move_inside(m) || is_empty(m.p) || is_enemy_of(c, m.p) || + is_friend_of(c, m.e)) + return false; + + int dx = m.t.x - m.f.x, dy = m.t.y - m.f.y; int v_x, v_y, l; - if (in_check_sim(from_x, from_y, to_x, to_y)) + if (in_check_sim(m)) return false; - switch (p.p) { + switch (m.p.p) { case p_pawn: - if ((dx != 0 && - ((dx != 1 && dx != -1) || (dy != 1 && p.c == c_w) || - (dy != -1 && p.c == c_b) || - (table[to_x][to_y].p == p_no && to_x != pawnx && to_y != pawny))) || - dy < -2 || dy > 2 || (dy == 1 && p.c != c_w) || + if ((dx != 0 && ((dx != 1 && dx != -1) || (dy != 1 && c == c_w) || + (dy != -1 && c == c_b) || + (is_empty(m.e) && is_same_pos(m.t, enp.p)))) || + dy < -2 || dy > 2 || (dy == 1 && c != c_w) || (dy == 2 && - (p.c != c_w || from_y != 1 || table[from_x][from_y + 1].p != p_no)) || - (dy == -1 && p.c != c_b) || + (c != c_w || m.f.y != 1 || table[m.f.x][m.f.y + 1].p != p_no)) || + (dy == -1 && c != c_b) || (dy == -2 && - (p.c != c_b || from_y != 6 || table[from_x][from_y - 1].p != p_no)) || - (dx == 0 && table[to_x][to_y].p != p_no)) + (c != c_b || m.f.y != 6 || table[m.f.x][m.f.y - 1].p != p_no)) || + (dx == 0 && !is_empty(m.e))) return false; break; case p_rook: @@ -255,12 +349,12 @@ bool is_valid(int from_x, int from_y, int to_x, int to_y) { v_x = (dx != 0) ? ((dx > 0) ? 1 : -1) : 0; v_y = (dy != 0) ? ((dy > 0) ? 1 : -1) : 0; for (int n = 1; n < abs(dx + dy); n++) - if (table[from_x + n * v_x][from_y + n * v_y].p != p_no) + if (!is_empty(table[m.f.x + n * v_x][m.f.y + n * v_y])) return false; - if ((from_x == 7 && from_y == 0) || (from_x == 7 && from_y == 7)) - moved_rook_r[p.c] = true; - if ((from_x == 0 && from_y == 0) || (from_x == 0 && from_y == 7)) - moved_rook_l[p.c] = true; + if ((m.f.x == 7 && m.f.y == 0) || (m.f.x == 7 && m.f.y == 7)) + moved_rook_r[c] = true; + if ((m.f.x == 0 && m.f.y == 0) || (m.f.x == 0 && m.f.y == 7)) + moved_rook_l[c] = true; break; case p_bishop: if (abs(dx) != abs(dy)) @@ -268,7 +362,7 @@ bool is_valid(int from_x, int from_y, int to_x, int to_y) { v_x = dx ? ((dx > 0) ? 1 : -1) : 0; v_y = dy ? ((dy > 0) ? 1 : -1) : 0; for (int n = 1; n < abs(dx); n++) - if (table[from_x + n * v_x][from_y + n * v_y].p != p_no) + if (!is_empty(table[m.f.x + n * v_x][m.f.y + n * v_y])) return false; break; case p_queen: @@ -278,39 +372,37 @@ bool is_valid(int from_x, int from_y, int to_x, int to_y) { v_y = dy ? ((dy > 0) ? 1 : -1) : 0; l = (dx * dy == 0) ? abs(dx + dy) : abs(dx); for (int n = 1; n < l; n++) - if (table[from_x + n * v_x][from_y + n * v_y].p != p_no) + if (!is_empty(table[m.f.x + n * v_x][m.f.y + n * v_y])) return false; break; case p_king: - if (in_check(p.c, to_x, to_y)) + if (in_check(c, m.t.x, m.t.y)) return 0; if (abs(dx) > 1 || abs(dy) > 1) { - if (!moved_king[p.c] && dy == 0) { - if (!moved_rook_l[p.c] && dx == -2 && - table[from_x - 1][from_y].p == p_no && - table[from_x - 3][from_y].p == p_rook && - table[from_x - 3][from_y].c == p.c && - !in_check(p.c, from_x - 1, from_y) && - !in_check(p.c, from_x, from_y)) { - table[from_x - 1][from_y] = table[from_x - 3][from_y]; - table[from_x - 3][from_y].p = p_no; + if (!moved_king[c] && dy == 0) { + if (!moved_rook_l[c] && dx == -2 && table[m.f.x - 1][m.f.y].p == p_no && + table[m.f.x - 3][m.f.y].p == p_rook && + table[m.f.x - 3][m.f.y].c == c && !in_check(c, m.f.x - 1, m.f.y) && + !in_check(c, m.f.x, m.f.y)) { + table[m.f.x - 1][m.f.y] = table[m.f.x - 3][m.f.y]; + table[m.f.x - 3][m.f.y].p = p_no; break; - } else if (!moved_rook_r[p.c] && dx == 3 && - table[from_x + 1][from_y].p == p_no && - table[from_x + 2][from_y].p == p_no && - table[from_x + 4][from_y].p == p_rook && - table[from_x + 4][from_y].c == p.c && - !in_check(p.c, from_x + 1, from_y) && - !in_check(p.c, from_x + 2, from_y) && - !in_check(p.c, from_x, from_y)) { - table[from_x + 2][from_y] = table[from_x + 4][from_y]; - table[from_x + 4][from_y].p = p_no; + } else if (!moved_rook_r[c] && dx == 3 && + table[m.f.x + 1][m.f.y].p == p_no && + table[m.f.x + 2][m.f.y].p == p_no && + table[m.f.x + 4][m.f.y].p == p_rook && + table[m.f.x + 4][m.f.y].c == c && + !in_check(c, m.f.x + 1, m.f.y) && + !in_check(c, m.f.x + 2, m.f.y) && + !in_check(c, m.f.x, m.f.y)) { + table[m.f.x + 2][m.f.y] = table[m.f.x + 4][m.f.y]; + table[m.f.x + 4][m.f.y].p = p_no; break; } } return false; } - moved_king[p.c] = true; + moved_king[c] = true; break; case p_knight: if (!((abs(dx) == 2 && abs(dy) == 1) || (abs(dx) == 1 && abs(dy) == 2))) @@ -323,24 +415,30 @@ bool is_valid(int from_x, int from_y, int to_x, int to_y) { return true; } -void print_move(color c, char buf[50]) { - printf("%s", buf); - if (c == c_w) - dprintf(b_fd, buf); - else - dprintf(w_fd, buf); +void do_move(move m) { + table[m.t.x][m.t.y] = table[m.f.x][m.f.y]; + table[m.f.x][m.f.y].p = p_no; } -void print_result(color c) { - if ((result r = is_checkmate(c)) != r_no) { - if (r == r_stalemate) { - PRINT_ALL("\ndöntetlen\n"); - } else { - if (c == c_w) - PRINT_ALL("\na fekete nyert!\n"); - else - PRINT_ALL("\na fehér nyert!\n"); - break; +piece_type choose_type(int fd) { + char cbuf[10] = {0}; + while (true) { + dprintf(fd, "mit kérsz?\n"); + dprintf(fd, "> "); + read(fd, cbuf, 10); + switch (cbuf[0]) { + case 'P': + return p_pawn; + case 'R': + return p_rook; + case 'N': + return p_knight; + case 'B': + return p_bishop; + case 'Q': + return p_queen; + case 'K': + return p_king; } } } @@ -355,9 +453,10 @@ void play_game() { dprintf(w_fd, "fekete gondolkodik...\n"); no_print: dprintf(*c_fd, "> "); - print_result(c_c); + if (print_result(c_c)) { + break; + } - // parse move char buf[50] = {0}; read(*c_fd, buf, 50); if (buf[0] == 's') @@ -369,64 +468,31 @@ void play_game() { dprintf(w_fd, buf); goto no_print; } - int from_x = buf[0] - 'a'; - int from_y = buf[1] - '1'; - int to_x = buf[3] - 'a'; - int to_y = buf[4] - '1'; - - // is legal - if (!is_inside(from_x) || !is_inside(from_y) || !is_inside(to_x) || - !is_inside(to_y) || table[from_x][from_y].p == p_no || - table[from_x][from_y].c != c_c || - (table[to_x][to_y].c == c_c && table[to_x][to_y].p != p_no) || - !is_valid(from_x, from_y, to_x, to_y)) { - dprintf(*c_fd, "hiba: %d %d %d %d\n", from_x, from_y, to_x, to_y); - goto no_print; - } else { - print_move(c_c, buf); - // do move - table[to_x][to_y] = table[from_x][from_y]; - table[from_x][from_y].p = p_no; + move m = parse_move(buf); + + if (is_move_legal(c_c, m)) { + print_move(m); + do_move(m); // en passant - if (to_x == pawnx && to_y == pawny && table[to_x][to_y].p == p_pawn) - table[pawnx][to_y + (pawny - to_y)].p = p_no; - pawnx = -1, pawny = -1; - if (table[to_x][to_y].p == p_pawn && - (from_y - to_y == -2 || from_y - to_y == 2)) - pawnx = to_x, pawny = to_y + (from_y - to_y) / 2; + if (enp.valid && is_same_pos(enp.p, m.t) && m.p.p == p_pawn) + enp.to_remove->p = p_no; + enp.valid = false; + if (m.p.p == p_pawn && abs(m.f.y - m.t.y) == 2) { + enp.valid = true; + enp.to_remove = &table[m.t.x][m.t.y]; + enp.p.x = m.t.x; + enp.p.y = m.t.y + (c_c == c_w ? -1 : 1); + } // trade pawn - if ((to_y == 0 || to_y == 7) && table[to_x][to_y].p == p_pawn) { - char cbuf[10] = {0}; - retry: - dprintf(*c_fd, "mit kérsz?\n"); - dprintf(*c_fd, "> "); - read(*c_fd, cbuf, 10); - switch (cbuf[0]) { - case 'P': - table[to_x][to_y].p = p_pawn; - break; - case 'R': - table[to_x][to_y].p = p_rook; - break; - case 'N': - table[to_x][to_y].p = p_knight; - break; - case 'B': - table[to_x][to_y].p = p_bishop; - break; - case 'Q': - table[to_x][to_y].p = p_queen; - break; - case 'K': - table[to_x][to_y].p = p_king; - break; - default: - goto retry; - } - } + if ((m.t.y == 0 || m.t.y == 7) && m.p.p == p_pawn) + table[m.t.x][m.t.y].p = choose_type(*c_fd); + + } else { + dprintf(*c_fd, "hiba\n"); + goto no_print; } skip: if (c_fd == &w_fd) { |