two-player version

development
Thomas Lindner 2023-06-21 22:22:56 +02:00
parent e141053cab
commit fa079d3a5e
2 changed files with 169 additions and 1 deletions

View File

@ -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)

View File

@ -1,5 +1,167 @@
#include <SDL.h>
#include <SDL2_gfxPrimitives.h>
#include <err.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}