aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorboa <boa@pm.me>2021-02-01 15:58:50 +0100
committerboa <boa@pm.me>2021-02-01 15:58:50 +0100
commitf4adaa2c550382ae2149078ccfe70d4941fee6c0 (patch)
tree6d46b933204776b0a84e96abfac9e9913e392422
parent21f0a88245e244a7183509fdd5e7499eea13829b (diff)
downloadajedrez-f4adaa2c550382ae2149078ccfe70d4941fee6c0.tar.gz
refactoring
-rwxr-xr-xchessbin0 -> 37712 bytes
-rw-r--r--sakkom.c344
2 files changed, 205 insertions, 139 deletions
diff --git a/chess b/chess
new file mode 100755
index 0000000..243e72d
--- /dev/null
+++ b/chess
Binary files differ
diff --git a/sakkom.c b/sakkom.c
index 430ce8d..3e8e8c3 100644
--- a/sakkom.c
+++ b/sakkom.c
@@ -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) {
Un proyecto texto-plano.xyz