HTMLify

ui.c
Views: 16 | Author: abh
#include <ncurses.h>
#include <locale.h>
#include <string.h>
#include "ttt.h"
#include "ui.h"

enum {
    WHITE,
    BLACK,
    RED,
    BLUE,
};

void draw_mark(int pos, char mark) {

    char *o[5] = {
        "▄▀▀▀▄",
        "█   █",
        " ▀▀▀ "
    };

    char *x[5] = {
        "▀▄ ▄▀",
        " ▄▀▄ ",
        "▀   ▀"
    };

    int markx, marky, x_offset, y_offset, i;

    marky = (LINES - 13) / 2;
    markx = (COLS - 25) / 2;

    // y offset 
    switch (pos) {
        case 1: case 2: case 3:
            y_offset = 1; break;
        case 4: case 5: case 6:
            y_offset = 5; break;
        case 7: case 8: case 9:
            y_offset = 9; break;
    }

    // x offset
    switch (pos) {
        case 1: case 4: case 7:
            x_offset = 2; break;
        case 2: case 5: case 8:
            x_offset = 10; break;
        case 3: case 6: case 9:
            x_offset = 18; break;
    }

    attron(COLOR_PAIR(mark == 'o' ? BLUE : RED));
    for (i=0; i<3; i++) {
        move(marky+y_offset+i, markx+x_offset);
        addstr((mark == 'o' ? o : x)[i]);
    }
    attroff(COLOR_PAIR(mark == 'o' ? BLUE : RED));
}

void draw_game(TTT *game) {
    // height = 13
    // width = 25
    int 
        tly = (LINES - 13) / 2,
        tlx = (COLS - 25) / 2,
        i
    ;

    // board
    char *lines[25] = {
        "█▀▀▀▀▀▀▀█▀▀▀▀▀▀▀█▀▀▀▀▀▀▀█",
        "█       █       █       █",
        "█       █       █       █",
        "█       █       █       █",
        "█▀▀▀▀▀▀▀█▀▀▀▀▀▀▀█▀▀▀▀▀▀▀█",
        "█       █       █       █",
        "█       █       █       █",
        "█       █       █       █",
        "█▀▀▀▀▀▀▀█▀▀▀▀▀▀▀█▀▀▀▀▀▀▀█",
        "█       █       █       █",
        "█       █       █       █",
        "█       █       █       █",
        "▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀",
    };

    for (i=0; i<13; i++) {
        move(tly+i, tlx);
        addstr(lines[i]);
    }

    // marks
    for (i=0; i<9; i++) {
        char m = game->state[i];
        if (m == ' ')
            continue;
        draw_mark(i+1, m);
    }

    // player names
    if (game->turn == 1)
        attron(COLOR_PAIR(game->symbols[0] == 'o' ? BLUE : RED));
    mvaddstr(tly-2, tlx, game->player1);
    attroff(COLOR_PAIR(RED));
    attroff(COLOR_PAIR(BLUE));
    
    if (game->turn == 2)
        attron(COLOR_PAIR(game->symbols[1] == 'o' ? BLUE : RED));
    mvaddstr(tly-2, tlx-strlen(game->player2)+25, game->player2);
    attroff(COLOR_PAIR(RED));
    attroff(COLOR_PAIR(BLUE));
}

int detect_pos(int x, int y) {
    int
        tly = (LINES - 13) / 2,
        tlx = (COLS - 25) / 2,
        gx, gy, pos
    ;

    if (tly+0 <= y && y <= tly+3)
        gy = 1;
    if (tly+4 <= y && y <= tly+7)
        gy = 2;
    if (tly+8 <= y && y <= tly+11)
        gy = 3;

    if (tlx+1 <= x && x <= tlx+7)
        gx = 1;
    if (tlx+9 <= x && x <= tlx+15)
        gx = 2;
    if (tlx+17 <= x && x <= tlx+23)
        gx = 3;

    pos = (gy-1) * 3 + gx;

    if (0 < pos && pos < 10)
        return pos;

    return 0;
}

void draw_winner_screen(TTT *game) {
    for (int i=0; i<LINES; i++) {
        for (int j=0; j<COLS; j++) {
            if (i>3 && i<LINES-3 && j>3 && j<COLS-3)
                continue;
            attron(COLOR_PAIR((i+j)%2==1?RED:BLUE));
            mvaddstr(i, j, "█");
            attroff(COLOR_PAIR((i+j)%2==1?RED:BLUE));
        }
    }

    int w = TTT_check_win(game), offset;
    char winner_line[32];
    switch (w) {
        case 0:
            sprintf(winner_line, "Game is Draw [-]"); 
            break;
        case 1:
            sprintf(winner_line, "Winner is: %s [%c]", game->player1, game->symbols[0]);
            break;
        case 2:
            sprintf(winner_line, "Winner is: %s [%c]", game->player2, game->symbols[1]);
            break;
    }

    offset = (COLS - strlen(winner_line))/2;

    mvaddstr(8, offset, winner_line);
}

void ui(TTT *game) {

    MEVENT event;
    int key, mark_pos;
    bool _exit = false;

    setlocale(LC_ALL, "");
    initscr();
    keypad(stdscr, true);
    noecho();
    cbreak();
    curs_set(0);
    mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
    start_color();

    // init_pair(0, COLOR_WHITE, COLOR_BLACK);
    init_pair(WHITE, COLOR_WHITE, COLOR_BLACK);
    init_pair(BLACK, COLOR_BLACK, COLOR_WHITE);
    init_pair(RED, COLOR_RED, COLOR_BLACK);
    init_pair(BLUE, COLOR_BLUE, COLOR_BLACK);

    draw_game(game);
    while (game->running || _exit) { 
        key = getch();
        switch (key) {
            case 'q':
                _exit = true;
                break;
            case KEY_MOUSE:
                if (getmouse(&event) == OK) {
                    if (event.bstate & BUTTON1_CLICKED) {
                        mark_pos = detect_pos(event.x, event.y);
                        if (mark_pos != 0)
                            TTT_mark(game, mark_pos);
                    }
                }
        }
        erase();
        draw_game(game);

        if (strcmp((game->turn == 1 ? game->player1 : game->player2), "-<BOT>-")==0) {
            TTT_bot_turn(game);
            erase();
            draw_game(game);
        }
    }

    draw_winner_screen(game);

    getch();
    endwin();
}

Comments