summaryrefslogtreecommitdiff
path: root/main.c
blob: 9edb8bfae127e435da4f3c7b2f62304f609bfae5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* main.c
 * Created: 2023-08-25
 * Author: Aryadev Chavali
 * Description: Entry point of program
 */
#include <malloc.h>
#include <stdio.h>

#include <raylib.h>
#include <raymath.h>

struct State
{
  // Sandpiles
  unsigned char *data;
  size_t dwidth;

  size_t window_len;
  int multiplier;
};

typedef struct State state_t;

void step(state_t *state)
{
  state->data[((state->dwidth / 2) * state->dwidth) + (state->dwidth / 2)]++;
  for (size_t i = 0; i < state->dwidth; ++i)
    for (size_t j = 0; j < state->dwidth; ++j)
      if (state->data[(i * state->dwidth) + j] >= 4)
      {
        unsigned char *references[] = {
            (j == 0) ? NULL : &state->data[((i)*state->dwidth) + j - 1],
            (i == state->dwidth - 1)
                ? NULL
                : &state->data[((i + 1) * state->dwidth) + j],
            (j == state->dwidth - 1)
                ? NULL
                : &state->data[(i * state->dwidth) + j + 1],
            (i == 0) ? NULL : &state->data[((i - 1) * state->dwidth) + j]};
        for (size_t k = 0; k < 4; ++k)
          if (references[k])
            *references[k] += 1;
        state->data[(i * state->dwidth) + j] = 0;
      }
}

int main(void)
{
  state_t state    = {NULL, 256, 512, 0};
  state.data       = calloc(state.dwidth * state.dwidth, sizeof(*state.data));
  state.multiplier = state.window_len / state.dwidth;

  Camera2D camera = {0};
  camera.zoom     = 1.0f;
  InitWindow(state.window_len, state.window_len, "Abelian sand pile");
  SetTargetFPS(60);
  const float zoom = 0.125f;

  while (!WindowShouldClose())
  {
    step(&state);

    if (IsKeyPressed(KEY_UP) || IsKeyDown(KEY_UP))
    {
      Vector2 centre    = {state.window_len / 2, state.window_len / 2};
      Vector2 world_pos = GetScreenToWorld2D(centre, camera);
      camera.offset     = centre;
      camera.target     = world_pos;
      camera.zoom += zoom;
      if (camera.zoom < zoom)
        camera.zoom = zoom;
    }
    if (IsKeyPressed(KEY_DOWN) || IsKeyDown(KEY_DOWN))
    {
      Vector2 centre    = {state.window_len / 2, state.window_len / 2};
      Vector2 world_pos = GetScreenToWorld2D(centre, camera);
      camera.offset     = centre;
      camera.target     = world_pos;
      camera.zoom -= zoom;
      if (camera.zoom < zoom)
        camera.zoom = zoom;
    }

    if (IsMouseButtonDown(MOUSE_BUTTON_LEFT))
    {
      Vector2 delta = Vector2Scale(GetMouseDelta(), -1.0f / camera.zoom);
      camera.target = Vector2Add(camera.target, delta);
    }

    BeginDrawing();
    ClearBackground(BLACK);
    BeginMode2D(camera);
    for (size_t i = 0; i < state.dwidth; ++i)
      for (size_t j = 0; j < state.dwidth; ++j)
      {
        Color c                = {0};
        unsigned char sandpile = state.data[(i * state.dwidth) + j];
        if (sandpile == 0)
          c = BLACK;
        else if (sandpile == 1)
          c = GREEN;
        else if (sandpile == 2)
          c = PURPLE;
        else if (sandpile == 3)
          c = YELLOW;

        DrawRectangle(i * state.multiplier, j * state.multiplier,
                      state.multiplier, state.multiplier, c);
      }
    EndMode2D();
    EndDrawing();
  }
  CloseWindow();
  return 0;
}