summaryrefslogtreecommitdiff
path: root/src/ui.c
diff options
context:
space:
mode:
authorMario Kilies <MarioKilies@GMX.net>2011-01-13 22:14:28 +0100
committerMario Kilies <MarioKilies@GMX.net>2011-01-13 22:14:28 +0100
commit1cf0350c2bc286e56b3b71d19fb03e080e2e67cf (patch)
tree39b14a08d4bff79ebf5e86fa489e0cad99c5d5f0 /src/ui.c
parentbd75e455a55c6e14c3f6eaf92308f4df0ce3bd2c (diff)
Moved display.[ch] to ui.[ch].
Diffstat (limited to 'src/ui.c')
-rw-r--r--src/ui.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/src/ui.c b/src/ui.c
new file mode 100644
index 0000000..6b80763
--- /dev/null
+++ b/src/ui.c
@@ -0,0 +1,314 @@
+#include "ui.h"
+#include "cardstack.h"
+
+// Definition of ncurses color pair identifiers
+#define CP_WHITE_ON_BLACK 1
+#define CP_YELLOW_ON_BLACK 2
+#define CP_BLUE_ON_BLACK 3
+#define CP_MAGENTA_ON_BLACK 4
+#define CP_RED_ON_BLACK 5
+
+static bool colors = false;
+static WINDOW *w_table_cards;
+static WINDOW *w_stack_points;
+static WINDOW *w_current_state;
+static WINDOW *w_hand_cards;
+
+static void draw_card(WINDOW *w, const uint8_t row, const uint8_t col, const bool highlight, const card c)
+{
+ unsigned color_pair = 0;
+
+ if (highlight)
+ wattron(w, A_BOLD);
+
+ if (colors)
+ {
+ switch (card_get_points(c))
+ {
+ case 7:
+ color_pair = CP_MAGENTA_ON_BLACK;
+ break;
+ case 5:
+ color_pair = CP_RED_ON_BLACK;
+ break;
+ case 3:
+ color_pair = CP_YELLOW_ON_BLACK;
+ break;
+ case 2:
+ color_pair = CP_BLUE_ON_BLACK;
+ break;
+ default:
+ color_pair = CP_WHITE_ON_BLACK;
+ }
+
+ wattron(w, COLOR_PAIR(color_pair));
+ }
+
+ mvwaddch(w, row, col, ACS_ULCORNER); // Upper left corner
+ mvwhline(w, row, col+1, ACS_HLINE, 5); // Upper horizontal line
+ mvwaddch(w, row, col+6, ACS_URCORNER); // Upper right corner
+ mvwvline(w, row+1, col, ACS_VLINE, 3); // Left vertical line
+ mvwvline(w, row+1, col+6, ACS_VLINE, 3); // Right vertical line
+ mvwaddch(w, row+4, col, ACS_LLCORNER); // Lower left corner
+ mvwhline(w, row+4, col+1, ACS_HLINE, 5); // Lower horizontal line
+ mvwaddch(w, row+4, col+6, ACS_LRCORNER); // Lower right corner
+ mvwprintw(w, row+1, col+1, " %3d ", c); // Card number, 3 digits wide, filled with spaces, if number has fewer digits
+
+ // Clear the rest of the card first
+ mvwprintw(w, row+2, col+1, " ");
+ mvwprintw(w, row+3, col+1, " ");
+
+ switch (card_get_points(c))
+ {
+ case 7:
+ // "** **"
+ // " *** "
+ mvwhline(w, row+2, col+1, ACS_DIAMOND, 2);
+ mvwhline(w, row+2, col+4, ACS_DIAMOND, 2);
+ mvwhline(w, row+3, col+2, ACS_DIAMOND, 3);
+ break;
+ case 5:
+ // "* * *"
+ // " * * "
+ mvwaddch(w, row+2, col+1, ACS_DIAMOND);
+ mvwaddch(w, row+2, col+3, ACS_DIAMOND);
+ mvwaddch(w, row+2, col+5, ACS_DIAMOND);
+ mvwaddch(w, row+3, col+2, ACS_DIAMOND);
+ mvwaddch(w, row+3, col+4, ACS_DIAMOND);
+ break;
+ case 3:
+ // " * * "
+ // " * "
+ mvwaddch(w, row+2, col+2, ACS_DIAMOND);
+ mvwaddch(w, row+2, col+4, ACS_DIAMOND);
+ mvwaddch(w, row+3, col+3, ACS_DIAMOND);
+ break;
+ case 2:
+ // " * * "
+ // " "
+ mvwaddch(w, row+2, col+2, ACS_DIAMOND);
+ mvwaddch(w, row+2, col+4, ACS_DIAMOND);
+ break;
+ default:
+ // " * "
+ // " "
+ mvwaddch(w, row+2, col+3, ACS_DIAMOND);
+ }
+
+ if (colors)
+ {
+ wattroff(w, COLOR_PAIR(color_pair));
+ }
+
+ if (highlight)
+ wattroff(w, A_BOLD);
+}
+
+static void draw_cardstack(WINDOW *w, const uint8_t row, const uint8_t col, const bool highlight, const cardstack cs)
+{
+ for (uint8_t i = 0; i < MAX_CARDSTACK_SIZE; i++)
+ {
+ if (cs[i] != 0)
+ {
+ draw_card(w, row, i*2, highlight, cs[i]);
+ }
+ }
+}
+
+/**
+ * Displays the table cards window. Draws table stacks and can highlight a stack.
+ * @param[in] ts The table stacks to display
+ * @param[in] highlight If true, a stack will be highlighted
+ * @param[in] highlighted_stack The stack to highlight. Only used, if highlight is true
+*/
+void ui_display_wnd_table_cards(const tablestacks ts, const bool highlight, const uint8_t highlighted_stack)
+{
+ wattron(w_table_cards, A_BOLD);
+ mvwprintw(w_table_cards, 0, 2, "Table Cards:");
+ wattroff(w_table_cards, A_BOLD);
+
+ for (uint8_t i = 0; i < NUM_TABLESTACKS; i++)
+ {
+ if (highlight)
+ {
+ if (i == highlighted_stack)
+ {
+ draw_cardstack(w_table_cards, 1 + i*5, 0, true, ts[i]);
+ continue;
+ }
+ }
+
+ draw_cardstack(w_table_cards, 1 + i*5, 0, false, ts[i]);
+ }
+
+ wrefresh(w_table_cards);
+}
+
+/**
+ * Displays the stack points window.
+ * @param[in] ts The table stacks used for calculation of stack points
+*/
+void ui_display_wnd_stack_points(const tablestacks ts)
+{
+ wattron(w_stack_points, A_BOLD);
+ mvwprintw(w_stack_points, 0, 0, "Pts:");
+ wattroff(w_stack_points, A_BOLD);
+
+ for (uint8_t i = 0; i < NUM_TABLESTACKS; i++)
+ {
+ mvwprintw(w_stack_points, 3 + i*5, 1, "%2d", cardstack_get_points(ts[i]));
+ }
+
+ wrefresh(w_stack_points);
+}
+
+/**
+ * Displays the current state window, showing all player names and their open cards and the client player's score.
+ * @param[in] pnoc Array of (player name, open card) tuples. Array has to be sorted by open card, lowest open card first
+ * @param[in] num_players The number of players to show a player name and open card for
+ * @param[in] active_players The currently active player
+ * @param[in] score The players score
+*/
+void ui_display_wnd_current_state(const player_name_open_card_tuple pnoc[], const uint8_t num_players, const uint8_t active_player, const uint32_t score)
+{
+ wattron(w_current_state, A_BOLD);
+ mvwprintw(w_current_state, 0, 0, "Current state:");
+ mvwprintw(w_current_state, 0, 22, "Your Score: %3d", score);
+ wattroff(w_current_state, A_BOLD);
+ mvwprintw(w_current_state, 1, 1, "Player Card");
+ mvwprintw(w_current_state, 1, 22, "Player Card");
+ mvwvline(w_current_state, 1, 19, ACS_VLINE, 6); // Vertical line
+
+ for (uint8_t i = 0; i < num_players; i++)
+ {
+ if (i == active_player)
+ wattron(w_current_state, COLOR_PAIR(CP_YELLOW_ON_BLACK));
+
+ if (i < 5)
+ {
+ mvwprintw(w_current_state, 2+i, 1, "%-s", pnoc[i].player_name);
+ mvwprintw(w_current_state, 2+i, 13, "%3d", pnoc[i].open_card);
+ }
+ else
+ {
+ mvwprintw(w_current_state, 2+(i-5), 22, "%-s", pnoc[i].player_name);
+ mvwprintw(w_current_state, 2+(i-5), 34, "%3d", pnoc[i].open_card);
+ }
+
+ if (i == active_player)
+ wattroff(w_current_state, COLOR_PAIR(CP_YELLOW_ON_BLACK));
+ }
+
+ wrefresh(w_current_state);
+}
+
+/**
+ * Displays the hand cards window.
+ * @param[in] h The hand that will be displayed. h must not contain 0
+ * @param[in] highlight If true, a card will be highlighted
+ * @param[in] highlighted_card The card to highlight. Only used, if highlight is true
+*/
+void ui_display_wnd_hand_cards(const hand h, const bool highlight, const uint8_t highlighted_card)
+{
+ wattron(w_hand_cards, A_BOLD);
+ mvwprintw(w_hand_cards, 0, 0, "Hand Cards:");
+ wattroff(w_hand_cards, A_BOLD);
+
+ for (uint8_t i = 0; i < MAX_HAND_CARDS; i++)
+ {
+ if (highlight && i == highlighted_card)
+ {
+ if (i < 5) // Start with the first row of cards
+ draw_card(w_hand_cards, 1, i*8, true, h[i]);
+ else // And then draw the second row
+ draw_card(w_hand_cards, 6, (i-5)*8, true, h[i]);
+ continue;
+ }
+
+ if (i < 5) // Start with the first row of cards
+ draw_card(w_hand_cards, 1, i*8, false, h[i]);
+ else // And then draw the second row
+ draw_card(w_hand_cards, 6, (i-5)*8, false, h[i]);
+ }
+
+ wrefresh(w_hand_cards);
+}
+
+/**
+ * Initializes ncurses.
+*/
+void ui_init(void)
+{
+ initscr(); // Start curses mode
+ if (TRUE == has_colors())
+ {
+ colors = true;
+ start_color();
+
+ init_pair(CP_WHITE_ON_BLACK, COLOR_WHITE, COLOR_BLACK);
+ init_pair(CP_YELLOW_ON_BLACK, COLOR_YELLOW, COLOR_BLACK);
+ init_pair(CP_BLUE_ON_BLACK, COLOR_BLUE, COLOR_BLACK);
+ init_pair(CP_MAGENTA_ON_BLACK, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(CP_RED_ON_BLACK, COLOR_RED, COLOR_BLACK);
+ bkgd(COLOR_PAIR(0));
+ }
+ raw(); // Line buffering disabled
+ keypad(stdscr, true); // We get F1, F2 etc..
+ nodelay(stdscr, true); // Non-blocking input
+ noecho(); // Don't echo() while we do getch
+ curs_set(0); // Make the cursor invisible
+ clear();
+ refresh();
+
+ // Window positions and sizes
+ w_table_cards = newwin(21, 15, 0, 0);
+ w_stack_points = newwin(19, 4, 0, 17);
+ w_current_state = newwin(10, 38, 0, 24);
+ w_hand_cards = newwin(11, 39, 10, 24);
+
+ // Example data set for table cards window
+ const tablestacks ts = {{1, 2, 3, 4, 101}, {6, 7, 53, 0, 0}, {11, 55, 0, 0, 0}, {17, 29, 36, 42, 0}};
+
+ // The stack points window uses ts, too, so there is no separate data set
+
+ // Example data set for hand cards window
+ const hand h = {12, 13, 22, 25, 27, 69, 77, 85, 100, 103};
+
+ // Example data set for current state window
+ const player_name_open_card_tuple pnoc[10] = {
+ {"$you", 10},
+ {"1234567890", 23},
+ {"baz", 38},
+ {"foo_bar", 14},
+ {"lolcat", 60},
+ {"blablub123", 15},
+ {"abcdefg", 103},
+ {"hello", 98},
+ {"hornoxe", 33},
+ {"1337nick", 74}
+ };
+ const uint8_t num_players = 10;
+ const uint32_t score = 10;
+
+ // Draw user interface
+ mvvline(0, 22, ACS_VLINE, 21); // Vertical line
+ refresh();
+ ui_display_wnd_table_cards(ts, true, 1);
+ ui_display_wnd_stack_points(ts);
+ ui_display_wnd_current_state(pnoc, num_players, 2, score);
+ ui_display_wnd_hand_cards(h, true, 8);
+
+ sleep(4);
+}
+
+/**
+ * Finalizes ncurses.
+*/
+void ui_fini(void)
+{
+ delwin(w_table_cards);
+ delwin(w_stack_points);
+ delwin(w_current_state);
+ delwin(w_hand_cards);
+ endwin(); // End curses mode
+}