-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
169 lines (144 loc) · 5.48 KB
/
main.c
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define FACTOR 8
#define SCREEN_WIDTH 32 * FACTOR
#define SCREEN_HEIGHT 16 * FACTOR
uint32_t pixels[SCREEN_WIDTH * SCREEN_HEIGHT];
uint32_t white = 0xFFFFFFFF; // White
uint32_t black = 0x00000000; // Black
int ruleValue = 109;
int parseBase2(char *str) {
int result = 0;
int length = strlen(str); // Get the length of the binary string
for (int i = 0; i < length; i++) {
if (str[i] == '1') {
// Calculate the power of 2 based on the position from the right
int pos = length - i - 1;
result += (1 << (pos));
}
}
return result;
}
uint32_t calculateState(uint32_t past, uint32_t current, uint32_t next) {
char ruleset[9];
for (int i = 0; i < 8; i++) {
ruleset[i] = (ruleValue & (1 << (7 - i))) ? '1' : '0';
}
ruleset[8] = '\0';
char rule[4];
rule[0] = past == white ? '0' : '1';
rule[1] = current == white ? '0' : '1';
rule[2] = next == white ? '0' : '1';
rule[3] = '\0';
int index = 7 - parseBase2(rule);
if (ruleset[index] == '0') {
return white;
} else {
return black;
}
}
uint32_t* calculateList(uint32_t* pixels) {
uint32_t *newpixels = malloc(SCREEN_WIDTH * sizeof(uint32_t));
if (newpixels == NULL) {
// Handle memory allocation failure
printf("Error: Failed to allocate memory\n");
return NULL;
}
// Process all rows
newpixels[0] = calculateState(pixels[SCREEN_WIDTH - 1], pixels[0], pixels[1]);
for (int x = 1; x < SCREEN_WIDTH - 1; x++) {
newpixels[x] = calculateState(pixels[x - 1], pixels[x], pixels[x + 1]);
}
newpixels[SCREEN_WIDTH - 1] = calculateState(pixels[SCREEN_WIDTH - 2], pixels[SCREEN_WIDTH - 1], pixels[0]);
return newpixels;
};
int main(int argc, char** argv){
if(SDL_Init(SDL_INIT_VIDEO) < 0){
printf("Error: SDL failed to initialize\nSDL Error: '%s'\n", SDL_GetError());
return 1;
}
SDL_Window *window = SDL_CreateWindow("Elementary Cellular Automata", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_RESIZABLE);
if(!window){
printf("Error: Failed to open window\nSDL Error: '%s'\n", SDL_GetError());
return 1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if(!renderer){
printf("Error: Failed to create renderer\nSDL Error: '%s'\n", SDL_GetError());
return 1;
}
if (argc >= 2){
// Assume next argument is the rule number
ruleValue = atoi(argv[1]);
}
// ============= Setup ===================
// Fill in pixels
for (int i = 0; i < SCREEN_WIDTH; i++){
pixels[i] = white;
}
pixels[SCREEN_WIDTH / 2] = black;
// ======================================
bool running = true;
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT);
int y = 0;
int finished = 0; // 0 = not finished, 1 = finished
while(running){
SDL_Event event;
while(SDL_PollEvent(&event)){
switch(event.type){
case SDL_QUIT:
running = false;
break;
case SDL_WINDOWEVENT:
if(event.window.event == SDL_WINDOWEVENT_RESIZED){
int newWidth = event.window.data1;
int newHeight = event.window.data2;
// Calculate the new scale based on the resized window dimensions
float scaleX = (float)newWidth / SCREEN_WIDTH;
float scaleY = (float)newHeight / SCREEN_HEIGHT;
// Set the new scale for rendering
SDL_RenderSetScale(renderer, scaleX, scaleY);
}
break;
default:
break;
}
}
if (finished == 1) {
SDL_UpdateTexture(texture, NULL, pixels, SCREEN_WIDTH * sizeof(uint32_t));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
continue;
}
for (int y = 1; y < SCREEN_HEIGHT; y++) { // Start from the second row
uint32_t *previousRow = &pixels[(y - 1) * SCREEN_WIDTH]; // Get the previous row
uint32_t *newRow = calculateList(previousRow); // Calculate the new row based on the previous row
if (newRow != NULL) {
for (int i = 0; i < SCREEN_WIDTH; i++) {
pixels[i + (y * SCREEN_WIDTH)] = newRow[i]; // Update the current row with the new state
}
free(newRow);
// Update the texture once after all rows are processed
SDL_UpdateTexture(texture, NULL, pixels, SCREEN_WIDTH * sizeof(uint32_t));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
SDL_Delay(10);
}
}
if (finished == 0) {
finished = 1;
}
}
// Destroy the texture after the loop if it exists
if (texture) {
SDL_DestroyTexture(texture);
}
SDL_DestroyRenderer(renderer); // Destroy the renderer
SDL_DestroyWindow(window); // Destroy the window
SDL_Quit(); // Quit SDL
return 0;
}