// SAKKOM: sakk a konzolban király! online multiplayer
// chess.com alternatíva, ami netcatet használ mint kliens
//
// AJEDREZ: servidor de ajedrez multijugador en línea
// alternativo a chess.com con un cliente para netcat.
// Hispanizado para texto-plano.xyz
//
// do what you want
// boa
#include <arpa/inet.h>
#include <pthread.h> // -lpthread
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#ifdef __BSD_VISIBLE
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#define PRINT_ALL(f_, ...) \
do { \
dprintf(w_fd, (f_), ##__VA_ARGS__); \
dprintf(b_fd, (f_), ##__VA_ARGS__); \
} while (0)
typedef enum mode { mode_ascii, mode_unicode } mode;
mode modes[2];
typedef enum color { c_w = 0, c_b = 1 } color;
typedef enum castle { castle_no, castle_long, castle_short } castle;
int colors[] = {39, 30};
char ascii_colors[] = {' ', '*'};
int abs(int a) {
if (a >= 0)
return a;
else
return -1 * a;
}
char symbols[7][7] = {" ", "♟︎", "♜", "♞", "♝", "♛", "♚"};
char ascii_symbols[7] = {' ', 'P', 'R', 'N', 'B', 'Q', 'K'};
typedef enum result { r_no, r_win, r_stalemate } result;
typedef enum piece_type {
p_no, // vacío
p_pawn, // peón
p_rook, // torre
p_knight, // caballo
p_bishop, // alfil
p_queen, // reina
p_king // rey
} piece_type;
typedef struct pos {
int x;
int y;
} pos;
typedef struct piece {
piece_type p;
color c;
} piece;
typedef struct move {
pos f; // pos. origen
pos t; // pos. destino
piece p; // pieza movida
piece e; // enemigo tomado
} 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 remaining_time[2] = {30 * 60, 30 * 60};
int game_number = 1;
void do_move(move m);
bool is_move_legal(color c, move m);
bool in_check(color c, int cx, int cy);
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() {
if (modes[c_w] == mode_unicode) {
dprintf(w_fd,
"\n \e[43m\x1B[30m\033[1m NEGRO \x1B[0m\n\n ");
for (int x = 0; x < 8; x++) {
dprintf(w_fd, " %c ", 'A' + x);
}
dprintf(w_fd, "\n \e[43m┏━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┓\x1B[0m\n");
for (int y = 7; y >= 0; y--) {
if (y != 7) {
dprintf(w_fd, "\x1B[0m "
"\e[43m┣━━━╋━━━╋━━━╋━━━╋━━━╋━━━╋━━━╋━━━┫\x1B[0m\n");
}
dprintf(w_fd, " %d \e[43m┃", y + 1);
for (int x = 0; x < 8; x++)
dprintf(w_fd, "\e[43m\x1B[%dm \033[1m%s \x1B[0m\e[43m┃",
colors[table[x][y].c], symbols[table[x][y].p]);
dprintf(w_fd, "\x1B[0m %d\x1B[0m\n", y + 1);
}
dprintf(w_fd, " \e[43m┗━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┛\x1B[0m\n ");
for (int x = 0; x < 8; x++) {
dprintf(w_fd, " %c ", 'A' + x);
}
dprintf(
w_fd,
"\n\n \e[43m\x1B[39m\033[1m BLANCO \x1B[0m\n\n\x1B[0m");
} else {
dprintf(w_fd, "\n [ NEGRO ]\n\n ");
for (int x = 0; x < 8; x++) {
dprintf(w_fd, " %c ", 'A' + x);
}
dprintf(w_fd, "\n +---+---+---+---+---+---+---+---+\n");
for (int y = 7; y >= 0; y--) {
if (y != 7) {
dprintf(w_fd, " +---+---+---+---+---+---+---+---+\n");
}
dprintf(w_fd, " %d |", y + 1);
for (int x = 0; x < 8; x++)
dprintf(w_fd, "%c%c |", ascii_colors[table[x][y].c],
ascii_symbols[table[x][y].p]);
dprintf(w_fd, " %d\n", y + 1);
}
dprintf(w_fd, " +---+---+---+---+---+---+---+---+\n ");
for (int x = 0; x < 8; x++) {
dprintf(w_fd, " %c ", 'A' + x);
}
dprintf(w_fd, "\n\n [ BLANCO ]\n\n");
}
if (modes[c_b] == mode_unicode) {
dprintf(b_fd,
"\n \e[43m\x1B[39m\033[1m BLANCO \x1B[0m\n\n ");
for (int x = 0; x < 8; x++) {
dprintf(b_fd, " %c ", 'A' + 7 - x);
}
dprintf(b_fd, "\n \e[43m┏━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┓\x1B[0m\n");
for (int y = 0; y < 8; y++) {
if (y != 0) {
dprintf(b_fd, "\x1B[0m "
"\e[43m┣━━━╋━━━╋━━━╋━━━╋━━━╋━━━╋━━━╋━━━┫\x1B[0m\n");
}
dprintf(b_fd, " %d \e[43m┃", y + 1);
for (int x = 7; x >= 0; x--)
dprintf(b_fd, "\e[43m\x1B[%dm \033[1m%s \x1B[0m\e[43m┃",
colors[table[x][y].c], symbols[table[x][y].p]);
dprintf(b_fd, "\x1B[0m %d\n", y + 1);
}
dprintf(b_fd, " \e[43m┗━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┛\x1B[0m\n ");
for (int x = 0; x < 8; x++) {
dprintf(b_fd, " %c ", 'A' + 7 - x);
}
dprintf(
b_fd,
"\n\n \e[43m\x1B[30m\033[1m NEGRO \x1B[0m\n\n\x1B[0m");
} else {
dprintf(b_fd, "\n [ BLANCO ]\n\n ");
for (int x = 0; x < 8; x++) {
dprintf(b_fd, " %c ", 'A' + 7 - x);
}
dprintf(b_fd, "\n +---+---+---+---+---+---+---+---+\n");
for (int y = 0; y < 8; y++) {
if (y != 0) {
dprintf(b_fd, " +---+---+---+---+---+---+---+---+\n");
}
dprintf(b_fd, " %d |", y + 1);
for (int x = 7; x >= 0; x--)
dprintf(b_fd, "%c%c |", ascii_colors[table[x][y].c],
ascii_symbols[table[x][y].p]);
dprintf(b_fd, " %d\n", y + 1);
}
dprintf(b_fd, " +---+---+---+---+---+---+---+---+\n ");
for (int x = 0; x < 8; x++) {
dprintf(b_fd, " %c ", 'A' + 7 - x);
}
dprintf(b_fd, "\n\n [ NEGRO ]\n\n");
}
}
bool in_check(color c, int cx, int 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;
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)) {
return true;
}
}
}
return false;
}
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 == m.p.c) {
res = in_check(m.p.c, x, y);
goto out;
}
}
}
out:
table[m.f.x][m.f.y] = m.p;
table[m.t.x][m.t.y] = m.e;
return res;
}
void setup_table() {
table[0][0] = (piece){p_rook, c_w};
table[1][0] = (piece){p_knight, c_w};
table[2][0] = (piece){p_bishop, c_w};
table[3][0] = (piece){p_king, c_w};
table[4][0] = (piece){p_queen, c_w};
table[5][0] = (piece){p_bishop, c_w};
table[6][0] = (piece){p_knight, c_w};
table[7][0] = (piece){p_rook, c_w};
for (int x = 0; x < 8; x++)
table[x][1] = (piece){p_pawn, c_w};
table[0][7] = (piece){p_rook, c_b};
table[1][7] = (piece){p_knight, c_b};
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[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};
}
pos find_king(color c) {
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 == c)
return (pos){x, y};
return (pos){-1, -1};
}
bool is_stalemate(color c) {
pos kp = find_king(c);
if (in_check(c, kp.x, kp.y))
return false;
move m;
for (m.f.y = 0; m.f.y < 8; m.f.y++) {
for (m.f.x = 0; m.f.x < 8; m.f.x++) {
if (table[m.f.x][m.f.y].c == c) {
m.p = table[m.f.x][m.f.y];
for (m.t.y = 0; m.t.y < 8; m.t.y++) {
for (m.t.x = 0; m.t.x < 8; m.t.x++) {
if (m.t.x == m.f.x && m.t.y == m.f.y)
continue;
m.e = table[m.t.x][m.t.y];
if (is_move_legal(c, m)) {
return false;
}
}
}
}
}
}
return true;
}
bool is_checkmate(color c) {
// probably the most simple and least efficient way to solve this problem
move m;
for (m.f.y = 0; m.f.y < 8; m.f.y++) {
for (m.f.x = 0; m.f.x < 8; m.f.x++) {
if (table[m.f.x][m.f.y].c == c) {
m.p = table[m.f.x][m.f.y];
for (m.t.y = 0; m.t.y < 8; m.t.y++) {
for (m.t.x = 0; m.t.x < 8; m.t.x++) {
m.e = table[m.t.x][m.t.y];
if (is_move_legal(c, m)) {
return false;
}
}
}
}
}
}
return true;
}
int move_num = 1;
void print_move(move m) {
char buf[20];
int n = 0;
buf[n++] = ascii_symbols[m.p.p];
buf[n++] = m.f.x + 'a';
buf[n++] = m.f.y + '1';
buf[n++] = ' ';
if (m.e.p != p_no)
buf[n++] = ascii_symbols[m.p.p];
buf[n++] = m.t.x + 'a';
buf[n++] = m.t.y + '1';
buf[n++] = '\n';
buf[n++] = '\0';
if (m.p.c == c_w) {
PRINT_ALL("%d. blanco: ", move_num);
} else {
PRINT_ALL("%d. negro: ", move_num);
move_num++;
}
PRINT_ALL(buf);
}
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;
}
castle is_castle(color c, move m) {
int dx = m.t.x - m.f.x, dy = m.t.y - m.f.y;
if (m.p.p == p_king) {
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)) {
return castle_short;
} 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)) {
return castle_long;
}
}
}
return castle_no;
}
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;
switch (m.p.p) {
case p_pawn:
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 &&
(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 &&
(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:
if (dx * dy != 0)
return false;
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 (!is_empty(table[m.f.x + n * v_x][m.f.y + n * v_y]))
return false;
break;
case p_bishop:
if (abs(dx) != abs(dy))
return false;
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 (!is_empty(table[m.f.x + n * v_x][m.f.y + n * v_y]))
return false;
break;
case p_queen:
if (dx * dy != 0 && abs(dx) != abs(dy))
return false;
v_x = dx ? ((dx > 0) ? 1 : -1) : 0;
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 (!is_empty(table[m.f.x + n * v_x][m.f.y + n * v_y]))
return false;
break;
case p_king:
if (abs(dx) > 3 || abs(dy) > 1)
return false;
if (in_check(c, m.t.x, m.t.y))
return false;
if (abs(dx) > 1) {
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)) {
return true;
} 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)) {
return true;
}
}
return false;
}
break;
case p_knight:
if (!((abs(dx) == 2 && abs(dy) == 1) || (abs(dx) == 1 && abs(dy) == 2)))
return false;
break;
case p_no:
return false;
break;
}
if (in_check_sim(m))
return false;
return true;
}
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;
}
piece_type choose_type(int fd) {
char cbuf[10] = {0};
while (true) {
dprintf(fd, "¿qué hacer?\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;
}
}
}
color c_c;
bool is_printing = false;
void *run_timer(void *vargp) {
while (true) {
if (!is_printing) {
dprintf(*c_fd, "\0337\r%02d:%02d > \0338", remaining_time[c_c] / 60,
remaining_time[c_c] % 60);
remaining_time[c_c]--;
if (remaining_time[c_c] <= 0) {
if (c_c == c_w)
PRINT_ALL("blanco se ha quedado sin tiempo. ¡negro gana!\n");
else
PRINT_ALL("negro se ha quedado sin tiempo. ¡blanco gana!\n");
raise(SIGTERM);
}
}
sleep(1);
}
return NULL;
}
void play_game() {
PRINT_ALL("¿interfaz (a)scii o (u)nicode? [u] ");
char input_str[50];
read(w_fd, input_str, 50);
if (input_str[0] == 'a')
modes[c_w] = mode_ascii;
else
modes[c_w] = mode_unicode;
read(b_fd, input_str, 50);
if (input_str[0] == 'a')
modes[c_b] = mode_ascii;
else
modes[c_b] = mode_unicode;
c_c = c_w; // current color
is_printing = true;
pthread_t thread_id;
pthread_create(&thread_id, NULL, run_timer, NULL);
print_table();
for (;;) {
is_printing = true;
if (c_c == c_w)
dprintf(b_fd, "blanco está pensando...\n");
else
dprintf(w_fd, "negro está pensando...\n");
no_print:
if (is_checkmate(c_c)) {
if (c_c == c_w)
PRINT_ALL("\n¡jaque mate! ¡negro gana!\n");
else
PRINT_ALL("\n¡jaque mate! ¡blanco gana!\n");
break;
} else if (is_stalemate(c_c)) {
PRINT_ALL("\n¡empate!\n");
break;
}
dprintf(*c_fd, "\n%02d:%02d > ", remaining_time[c_c] / 60,
remaining_time[c_c] % 60);
is_printing = false;
char buf[50] = {0};
read(*c_fd, buf, 50);
is_printing = true;
if (buf[0] == 's')
goto skip;
if (buf[0] == ':') {
if (c_c == c_w)
dprintf(b_fd, buf);
else
dprintf(w_fd, buf);
goto no_print;
}
move m = parse_move(buf);
if (is_move_legal(c_c, m)) {
do_move(m);
castle ct = is_castle(c_c, m);
if (ct == castle_short) {
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;
} else if (ct == castle_long) {
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;
}
if (m.p.p == p_rook &&
((m.f.x == 7 && m.f.y == 0) || (m.f.x == 7 && m.f.y == 7)))
moved_rook_r[c_c] = true;
else if (m.p.p == p_rook &&
((m.f.x == 0 && m.f.y == 0) || (m.f.x == 0 && m.f.y == 7)))
moved_rook_l[c_c] = true;
else if (m.p.p == p_king)
moved_king[c_c] = true;
// en passant
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 ((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);
print_table();
print_move(m);
} else {
dprintf(*c_fd, "error\n");
goto no_print;
}
skip:
if (c_fd == &w_fd) {
c_fd = &b_fd;
c_c = c_b;
} else {
c_fd = &w_fd;
c_c = c_w;
}
}
}
int main() {
setup_table();
// stolen from: https://git.sr.ht/~martijnbraam/among-sus
fd_set rfds, afds;
uint16_t port = 1234;
int listen_fd, listen6_fd, new_fd, i;
socklen_t client_size;
struct sockaddr_in listen_addr = {0}, client_addr = {0};
struct sockaddr_in6 listen6_addr = {0};
if ((listen_fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("IPv4 socket");
exit(EXIT_FAILURE);
}
if ((listen6_fd = socket(PF_INET6, SOCK_STREAM, 0)) == -1) {
perror("IPv6 socket");
exit(EXIT_FAILURE);
}
i = 1;
if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i))) {
perror("IPv4 setsockopt");
exit(EXIT_FAILURE);
}
if (setsockopt(listen6_fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i))) {
perror("IPv6 setsockopt");
exit(EXIT_FAILURE);
}
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listen_addr.sin_port = htons(port);
listen6_addr.sin6_family = AF_INET6;
listen6_addr.sin6_addr = in6addr_any;
listen6_addr.sin6_port = htons(port);
if (setsockopt(listen6_fd, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
if (setsockopt(listen6_fd, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
if (bind(listen_fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) <
0) {
perror("ipv4 bind");
return -1;
}
if (bind(listen6_fd, (struct sockaddr *)&listen6_addr, sizeof(listen6_addr)) <
0) {
perror("ipv6 bind");
return -1;
}
listen(listen_fd, 5);
listen(listen6_fd, 5);
printf("Escuchando en :%d\n", port);
FD_ZERO(&afds);
FD_SET(listen_fd, &afds);
FD_SET(listen6_fd, &afds);
while (1) {
rfds = afds;
if (select(FD_SETSIZE, &rfds, NULL, NULL, NULL) < 0) {
perror("select");
exit(EXIT_FAILURE);
}
for (i = 0; i < FD_SETSIZE; ++i) {
if (FD_ISSET(i, &rfds)) {
if (i == listen_fd || i == listen6_fd) {
client_size = sizeof(client_addr);
new_fd = accept(i, (struct sockaddr *)&client_addr, &client_size);
if (new_fd < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
printf("Nueva conexión desde %s:%d\n", inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
FD_SET(new_fd, &afds);
if (w_fd == -1) {
dprintf(new_fd, "tú eres las blancas\n");
w_fd = new_fd;
} else if (b_fd == -1) {
dprintf(new_fd, "tú eres las negras\n");
dprintf(w_fd, "ha entrado las negras, ¡comenzamos!\n");
b_fd = new_fd;
if (fork() == 0) {
play_game();
return 0;
} else {
w_fd = -1;
b_fd = -1;
game_number++;
}
} else {
// write(new_fd, "nincs hely!\n", strlen("nincs hely!\n"));
}
} else {
close(i);
FD_CLR(i, &afds);
}
}
}
}
return 0;
}