#include <stdlib.h>
#include <stdint.h>
#include <math.h>
+
#include "structs.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
FVec2 ** grid;
FVec2 ** grid_prime;
FVec2 ** grid_temp;
+IVec2 grid_size;
float kernel_sum(Mat3 kernel, Mat3 source) {
float result = 0.0f;
float a_prime = 1.0f;
int x_less = (x - 1 < 0) ? x : x - 1;
int y_less = (y - 1 < 0) ? y : y - 1;
- int x_more = (x + 1 == GRID_X) ? x : x + 1;
- int y_more = (y + 1 == GRID_Y) ? y : y + 1;
+ int x_more = (x + 1 == grid_size.x) ? x : x + 1;
+ int y_more = (y + 1 == grid_size.y) ? y : y + 1;
// Use species A in the convolution, b_prime will need B
// For now we won't iterate over edge rows and columns to avoid special case
float b_prime = 1.0f;
int x_less = (x-1 < 0) ? x : x-1;
int y_less = (y-1 < 0) ? y : y-1;
- int x_more = (x+1 == GRID_X) ? x : x+1;
- int y_more = (y+1 == GRID_Y) ? y : y+1;
+ int x_more = (x+1 == grid_size.x) ? x : x+1;
+ int y_more = (y+1 == grid_size.y) ? y : y+1;
// Use species A in the convolution, b_prime will need B
Mat3 source =
for (warg->iterations = 0; warg->iterations < warg->max_iterations; warg->iterations++)
{
printf("worker %d: work unit %d/%d\n", warg->worker_id, warg->iterations, warg->max_iterations);
- for (int x = start_x; x < w + start_x && x < GRID_X; x++)
+ for (int x = start_x; x < w + start_x && x < grid_size.x; x++)
{
- for (int y = start_y; y < h + start_y && y < GRID_Y; y++)
+ for (int y = start_y; y < h + start_y && y < grid_size.y; y++)
{
FVec2 each = grid[x][y];
if (each.c >= 0.5f)
+ {
each.b = 1.0f;
+ each.c -= 5.0f/((float)(opts.max_iterations/100.0f));
+ }
grid_prime[x][y].a = rd_a_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b);
grid_prime[x][y].b = rd_b_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b);
}
grid_prime = grid_temp;
waiting_workers = 0;
printf("worker-boss %d: completing report\n", warg->worker_id);
- if ((warg->iterations % 100 == 0))
- {
- char buffer[GRID_X][GRID_Y];
- for (int x = 0; x < GRID_X; x++)
- {
- for (int y = 0; y < GRID_Y; y++)
- {
- buffer[x][y] = (uint8_t)(255.0f * grid[x][y].a);
- }
- }
- char name[64] = {0};
- sprintf(name, "img/%s/%d.png", opts.name, warg->iterations);
- stbi_write_png(name, GRID_X, GRID_Y, 1, buffer, GRID_X * sizeof(uint8_t));
- }
}
pthread_mutex_unlock(&mutex);
pthread_barrier_wait(&barrier);
int initialize(int worker_count, RD_Opts active_opt)
{
- grid = (FVec2**)malloc(GRID_X * sizeof(FVec2*));
- for (int n = 0; n < GRID_X; n++)
- {
- grid[n] = (FVec2*)malloc(GRID_Y * sizeof(FVec2));
- }
-
- grid_prime = (FVec2**)malloc(GRID_X * sizeof(FVec2*));
- for (int n = 0; n < GRID_X; n++)
+ grid_prime = (FVec2**)malloc(grid_size.x * sizeof(FVec2*));
+ for (int n = 0; n < grid_size.x; n++)
{
- grid_prime[n] = (FVec2*)malloc(GRID_Y * sizeof(FVec2));
+ grid_prime[n] = (FVec2*)malloc(grid_size.y * sizeof(FVec2));
}
srand(time(NULL));
- float radius = GRID_X/2.1f;
- int center_x = GRID_X/2;
- int center_y = GRID_Y/2;
- for (int x = 0; x < GRID_X; x++)
+ float radius = grid_size.x/2.1f;
+ int center_x = grid_size.x/2;
+ int center_y = grid_size.y/2;
+ for (int x = 0; x < grid_size.x; x++)
{
- for (int y = 0; y < GRID_Y; y++)
+ for (int y = 0; y < grid_size.y; y++)
{
grid[x][y].a = 1.0f;
grid[x][y].b = 0.0f;
// Slap in an entrance or something here
// or add support for post-processing
+ if (abs(x-center_x) < 3 && (y <= (5 * (grid_size.y/8))))
+ {
+ grid[x][y].c = 1.0f;
+ }
+
+ if (abs(y-center_y) < 8 && (x <= (6 * (grid_size.x/8))) && (x >= (2 * (grid_size.x/8))))
+ {
+ grid[x][y].c = 1.0f;
+ }
} break;
}
}
}
- const int seed_count = sqrt(GRID_X) * 1;
- const int width = 4 * (GRID_X/128);
+ /* Big seeds good for rooms */
+ const int seed_count = sqrt(grid_size.x) * 2;
+ const int width = 12 * (grid_size.x/128);
const int height = width * 1;
for (int n = 0; n < seed_count; n++)
{
- int rand_x = rand() % GRID_X;
- int rand_y = rand() % GRID_Y;
+ int rand_x = rand() % grid_size.x;
+ int rand_y = rand() % grid_size.y;
grid[rand_x][rand_y].b = 1.0f;
grid[rand_x][rand_y].c = 0.0f;
{
for (int y = rand_y-(height/2); y < rand_y+(height/2); y++)
{
- if (y >= GRID_Y || x >= GRID_X || y < 0 || x < 0)
+ if (y >= grid_size.y || x >= grid_size.x || y < 0 || x < 0)
continue;
// Third parameter for permanent presence of B chemicals (black)
grid[x][y].c = 1.0f;
warg = (worker_arg){
active_opt, grid, grid_prime,
- 0, 0, (GRID_X), (GRID_Y),
+ 0, 0, (grid_size.x), (grid_size.y),
.worker_count = worker_count,
.max_iterations = active_opt.max_iterations
};
{
wargs[t] = warg;
wargs[t].worker_id = t;
- wargs[t].width = (GRID_X/worker_count) + ((t == worker_count-1) ? 0 : 4);
+ wargs[t].width = (grid_size.x/worker_count) + ((t == worker_count-1) ? 0 : 4);
wargs[t].start_x = (wargs[t].width * t);
printf("worker %d x_span %d, %d\n", t, wargs[t].start_x, wargs[t].width);
pthread_create(&threads[t], NULL, iterator, &wargs[t]);
return 0;
}
-int generate_rd(int worker_count, RD_Opts active_opt)
+int generate_rd(int worker_count, RD_Opts active_opt, FVec2 **grid_buffer, IVec2 pgrid_size)
{
+ grid = grid_buffer;
+ grid_size = pgrid_size;
+
initialize(worker_count, active_opt);
while(!should_quit) {}
printf("Opts: {\nIterations: %d\nTime delta: %f\nDiffA: %f\nDiffB: %f\nFeed: %f\nKill: %f\n\n}\n", active_opt.max_iterations, active_opt.delta_t, active_opt.diff_a, active_opt.diff_b, active_opt.feed, active_opt.kill);
+ char buffer[pgrid_size.x][pgrid_size.y];
+ for (int x = 0; x < pgrid_size.x; x++)
+ {
+ for (int y = 0; y < pgrid_size.y; y++)
+ {
+ buffer[x][y] = (uint8_t)(255.0f * grid_buffer[x][y].a);
+ }
+ }
+ char name[64] = {0};
+ sprintf(name, "./%s.png", active_opt.name);
+ stbi_write_png(name, pgrid_size.x, pgrid_size.y, 1, buffer, pgrid_size.x * sizeof(uint8_t));
+
cleanup();
return 0;
}