コミットを比較

...

7 コミット

作成者 SHA1 メッセージ 日付
ninya9k 9d5b87fcf6 lol 2023-11-15 08:20:40 +00:00
ninya9k 0d498ca1e7 readable socket niceties 2023-11-15 08:20:40 +00:00
ninya9k 42825de37b send board over socket 2023-11-15 08:20:40 +00:00
woosh fbabee3e02 fixed initial r,c 2023-11-15 08:20:40 +00:00
woosh b011990b5c fixing input and curses board - still broken 2023-11-15 08:20:40 +00:00
ninya9k 7b825df6ef ignore | lines 2023-11-15 08:20:40 +00:00
ninya9k 97f0d66126 readable iff not game<->game session 2023-11-15 08:20:36 +00:00
1個のファイルの変更98行の追加96行の削除

194
uttt.c
ファイルの表示

@ -41,6 +41,12 @@ const char arg_local[] = "--local";
const char arg_host[] = "--host"; const char arg_host[] = "--host";
const char arg_join[] = "--join"; const char arg_join[] = "--join";
const char PLAY_BOARDS[][14] = {
"top left", "top middle", "top right",
"middle left", "middle", "middle right",
"bottom left", "bottom middle", "bottom right",
"all boards",
};
char ut_turn(char player) char ut_turn(char player)
{ {
@ -183,17 +189,17 @@ void ut_drawBoard(void (*mvch)(void*, int, int, char), void *arg, const char *ti
*/ */
for(int r = 0; r < 3; r++) // tiles for(int r = 0; r < 3; r++) // tiles
for(int c = 0; c < 3; c++) for(int c = 0; c < 3; c++)
mvch(arg, iy + 2 * r, ix + 2 * c, T(r, c) != '\0' ? T(r, c) : ' '); mvch(arg, iy + 2 * r + 1, ix + 2 * c + 1, T(r, c) != '\0' ? T(r, c) : ' ');
//char info = winner != '\0' ? winner : highlight ? '*' : ' '; //char info = winner != '\0' ? winner : highlight ? '*' : ' ';
for(int r = 0; r < 3; r++) // | for(int r = 0; r < 3; r++) // |
for(int c = 0; c < 2; c++) for(int c = 0; c < 2; c++)
mvch(arg, iy + 2 * r, ix + 2 * c + 1, winner != '\0' ? winner : '|'); mvch(arg, iy + 2 * r + 1, ix + 2 * c + 1 + 1, winner != '\0' ? winner : '|');
for(int r = 0; r < 2; r++) // - for(int r = 0; r < 2; r++) // -
for(int c = 0; c < 3; c++) for(int c = 0; c < 3; c++)
mvch(arg, iy + 2 * r + 1, ix + 2 * c, winner != '\0' ? winner : '-'); mvch(arg, iy + 2 * r + 1 + 1, ix + 2 * c + 1, winner != '\0' ? winner : '-');
for(int r = 0; r < 2; r++) // + for(int r = 0; r < 2; r++) // +
for(int c = 0; c < 2; c++) for(int c = 0; c < 2; c++)
mvch(arg, iy + 2 * r + 1, ix + 2 * c + 1, winner != '\0' ? winner : highlight ? '*' : '+'); mvch(arg, iy + 2 * r + 1 + 1, ix + 2 * c + 1 + 1, winner != '\0' ? winner : highlight ? '*' : '+');
for(int r = 0; r < 7; r++) // | boundary for(int r = 0; r < 7; r++) // | boundary
for(int c = 0; c < 2; c++) for(int c = 0; c < 2; c++)
mvch(arg, iy + r, ix + 6 * c, ' '); mvch(arg, iy + r, ix + 6 * c, ' ');
@ -209,7 +215,7 @@ void ut_drawTiles(void (*mvch)(void*, int, int, char), void *arg, const struct u
for(int c = 0; c < 3; c++) for(int c = 0; c < 3; c++)
ut_drawBoard(mvch, arg, (char *)state->tiles, ut_drawBoard(mvch, arg, (char *)state->tiles,
27 * r + 3 * c, 9, 27 * r + 3 * c, 9,
7 * r + 1, 7 * c + 1, 7 * r, 7 * c,
state->boards[r][c], state->boards[r][c],
state->playBoard == -1 || state->playBoard == 3 * r + c); state->playBoard == -1 || state->playBoard == 3 * r + c);
if(numbers) if(numbers)
@ -245,6 +251,7 @@ void ut_bmvch(void *arg, int y, int x, char c)
((char (*)[DBOARDS_X])arg)[y][x] = c; ((char (*)[DBOARDS_X])arg)[y][x] = c;
} }
#define DTILES_LINE 1
void ut_cursdraw(const struct ut_state *state) void ut_cursdraw(const struct ut_state *state)
{ {
ut_cursprintf("Turn: %c Play board: %d\n", (int)state->player, state->playBoard); ut_cursprintf("Turn: %c Play board: %d\n", (int)state->player, state->playBoard);
@ -264,22 +271,22 @@ void ut_sockdraw(const struct ut_state *state, int fd)
} }
} }
/*void ut_show(const struct ut_state *state, int fd, bool as_comment) { void ut_show(const struct ut_state *state, int fd) {
#define tiles state->tiles #define tiles state->tiles
ut_dprintf(fd, "%sTurn: %c\n%sPlay board: %d\n", as_comment ? "| " : "", (int)state->player, as_comment ? "| " : "", state->playBoard); ut_dprintf(fd, "Turn: %c\nPlay board: %s\n", (int)state->player, PLAY_BOARDS[(state->playBoard + 10) % 10]);
int play_board_row = -1; int play_board_row = -1;
int play_board_col = -1; int play_board_col = -1;
if (state->playBoard != -1) { if (state->playBoard != -1) {
play_board_row = state->playBoard / 3; play_board_row = state->playBoard / 3;
play_board_col = state->playBoard % 3; play_board_col = state->playBoard % 3;
} }
ut_dprintf(fd, "%s 012 345 678\n", as_comment ? "| " : ""); ut_dprintf(fd, " 012 345 678\n");
for(int y = 0; y < 9; y++) for(int y = 0; y < 9; y++)
{ {
if (y == 3 || y == 6) { if (y == 3 || y == 6) {
ut_dprintf(fd, "%s ---+---+---\n", as_comment ? "| " : ""); ut_dprintf(fd, " ---+---+---\n");
} }
ut_dprintf(fd, "%s%d ", as_comment ? "| " : "", y); ut_dprintf(fd, "%d ", y);
for(int x = 0; x < 9; x++) for(int x = 0; x < 9; x++)
{ {
if (x == 3 || x == 6) { if (x == 3 || x == 6) {
@ -293,9 +300,9 @@ void ut_sockdraw(const struct ut_state *state, int fd)
ut_writefill(fd, "\n", 1); ut_writefill(fd, "\n", 1);
} }
if (play_board_col == -1) { if (play_board_col == -1) {
ut_dprintf(fd, "%s ^^^ ^^^ ^^^", as_comment ? "| " : ""); ut_dprintf(fd, " ^^^ ^^^ ^^^");
} else { } else {
ut_dprintf(fd, "%s ", as_comment ? "| " : ""); ut_dprintf(fd, " ");
for (int i = 0; i < play_board_col; i++) { for (int i = 0; i < play_board_col; i++) {
ut_dprintf(fd, " "); ut_dprintf(fd, " ");
} }
@ -303,7 +310,7 @@ void ut_sockdraw(const struct ut_state *state, int fd)
} }
ut_writefill(fd, "\n", 1); ut_writefill(fd, "\n", 1);
#undef tiles #undef tiles
}*/ }
/*void ut_show_boards(const struct ut_state *state) { /*void ut_show_boards(const struct ut_state *state) {
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
@ -337,7 +344,11 @@ int ut_cursgetpos(const struct ut_state *state, int *r, int *c)
(state->boards[r / 3][c / 3] == '\0' || d % 3 == 1)) (state->boards[r / 3][c / 3] == '\0' || d % 3 == 1))
MEVENT event; MEVENT event;
ut_cursprintf("Select move with arrow keys or mouse.\n"); ut_cursprintf("Select move with arrow keys or mouse.\n");
if(state->playBoard == -1) if(*r < 0 || *r >= 9 || *c < 0 || *c >= 9)
{
*r = 4; *c = 4;
}
else if(state->playBoard == -1)
{ {
*r = 3 * (*r / 3) + 1; *r = 3 * (*r / 3) + 1;
*c = 3 * (*c / 3) + 1; *c = 3 * (*c / 3) + 1;
@ -354,7 +365,7 @@ int ut_cursgetpos(const struct ut_state *state, int *r, int *c)
*r = 3 * (*r / 3) + 1; *r = 3 * (*r / 3) + 1;
*c = 3 * (*c / 3) + 1; *c = 3 * (*c / 3) + 1;
}*/ }*/
move((7 * (*r / 3) + 1) + (2 * (*r % 3)), move(DTILES_LINE + (7 * (*r / 3) + 1) + (2 * (*r % 3)),
(7 * (*c / 3) + 1) + (2 * (*c % 3))); (7 * (*c / 3) + 1) + (2 * (*c % 3)));
refresh(); refresh();
switch(getch()) switch(getch())
@ -362,6 +373,7 @@ int ut_cursgetpos(const struct ut_state *state, int *r, int *c)
case KEY_MOUSE: case KEY_MOUSE:
if(getmouse(&event) == OK && (event.bstate & BUTTON1_CLICKED)) if(getmouse(&event) == OK && (event.bstate & BUTTON1_CLICKED))
{ {
event.y -= DTILES_LINE;
if(event.y < 0 || event.y >= 21) {break;} if(event.y < 0 || event.y >= 21) {break;}
if(event.x < 0 || event.x >= 21) {break;} if(event.x < 0 || event.x >= 21) {break;}
*r = (event.y % 7 - 1) / 2 + 3 * (event.y / 7); *r = (event.y % 7 - 1) / 2 + 3 * (event.y / 7);
@ -454,35 +466,54 @@ int ut_cursgetpos(const struct ut_state *state, int *r, int *c)
return true; return true;
}*/ }*/
int ut_sockgetpos(const struct ut_state *state, int sock, int *x, int *y) { // TODO int ut_ignore_line(int sock) {
const int MAX_LINE_LEN = 128; char byte;
for (int i = 0; i < 128; i++) {
if (ut_readfill(sock, &byte, 1)) {
return 1;
}
if (byte == '\n') {return 0;}
}
return 2;
}
int ut_sockgetpos(const struct ut_state *state, int sock, int *x, int *y, bool readable) { // TODO
int index = 0;
char byte; char byte;
int n;
while (true) { while (true) {
char line[MAX_LINE_LEN]; int r = ut_readfill(sock, &byte, 1);
int len = ut_readline(sock, line, MAX_LINE_LEN); if (r < 0) {return r;}
if (len < 0) {return len;} if (r == 0) {
if (len == 0) {printf("sex\n");return -1;} printf("Connection closed.\n");
line[len] = 0; return -1;
printf("got >>>>>> line: '%s'\n", line); }
if (line[0] == '|') {continue;} if (index == 0 && byte == '|') {
if (len != 3) {return -3;} if (ut_ignore_line(sock)) {return -1;}
if (line[1] != ',') {return -3;} } else if (index == 0) {
*x = line[0] - 0x30; *x = byte - 0x30;
*y = line[2] - 0x30; } else if (index == 2) {
break; *y = byte - 0x30;
} else if (index == 1 && byte != ',' || index == 3 && byte != '\n') {
printf("Partner sent malformed coords - retrying\n");
if (ut_ignore_line(sock)) {return -1;}
if (readable) {
ut_dprintf(sock, "Invalid coordinates. Try again: ");
}
index = 0;
continue;
}
index++;
if (index == 4) {break;}
} }
printf("x=%d y=%d\n", *x, *y); printf("x=%d y=%d\n", *x, *y);
return 0; return 0;
} }
int ut_local_game(struct ut_state *state) { int ut_local_game(struct ut_state *state) {
int x, y; int x, y;
for(;;) for(;;)
{ {
int r, c, err; int r = 4, c = 4;
ut_curserase(); ut_curserase();
ut_cursdraw(state); ut_cursdraw(state);
char w = ut_winner((char *)state->boards, 0, 3); char w = ut_winner((char *)state->boards, 0, 3);
@ -498,10 +529,8 @@ int ut_local_game(struct ut_state *state) {
} }
break; break;
} }
err = ut_cursgetpos(state, &r, &c); if(ut_cursgetpos(state, &r, &c)) {continue;}
if (err) {continue;} if(ut_move(state, state, r, c)) {continue;}
err = ut_move(state, state, r, c);
if (err) {continue;}
} }
return 0; return 0;
} }
@ -510,12 +539,12 @@ int ut_network_game(struct ut_state *state, int sock, char player, bool readable
int x, y; int x, y;
//printf("You play as %c.\n", player); //printf("You play as %c.\n", player);
while (true) { while (true) {
ut_show(state, 1, false); //ut_show(state, 1, false);
ut_show_boards(state); //ut_show_boards(state);
ut_show(state, sock, true); ut_show(state, sock);
if (state->player == player) { if (state->player == player) {
if (readable) {ut_dprintf(sock, "Waiting for game partner ...\n");} if (readable) {ut_dprintf(sock, "Waiting for game partner ...\n");}
bool ok = getpos(state, &x, &y); bool ok = ut_cursgetpos(state, &x, &y);
if (!ok) {continue;} if (!ok) {continue;}
ut_dprintf(sock, "%d,%d\n", x, y); ut_dprintf(sock, "%d,%d\n", x, y);
} else { } else {
@ -524,16 +553,10 @@ int ut_network_game(struct ut_state *state, int sock, char player, bool readable
// line feed aligns game board each turn // line feed aligns game board each turn
ut_dprintf(sock, "\nPlace token %c in position x,y: ", ut_turn(player)); ut_dprintf(sock, "\nPlace token %c in position x,y: ", ut_turn(player));
} }
int err = ut_sockgetpos(state, sock, &x, &y); int err = ut_sockgetpos(state, sock, &x, &y, readable);
if (err == -1) { if (err == -1) {
printf("Connection closed.\n"); printf("Connection closed.\n");
return 1; return 1;
} else if (err == -2) {
printf("Partner sent too much data - exiting\n");
return 1;
} else if (err == -3) {
printf("Partner sent malformed data - retrying ...\n");
continue;
} }
} }
int err = ut_move(state, state, y, x); int err = ut_move(state, state, y, x);
@ -600,12 +623,32 @@ int ut_host_game(struct ut_state *state) {
char player; char player;
if ((player = ut_random_player()) < 0) {return 1;} if ((player = ut_random_player()) < 0) {return 1;}
// check to determine readable
char byte;
ut_dprintf(conn, "| Press enter to start: ");
if (ut_readfill(conn, &byte, 1)) {
printf("Connection closed.\n");
return 1;
}
bool readable = byte != '\0';
if (byte != '\n') {
int err = ut_ignore_line(sock);
if (err == 1) {
printf("Connection closed.\n");
return 1;
} else if (err == 2) {
printf("Partner sent too much data - exiting\n");
return 1;
}
}
// tell partner X or O // tell partner X or O
ut_dprintf(conn, "%c\n", ut_turn(player)); ut_dprintf(conn, "%c\n", ut_turn(player));
if (readable) {
ut_dprintf(conn, "You play as: %c\n\n", ut_turn(player));
}
// TODO check to determine readable return ut_network_game(state, conn, player, readable);
return ut_network_game(state, conn, player);
} }
int ut_join_game(struct ut_state *state) { int ut_join_game(struct ut_state *state) {
@ -626,17 +669,17 @@ int ut_join_game(struct ut_state *state) {
return 1; return 1;
} }
// tell host to deactivate readable
ut_dprintf(sock, "\0\n");
// host decides X or O // host decides X or O
char player_buf[2]; char player_buf[2];
char *player = (char*)&player_buf; char *player = (char*)&player_buf;
int r = ut_readfill(sock, player_buf, 2); int r = ut_readfill(sock, player_buf, 2);
if (r == 2) {printf("Connection closed.\n");} if (r == 2) {printf("Connection closed.\n");}
if (r != 0) {return 1;} if (r != 0) {return 1;}
state->host_player = ut_turn(*player);
// TODO send '\0' to deactivate readable return ut_network_game(state, sock, *player, false);
return ut_network_game(state, sock, *player);
} }
void finish(int sig) void finish(int sig)
@ -665,47 +708,6 @@ void begin(void)
mousemask(BUTTON1_CLICKED, NULL); mousemask(BUTTON1_CLICKED, NULL);
} }
/*int main(int argc, char *argv[]) {
signal(SIGINT, finish);
initscr();
keypad(stdscr, TRUE);
nonl(); // \r instead of \r\n
cbreak();
noecho();
mousemask(BUTTON1_CLICKED, NULL);
struct ut_state state = ut_initial;
while (true) {
int r, c, err;
erase();
ut_draw(&state);
char w = ut_winner((char *)state.boards, 0, 3);
if(w)
{
if(w == ' ')
{
mvaddstr(21, 0, "Draw!");
}
else
{
mvaddch(21, 0, w);
mvaddstr(21, 1, " Wins!");
}
mvaddstr(22, 0, "Press any key to exit.");
refresh();
mousemask(0, NULL);
getch();
break;
}
err = ut_click(&state, &r, &c);
if (err) {continue;}
err = ut_move(&state, &state, r, c);
if (err) {continue;}
}
finish(0);
return 0;
}*/
int main(int argc, char **argv) { int main(int argc, char **argv) {
struct ut_state state = ut_initial; struct ut_state state = ut_initial;