From 630c3d810172fb06ee406cd3a6e57a45673b5886 Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Sat, 9 Apr 2022 07:09:14 -0700 Subject: refactor ncurses code; better status bar --- dartbot.c | 210 ++++++++++++++++++++++++++++---------------------------------- 1 file changed, 93 insertions(+), 117 deletions(-) diff --git a/dartbot.c b/dartbot.c index defd528..c1db96d 100644 --- a/dartbot.c +++ b/dartbot.c @@ -36,24 +36,29 @@ #define GEN_RING_STRING(X, D) #X, #define GEN_RING_OUTER_DIST(X, D) D, -#define FOREACH_COLOUR(M) \ - M(140, 82, 0) \ - M(100, 154, 0) \ - M(60, 226, 0) \ - M(40, 214, 0) \ - M(20, 202, 0) \ - M(0, 196, 0) \ - M(DARTS, 235, 0) \ - M(VISIT, 244, 0) \ - M(PROMPT, 0, 7) -#define GEN_COLOUR_ENUM(X, FG, BG) C_ ## X, -#define GEN_COLOUR_INIT_PAIR(X, FG, BG) init_pair(C_ ## X, FG, BG); +enum ring { + FOREACH_RING(GEN_RING_ENUM) + R_OUT +}; -enum colour { - C_DEFAULT, // need rest to start at 1 - FOREACH_COLOUR(GEN_COLOUR_ENUM) +char *RING_NAMES[] = { + FOREACH_RING(GEN_RING_STRING) + "OUT" }; +double OUTER_DISTS[] = { + FOREACH_RING(GEN_RING_OUTER_DIST) +}; + +double CENTRE_DISTS[sizeof(OUTER_DISTS)/sizeof(*OUTER_DISTS)]; +void init_centre_dists() +{ + CENTRE_DISTS[0] = 0; + for (int i = R_25; i < R_OUT; ++i) + CENTRE_DISTS[i] = (OUTER_DISTS[i] - + ((OUTER_DISTS[i] - OUTER_DISTS[i-1]) / 2)); +} + int SECTORS[] = { 20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, 16, 8, 11, 14, 9, 12, 5 }; #define NUM_SECTORS (sizeof(SECTORS) / sizeof(*SECTORS)) @@ -71,29 +76,31 @@ void init_sectors() } } -enum ring { - FOREACH_RING(GEN_RING_ENUM) - R_OUT -}; - -char *RING_NAMES[] = { - FOREACH_RING(GEN_RING_STRING) - "OUT" -}; +#define FOREACH_COLOUR(M) \ + M(140, 82, 0) \ + M(100, 154, 0) \ + M(60, 226, 0) \ + M(40, 214, 0) \ + M(20, 202, 0) \ + M(0, 196, 0) \ + M(DARTS, 235, 0) \ + M(VISIT, 244, 0) \ + M(PROMPT, 0, 7) +#define GEN_COLOUR_ENUM(X, FG, BG) C_ ## X, +#define GEN_COLOUR_INIT_PAIR(X, FG, BG) init_pair(C_ ## X, FG, BG); -double OUTER_DISTS[] = { - FOREACH_RING(GEN_RING_OUTER_DIST) +enum colour { + C_DEFAULT, // index 0 is reserved for default colours + FOREACH_COLOUR(GEN_COLOUR_ENUM) }; -double CENTRE_DISTS[sizeof(OUTER_DISTS)/sizeof(*OUTER_DISTS)]; -void init_centre_dists() +void init_colours() { - CENTRE_DISTS[0] = 0; - for (int i = R_25; i < R_OUT; ++i) - CENTRE_DISTS[i] = (OUTER_DISTS[i] - - ((OUTER_DISTS[i] - OUTER_DISTS[i-1]) / 2)); + FOREACH_COLOUR(GEN_COLOUR_INIT_PAIR) } +WINDOW *w, *statw; + struct ccoords { double x, y; }; @@ -298,7 +305,7 @@ void leg_free(struct leg *l) free(l); } -void comp_visit(__attribute__((unused)) WINDOW *w, struct leg *l) +void comp_visit(struct leg *l) { struct visit *v = l->visits + l->n_visits++; v->darts = calloc(3, sizeof(*(v->darts))); @@ -330,9 +337,9 @@ void test_match(int start_points) struct leg *l = leg_init(start_points); while(l->rem > 0) - comp_visit(NULL, l); + comp_visit(l); - printf("(%2d) %3d\n", l->n_visits, l->start); + printf("(%2d) %3d\n", 0, l->start); for(int i = 0; i < l->n_visits; ++i) { struct visit *v = l->visits + i; printf("(%2d) %3d %3d", i+1, v->points, v->rem); @@ -348,85 +355,44 @@ void test_match(int start_points) leg_free(l); } -void draw(WINDOW *w, struct leg *l) +void curses_status(char *status) { - werase(w); - box(w, 0, 0); - wmove(w, 0, 2); - waddstr(w, "dartbot"); - - char buf[100]; - int buflen = 0; - - int offset = 2; - int start_visit = (LINES - 3 > l->n_visits) ? 0 : (l->n_visits - (LINES - 3)); - if (start_visit == 0 && LINES - 3 > l->n_visits) { - wmove(w, (offset++)-start_visit, 2); - sprintf(buf, "(%2d) %3d", 0, l->start); - waddstr(w, buf); - } - - for (int i = start_visit; i < l->n_visits; ++i) { - wmove(w, offset+i-start_visit, 2); - struct visit *v = l->visits + i; - - buflen += sprintf(buf, "(%2d) %3d %3d", i+1, v->points, v->rem); - - for (int j = 0; j < v->n_darts; ++j) { - char *n = segment_name(v->darts[j]); - buflen += sprintf(buf + buflen, j == 0 ? " %4s" :" %4s", n); - free(n); - } - - buflen = 0; - waddstr(w, buf); - } - - wrefresh(w); + wmove(statw, 0, 0); + wclrtoeol(statw); + waddstr(statw, status); + wrefresh(statw); } -void user_visit(WINDOW *w, struct leg *l) +void user_visit(struct leg *l) { struct visit *v = l->visits + l->n_visits++; char prompt[] = " Enter points: "; - WINDOW *iw = subwin(w, 1, COLS-2, LINES-2, 1); - wbkgd(iw, COLOR_PAIR(C_PROMPT)); - waddstr(iw, prompt); - touchwin(w); - wrefresh(iw); + curses_status(prompt); char buf[100] = { 0 }; int buflen = 0; int c; - while((c = wgetch(iw)) != 10) { + while((c = wgetch(statw)) != 10) { if (c == 127) { if (buflen > 0) { buf[--buflen] = 0; - wmove(iw, 0, sizeof(prompt) - 1 + buflen); - wclrtoeol(iw); - touchwin(w); - wrefresh(iw); + wmove(statw, 0, sizeof(prompt) - 1 + buflen); + wclrtoeol(statw); + wrefresh(statw); } - } else if (c >= (int)'0' && c <= (int)'9') { + } else if (c >= '0' && c <= '9') { buf[buflen++] = c; - wechochar(iw, c); + wechochar(statw, c); } } - delwin(iw); - v->points = atoi(buf); l->rem -= v->points; v->rem = l->rem; } -void init_colours() -{ - FOREACH_COLOUR(GEN_COLOUR_INIT_PAIR) -} - int points_colour(int points) { if (points >= 180) @@ -447,7 +413,7 @@ int points_colour(int points) return COLOR_PAIR(C_0) | A_BOLD; } -void flushbuf(WINDOW *w, char *buf, int *buflen, int col) +void flushbuf(char *buf, int *buflen, int col) { if (!(*buflen)) return; @@ -458,40 +424,38 @@ void flushbuf(WINDOW *w, char *buf, int *buflen, int col) *buflen = 0; } -void curses_draw(WINDOW *w, struct leg *l1, struct leg *l2) +void curses_draw(struct leg *l1, struct leg *l2) { werase(w); - box(w, 0, 0); - wmove(w, 0, 2); - waddstr(w, "dartbot"); char buf[100]; int buflen = 0; + int wlines = LINES - 3; int n_visits = l1->n_visits > l2->n_visits ? l1->n_visits : l2->n_visits; + int start_visit = (wlines > n_visits) ? 0 : (n_visits - wlines); + int offset = 0; - int offset = 2; - int start_visit = (LINES - 3 > n_visits) ? 0 : (n_visits - (LINES - 3)); - if (start_visit == 0 && LINES - 3 > n_visits) { - wmove(w, (offset++)-start_visit, 2); + if (start_visit == 0 && wlines > n_visits) { + wmove(w, (offset++)-start_visit, 1); buflen = sprintf(buf, "(%2d)", 0); - flushbuf(w, buf, &buflen, COLOR_PAIR(C_VISIT)); + flushbuf(buf, &buflen, COLOR_PAIR(C_VISIT)); buflen = sprintf(buf, " %3d %3d", l1->start, l2->start); - flushbuf(w, buf, &buflen, 0); + flushbuf(buf, &buflen, 0); } for (int i = start_visit; i < n_visits; ++i) { - wmove(w, offset+i-start_visit, 2); + wmove(w, offset+i-start_visit, 1); buflen += sprintf(buf + buflen, "(%2d)", i+1); - flushbuf(w, buf, &buflen, COLOR_PAIR(C_VISIT)); + flushbuf(buf, &buflen, COLOR_PAIR(C_VISIT)); buflen += sprintf(buf + buflen, " "); - flushbuf(w, buf, &buflen, 0); + flushbuf(buf, &buflen, 0); struct visit *v = l1->visits + i; - flushbuf(w, buf, &buflen, 0); + flushbuf(buf, &buflen, 0); buflen += sprintf(buf + buflen, "%3d", v->points); - flushbuf(w, buf, &buflen, points_colour(v->points)); + flushbuf(buf, &buflen, points_colour(v->points)); buflen += sprintf(buf + buflen, " %3d", v->rem); @@ -500,53 +464,65 @@ void curses_draw(WINDOW *w, struct leg *l1, struct leg *l2) buflen += sprintf(buf + buflen, " %3d ", v->rem); - flushbuf(w, buf, &buflen, 0); + flushbuf(buf, &buflen, 0); buflen += sprintf(buf + buflen, "%3d", v->points); - flushbuf(w, buf, &buflen, points_colour(v->points)); + flushbuf(buf, &buflen, points_colour(v->points)); for (int j = 0; j < v->n_darts; ++j) { char *n = segment_name(v->darts[j]); buflen += sprintf(buf + buflen, j == 0 ? " %4s" :" %4s", n); free(n); } - flushbuf(w, buf, &buflen, COLOR_PAIR(C_DARTS)); + flushbuf(buf, &buflen, COLOR_PAIR(C_DARTS)); } - flushbuf(w, buf, &buflen, 0); + flushbuf(buf, &buflen, 0); } wrefresh(w); } -void curses_match(int start_points, void (*f1)(WINDOW *, struct leg *), - void (*f2)(WINDOW *, struct leg *)) +void curses_match(int start_points, void (*f1)(struct leg *), + void (*f2)(struct leg *)) { initscr(); + border(0, 0, 0, 0, 0, 0, 0, 0); + move(0, 2); + addstr("dartbot"); + refresh(); start_color(); init_colours(); curs_set(0); noecho(); - WINDOW *w = newwin(LINES, COLS, 0, 0); + w = newwin(LINES-3, COLS-2, 1, 1); + statw = newwin(1, COLS-2, LINES-2, 1); + wbkgd(statw, COLOR_PAIR(C_PROMPT)); struct leg *l1 = leg_init(start_points); struct leg *l2 = leg_init(start_points); - curses_draw(w, l1, l2); + curses_draw(l1, l2); while (l1->rem > 0 && l2->rem > 0) { - (*f1)(w, l1); - curses_draw(w, l1, l2); + (*f1)(l1); + curses_draw(l1, l2); if (l1->rem > 0) - (*f2)(w, l2); + (*f2)(l2); - curses_draw(w, l1, l2); + curses_draw(l1, l2); } + if (l1->rem <= 0) + curses_status("Player 1 wins."); + else if (l2->rem <= 0) + curses_status("Player 2 wins."); + leg_free(l1); leg_free(l2); wgetch(w); + delwin(statw); delwin(w); endwin(); } -- cgit v1.2.3-70-g09d2