aboutsummaryrefslogtreecommitdiff
path: root/src/wfc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wfc.c')
-rw-r--r--src/wfc.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/wfc.c b/src/wfc.c
new file mode 100644
index 0000000..e12d6de
--- /dev/null
+++ b/src/wfc.c
@@ -0,0 +1,159 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "typedef.h"
+#include "wfc.h"
+#include "tilemap.h"
+#include "tiles.h"
+#include "ppm.h"
+
+small_t DIMENTIONS;
+
+size_t width;
+size_t height;
+
+size_t SEED;
+size_t SCALE;
+
+void default_values()
+{
+ SEED = time(0);
+ width = 15;
+ height = 15;
+ SCALE = 9;
+}
+
+int get_least_entropy_index()
+{
+ // array of indexes with the least entropy
+ size_t least_entpy[TILEMAP_CAP];
+ size_t least_entpy_sz = 0;
+
+ for(size_t i = 0; i < SHEIGHT; i++)
+ {
+ for (size_t j = 0; j < SWIDTH; j++)
+ {
+ size_t index = i * SWIDTH + j;
+
+ if(least_entpy_sz == 0) {
+ least_entpy[least_entpy_sz++] = index;
+ continue;
+ }
+
+ size_t b1s = count_entropy(index);
+ size_t l1s = count_entropy(least_entpy[least_entpy_sz-1]);
+
+ if(b1s == l1s) {
+ if(least_entpy_sz >= TILEMAP_CAP) exit(69);
+ least_entpy[least_entpy_sz++] = index;
+ } else if(b1s < l1s) {
+ least_entpy[0] = index;
+ least_entpy_sz = 1;
+ }
+ }
+ }
+
+ return least_entpy[rand() % least_entpy_sz];
+
+}
+
+void collapse_this(int i)
+{
+ if(count_entropy(i) == 0) {
+ err("No possible tiles for this position: %d\n", i);
+ exit(EXIT_FAILURE);
+ }
+
+ small_t possibilities[TILES];
+ size_t psz = 0;
+
+ for(size_t n = 0; n < TILES; n++)
+ if(is_set(i, n)) possibilities[psz++] = n;
+
+ size_t t = possibilities[rand() % psz];
+ collapse(i, t); // collapse a random tile
+
+ // apply a bitmask, on tiles around the newly collapsed tile
+ if(i / SWIDTH != 0) // up
+ if(!(has_collapsed(i-SWIDTH)))
+ mask(i-SWIDTH, t, 0);
+
+ if(i % SWIDTH != (SWIDTH - 1)) // right
+ if(!(has_collapsed(i+1)))
+ mask(i+1, t, 1);
+
+ if(i % SWIDTH != 0) // left
+ if(!(has_collapsed(i-1)))
+ mask(i-1, t, 2);
+
+ if(i / SWIDTH != (SHEIGHT - 1)) // down
+ if(!(has_collapsed(i+SWIDTH)))
+ mask(i+SWIDTH, t, 3);
+}
+
+void wfc()
+{
+ for(int lei = get_least_entropy_index(); !has_collapsed(lei); lei = get_least_entropy_index())
+ collapse_this(lei);
+}
+
+void save_wfc()
+{
+ size_t img_wdt = TILE_WIDTH * SWIDTH;
+ size_t img_hgt = TILE_HEIGHT * SHEIGHT;
+ small_t *image = malloc(img_wdt * img_hgt * 3);
+
+ for(size_t i = 0; i < SHEIGHT; i++)
+ {
+ for(size_t j = 0; j < SWIDTH; j++)
+ {
+ size_t t = get_collapsed_tile((i * SWIDTH) + j);
+
+ for(size_t y = 0; y < TILE_HEIGHT; y++)
+ for(size_t x = 0; x < TILE_WIDTH; x++)
+ for(int k = 0; k < 3; k++)
+ image[((y+(i*TILE_HEIGHT))*img_wdt+
+ (x+(j*TILE_WIDTH)))*3 + k] =
+ get_tile_pixel(t, x, y, k);
+ }
+ }
+
+
+
+ char file_name[128] = {0};
+ sprintf(file_name, "%s/file_%ld.ppm", PATH, SEED);
+
+ save_as_ppm(file_name, image, img_wdt, img_hgt, SCALE);
+ info("Saved file with name: %s", file_name);
+
+ free(image);
+}
+
+void init_wfc()
+{
+ FILE *fp = fopen("files/tiles/tiles.dat", "rb");
+ if(!fp) {
+ err("Could not open file: %s\n", "files/tiles/tiles.dat");
+ exit(EXIT_FAILURE);
+ }
+
+ fread(&DIMENTIONS, sizeof(DIMENTIONS), 1, fp);
+
+ load_tiles(fp);
+ info("Tiles Loaded");
+
+ //load_rules(fp);
+ //info("Tile Rules Loaded");
+
+ fclose(fp);
+
+ init_tilemap(width, height);
+ info("Tilemap Initialized");
+}
+
+
+void deinit_wfc()
+{
+ free_tiles();
+ destroy_tilemap();
+}