From 9f7b107813612a61a6dbb804252519b2094d4289 Mon Sep 17 00:00:00 2001 From: woosh <> Date: Sun, 12 Nov 2023 12:20:31 +0000 Subject: [PATCH 1/6] new ncurses branch mean ninya --- uttt.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/uttt.c b/uttt.c index 4a7765b..1209870 100644 --- a/uttt.c +++ b/uttt.c @@ -174,8 +174,11 @@ void finish(int sig) int main(int *argc, char **argv) { signal(SIGINT, finish); - /*initscr(); - keypad(stdscr, TRUE);*/ + initscr(); + keypad(stdscr, TRUE); + nonl(); + cbreak(); + noecho(); struct ut_state state = ut_initial; while (true) { From 0244c1024488b0a00d66b2936c3028f65db1a304 Mon Sep 17 00:00:00 2001 From: woosh <> Date: Sun, 12 Nov 2023 15:53:57 +0000 Subject: [PATCH 2/6] ncurses is here --- uttt.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 110 insertions(+), 10 deletions(-) diff --git a/uttt.c b/uttt.c index 1209870..6ced0fe 100644 --- a/uttt.c +++ b/uttt.c @@ -32,7 +32,7 @@ char ut_turn(char player) } #define T(r, c) (tiles[offset + stride * r + c]) -char ut_winner(char *tiles, int offset, int stride) { +char ut_winner(const char *tiles, int offset, int stride) { // whoreizontal wins for (int y = 0; y < 3; y++) @@ -94,6 +94,96 @@ int ut_move(struct ut_state *new_state, const struct ut_state *old_state, int ro return 0; } +void ut_drawBoard(const char *tiles, int offset, int stride, int iy, int ix, char winner, bool highlight) +{ + // 5x5 board display + /* + * X|X|X + * -+-+- + * X|X|X + * -+-+- + * X|X|X + */ + for(int r = 0; r < 3; r++) + for(int c = 0; c < 3; c++) + mvaddch(iy + 2 * r, ix + 2 * c, T(r, c) != '\0' ? T(r, c) : ' '); + //char info = winner != '\0' ? winner : highlight ? '*' : ' '; + for(int r = 0; r < 3; r++) + for(int c = 0; c < 2; c++) + mvaddch(iy + 2 * r, ix + 2 * c + 1, winner != '\0' ? winner : '|'); + for(int r = 0; r < 2; r++) + for(int c = 0; c < 3; c++) + mvaddch(iy + 2 * r + 1, ix + 2 * c, winner != '\0' ? winner : '-'); + for(int r = 0; r < 2; r++) + for(int c = 0; c < 2; c++) + mvaddch(iy + 2 * r + 1, ix + 2 * c + 1, winner != '\0' ? winner : highlight ? '*' : '+'); +} + +void ut_draw(const struct ut_state *state) +{ + for(int r = 0; r < 3; r++) + for(int c = 0; c < 3; c++) + ut_drawBoard((char *)state->tiles, + 27 * r + 3 * c, 9, + 7 * r + 1, 7 * c + 1, + state->boards[r][c], + state->playBoard == -1 || state->playBoard == 3 * r + c); + mvaddstr(21, 0, "Select move with arrow keys or mouse."); + refresh(); +} + +int ut_click(int *r, int *c) +{ + MEVENT event; + for(;;) + { + move((7 * (*r / 3) + 1) + (2 * (*r % 3)), + (7 * (*c / 3) + 1) + (2 * (*c % 3))); + refresh(); + switch(getch()) + { + case KEY_MOUSE: + if(getmouse(&event) == OK && (event.bstate & BUTTON1_CLICKED)) + { + if(event.y < 0 || event.y >= 21) {break;} + if(event.x < 0 || event.x >= 21) {break;} + *r = event.y % 7 - 1; // this messes up cursor position + *c = event.x % 7 - 1; + if(*r % 2 != 0) {break;} + if(*c % 2 != 0) {break;} + *r /= 2; *c /= 2; + *r += 3 * (event.y / 7); + *c += 3 * (event.x / 7); + return 0; + } + break; + case 'w': /* FALLTHROUGH */ + case KEY_UP: + *r = (((*r - 1) % 9) + 9) % 9; + break; + case 'a': /* FALLTHROUGH */ + case KEY_LEFT: + *c = (((*c - 1) % 9) + 9) % 9; + break; + case 's': /* FALLTHROUGH */ + case KEY_DOWN: + *r = (*r + 1) % 9; + break; + case 'd': /* FALLTHROUGH */ + case KEY_RIGHT: + *c = (*c + 1) % 9; + break; + case ' ': /* FALLTHROUGH */ + case '\n': /* FALLTHROUGH */ + case KEY_ENTER: + return 0; + case ERR: /* FALLTHROUGH */ + default: + break; + } + } +} + void ut_show(const struct ut_state *state) { #define tiles state->tiles printf("Turn: %c\nPlay board: %d\n", (int)state->player, state->playBoard); @@ -176,31 +266,41 @@ int main(int *argc, char **argv) { signal(SIGINT, finish); initscr(); keypad(stdscr, TRUE); - nonl(); + //nonl(); cbreak(); noecho(); + mousemask(BUTTON1_CLICKED, NULL); struct ut_state state = ut_initial; while (true) { - int x, y; - ut_show(&state); - bool ok = getpos(&state, &y, &x); - if (!ok) {continue;} - int err = ut_move(&state, &state, x, y); + int r, c, err; + //ut_show(&state); + ut_draw(&state); + //bool ok = getpos(&state, &y, &x); + //if (!ok) {continue;} + err = ut_click(&r, &c); + if (err) {continue;} + err = ut_move(&state, &state, r, c); if (err) {continue;} char w = ut_winner((char *)state.boards, 0, 3); if(w) { if(w == ' ') { - printf("\nDraw!\n"); + mvaddstr(22, 0, "Draw!"); } else { - printf("\n%c wins!\n", (int)w); + mvaddch(22, 0, w); + mvaddstr(22, 1, " Wins!"); } - return 0; + mvaddstr(23, 0, "Press any key to exit."); + refresh(); + mousemask(0, NULL); + getch(); + break; } } + finish(0); return 0; } From 4954c8f4c8ab67a75d80d71b7af4c6a19aea9cfb Mon Sep 17 00:00:00 2001 From: woosh <> Date: Mon, 13 Nov 2023 02:52:21 +0000 Subject: [PATCH 3/6] better movement --- uttt.c | 80 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/uttt.c b/uttt.c index 6ced0fe..3f5d80c 100644 --- a/uttt.c +++ b/uttt.c @@ -128,15 +128,32 @@ void ut_draw(const struct ut_state *state) 7 * r + 1, 7 * c + 1, state->boards[r][c], state->playBoard == -1 || state->playBoard == 3 * r + c); - mvaddstr(21, 0, "Select move with arrow keys or mouse."); - refresh(); + //refresh(); } -int ut_click(int *r, int *c) +int ut_click(const struct ut_state *state, int *r, int *c) { +#define P(r, c, d) ((state->playBoard == -1 || state->playBoard == 3 * (r / 3) + (c / 3)) && \ + (state->boards[r / 3][c / 3] == '\0' || d % 3 == 1)) MEVENT event; + mvaddstr(21, 0, "Select move with arrow keys or mouse."); + if(state->playBoard == -1) + { + *r = 3 * (*r / 3) + 1; + *c = 3 * (*c / 3) + 1; + } + else + { + *r = 3 * (state->playBoard / 3) + 1; + *c = 3 * (state->playBoard % 3) + 1; + } for(;;) { + /*if(state->boards[*r / 3][*c / 3] != '\0') + { + *r = 3 * (*r / 3) + 1; + *c = 3 * (*c / 3) + 1; + }*/ move((7 * (*r / 3) + 1) + (2 * (*r % 3)), (7 * (*c / 3) + 1) + (2 * (*c % 3))); refresh(); @@ -157,24 +174,48 @@ int ut_click(int *r, int *c) return 0; } break; + case 'k': /* FALLTHROUGH */ case 'w': /* FALLTHROUGH */ case KEY_UP: - *r = (((*r - 1) % 9) + 9) % 9; + //*r = (((*r - 1) % 9) + 9) % 9; + for(int i = 0; i < 9 + 1; i++) + { + *r = (*r + 9 - 1) % 9; + if(P(*r, *c, *r)) {break;} + } break; + case 'h': /* FALLTHROUGH */ case 'a': /* FALLTHROUGH */ case KEY_LEFT: - *c = (((*c - 1) % 9) + 9) % 9; + //*c = (((*c - 1) % 9) + 9) % 9; + for(int i = 0; i < 9 + 1; i++) + { + *c = (*c + 9 - 1) % 9; + if(P(*r, *c, *c)) {break;} + } break; + case 'j': /* FALLTHROUGH */ case 's': /* FALLTHROUGH */ case KEY_DOWN: - *r = (*r + 1) % 9; + //*r = (*r + 1) % 9; + for(int i = 0; i < 9 + 1; i++) + { + *r = (*r + 1) % 9; + if(P(*r, *c, *r)) {break;} + } break; + case 'l': /* FALLTHROUGH */ case 'd': /* FALLTHROUGH */ case KEY_RIGHT: - *c = (*c + 1) % 9; + //*c = (*c + 1) % 9; + for(int i = 0; i < 9 + 1; i++) + { + *c = (*c + 1) % 9; + if(P(*r, *c, *c)) {break;} + } break; case ' ': /* FALLTHROUGH */ - case '\n': /* FALLTHROUGH */ + case '\r': /* FALLTHROUGH */ case KEY_ENTER: return 0; case ERR: /* FALLTHROUGH */ @@ -182,6 +223,7 @@ int ut_click(int *r, int *c) break; } } +#undef P } void ut_show(const struct ut_state *state) { @@ -266,7 +308,7 @@ int main(int *argc, char **argv) { signal(SIGINT, finish); initscr(); keypad(stdscr, TRUE); - //nonl(); + nonl(); // \r instead of \r\n cbreak(); noecho(); mousemask(BUTTON1_CLICKED, NULL); @@ -274,32 +316,30 @@ int main(int *argc, char **argv) { struct ut_state state = ut_initial; while (true) { int r, c, err; - //ut_show(&state); + erase(); ut_draw(&state); - //bool ok = getpos(&state, &y, &x); - //if (!ok) {continue;} - err = ut_click(&r, &c); - if (err) {continue;} - err = ut_move(&state, &state, r, c); - if (err) {continue;} char w = ut_winner((char *)state.boards, 0, 3); if(w) { if(w == ' ') { - mvaddstr(22, 0, "Draw!"); + mvaddstr(21, 0, "Draw!"); } else { - mvaddch(22, 0, w); - mvaddstr(22, 1, " Wins!"); + mvaddch(21, 0, w); + mvaddstr(21, 1, " Wins!"); } - mvaddstr(23, 0, "Press any key to exit."); + 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; From d2e2489715be4b27b73d388912219e593923a969 Mon Sep 17 00:00:00 2001 From: woosh <> Date: Mon, 13 Nov 2023 03:02:03 +0000 Subject: [PATCH 4/6] fix mouse movement and prevent moves on completed boards --- uttt.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/uttt.c b/uttt.c index 3f5d80c..8d71d7e 100644 --- a/uttt.c +++ b/uttt.c @@ -77,7 +77,10 @@ int ut_move(struct ut_state *new_state, const struct ut_state *old_state, int ro if (old_state->playBoard != -1 && old_state->playBoard != 3 * (row / 3) + (col / 3)) {return 1;} // bad move - tile is occupied - if(old_state->tiles[row][col] != '\0') {return 1;} // replace with ' ' maybe + if(old_state->tiles[row][col] != '\0') {return 1;} + + // bad move - board is finished + if(old_state->boards[row / 3][col / 3] != '\0') {return 1;} // copy old_state->{tiles,boards} to new_state->{tiles,boards} memmove(new_state->tiles, old_state->tiles, sizeof(old_state->tiles)); @@ -164,13 +167,10 @@ int ut_click(const struct ut_state *state, int *r, int *c) { if(event.y < 0 || event.y >= 21) {break;} if(event.x < 0 || event.x >= 21) {break;} - *r = event.y % 7 - 1; // this messes up cursor position - *c = event.x % 7 - 1; - if(*r % 2 != 0) {break;} - if(*c % 2 != 0) {break;} - *r /= 2; *c /= 2; - *r += 3 * (event.y / 7); - *c += 3 * (event.x / 7); + *r = (event.y % 7 - 1) / 2 + 3 * (event.y / 7); + *c = (event.x % 7 - 1) / 2 + 3 * (event.x / 7); + if(((event.y % 7) - 1) % 2 != 0) {break;} + if(((event.x % 7) - 1) % 2 != 0) {break;} return 0; } break; From 2805d5e46c74f54d68047f3c3e0170417e2c02f1 Mon Sep 17 00:00:00 2001 From: woosh <> Date: Mon, 13 Nov 2023 05:01:26 +0000 Subject: [PATCH 5/6] line it up --- uttt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uttt.c b/uttt.c index 8d71d7e..05ee77c 100644 --- a/uttt.c +++ b/uttt.c @@ -218,7 +218,7 @@ int ut_click(const struct ut_state *state, int *r, int *c) case '\r': /* FALLTHROUGH */ case KEY_ENTER: return 0; - case ERR: /* FALLTHROUGH */ + case ERR: /* FALLTHROUGH */ default: break; } From f0bf95189beb27cecf956e45b21c72d1ba17dfb6 Mon Sep 17 00:00:00 2001 From: woosh <> Date: Mon, 13 Nov 2023 06:37:05 +0000 Subject: [PATCH 6/6] fix ninya moment --- uttt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uttt.c b/uttt.c index 05ee77c..1326866 100644 --- a/uttt.c +++ b/uttt.c @@ -304,7 +304,7 @@ void finish(int sig) exit(0); } -int main(int *argc, char **argv) { +int main(int argc, char *argv[]) { signal(SIGINT, finish); initscr(); keypad(stdscr, TRUE);