From fa079d3a5ebb04b36d1f885fb34bdb11d1fc46d5 Mon Sep 17 00:00:00 2001 From: Thomas Lindner Date: Wed, 21 Jun 2023 22:22:56 +0200 Subject: [PATCH] two-player version --- meson.build | 6 ++ src/main.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 169 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index e1d21c6..77cfdda 100644 --- a/meson.build +++ b/meson.build @@ -5,13 +5,19 @@ project('sim', ['c'], 'warning_level=3', 'c_std=c11']) +cc = meson.get_compiler('c') +m_runtime_dep = cc.find_library('m', required : false) + sdl2_runtime_dep = dependency('SDL2', modules : ['SDL2']) +sdl2_gfx_runtime_dep = dependency('SDL2_gfx') sim_exe = executable('sim', sources : [ 'src/main.c', ], dependencies : [ + m_runtime_dep, sdl2_runtime_dep, + sdl2_gfx_runtime_dep, ], install : true) diff --git a/src/main.c b/src/main.c index d76f344..4576ee7 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,167 @@ #include +#include +#include +#include +#include +#include +#include + +#define ECHK(x) \ + do { \ + if (x) { \ + err(1, #x); \ + } \ + } while (0) + +#define ECHK_SDL(x) \ + do { \ + if (x < 0) { \ + errx(1, #x ": %s", SDL_GetError()); \ + } \ + } while (0) + +#define FRAMERATE 20 + +static int selected_edge; +static int active_player = -1; +static int edge_color[15]; + +#define EDGE(i, j) (5 * (i) + (j) - ((i) + 1) * (i) / 2 - 1) + +int loser(void) { + for (int i = 0; i < 6; i++) { + for (int j = i + 1; j < 6; j++) { + for (int k = j + 1; k < 6; k++) { + int a = edge_color[EDGE(i, j)]; + int b = edge_color[EDGE(j, k)]; + int c = edge_color[EDGE(i, k)]; + if (a && a == b && a == c) { + return a; + } + } + } + } + return 0; +} + +void input(SDL_KeyboardEvent *event) { + switch (event->keysym.scancode) { + case SDL_SCANCODE_UP: + if (selected_edge != -1) { + do { + selected_edge = (selected_edge + 1) % 15; + } while (edge_color[selected_edge]); + } + break; + case SDL_SCANCODE_DOWN: + if (selected_edge != -1) { + do { + selected_edge = (selected_edge + 14) % 15; + } while (edge_color[selected_edge]); + } + break; + case SDL_SCANCODE_SPACE: + if (selected_edge != -1) { + edge_color[selected_edge] = active_player; + active_player = -active_player; + if (loser()) { + selected_edge = -1; + } else { + do { + selected_edge = (selected_edge + 1) % 15; + } while (edge_color[selected_edge]); + } + } else { + selected_edge = 0; + memset(edge_color, 0, sizeof(edge_color)); + } + break; + case SDL_SCANCODE_ESCAPE: + case SDL_SCANCODE_Q: + exit(0); + default: + break; + } +} + +void draw(SDL_Renderer *renderer) { + int width, height; + ECHK_SDL(SDL_GetRendererOutputSize(renderer, &width, &height)); + + int unit_length = (width < height ? width : height) / 2; + int x_offset = width / 2; + int y_offset = height / 2; +#define X(x) (x_offset + unit_length * (x)) +#define Y(y) (y_offset + unit_length * (y)) + +#define BLACK 0, 0, 0, 0xff +#define GRAY 0x80, 0x80, 0x80, 0xff +#define SILVER 0xc0, 0xc0, 0xc0, 0xff +#define WHITE 0xff, 0xff, 0xff, 0xff +#define RED 0xff, 0, 0, 0xff +#define GREEN 0, 0xff, 0, 0xff +#define BLUE 0, 0, 0xff, 0xff + + if (selected_edge != -1) { + ECHK_SDL(SDL_SetRenderDrawColor(renderer, BLACK)); + } else { + ECHK_SDL(SDL_SetRenderDrawColor(renderer, RED)); + } + ECHK_SDL(SDL_RenderClear(renderer)); + +#define VERTEX(i) \ + X(0.7 * cosf(2 * M_PI * (i) / 6)), Y(0.7 * sinf(2 * M_PI * (i) / 6)) + + for (int i = 0; i < 6; i++) { + for (int j = i + 1; j < 6; j++) { + if (EDGE(i, j) == selected_edge) { + ECHK_SDL(thickLineRGBA(renderer, VERTEX(i), VERTEX(j), 10, WHITE)); + } else { + switch (edge_color[EDGE(i, j)]) { + case -1: + ECHK_SDL(thickLineRGBA(renderer, VERTEX(i), VERTEX(j), 10, GREEN)); + break; + case 1: + ECHK_SDL(thickLineRGBA(renderer, VERTEX(i), VERTEX(j), 10, BLUE)); + break; + default: + ECHK_SDL(thickLineRGBA(renderer, VERTEX(i), VERTEX(j), 10, GRAY)); + } + } + } + ECHK_SDL(filledCircleRGBA(renderer, VERTEX(i), 30, SILVER)); + } +} + +int main(int argc, char **argv) { + (void)argc, (void)argv; + + ECHK_SDL(SDL_Init(SDL_INIT_EVERYTHING)); + ECHK(atexit(SDL_Quit)); + + SDL_Window *window; + SDL_Renderer *renderer; + ECHK_SDL(SDL_CreateWindowAndRenderer(-1, -1, SDL_WINDOW_FULLSCREEN_DESKTOP, + &window, &renderer)); + SDL_SetWindowTitle(window, "SIM"); + + while (true) { + SDL_Event event; + while (SDL_WaitEventTimeout(&event, 1000 / FRAMERATE)) { + switch (event.type) { + case SDL_QUIT: + exit(0); + case SDL_KEYDOWN: + input(&event.key); + break; + default: + break; + } + } + + draw(renderer); + SDL_RenderPresent(renderer); + } -int main() { return 0; }