aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2022-12-22 22:43:44 +0200
committerkartofen <mladenovnasko0@gmail.com>2022-12-22 22:43:44 +0200
commit764070a86a7aa98480eaaff64dfba7e2f2943292 (patch)
tree830589ac702d540bfd76cfb0e5faa5e8988432b0
parent4c9fafc4c126af2466dc6c56b9c952f901a1c726 (diff)
refactor
-rwxr-xr-xbuild.sh30
-rwxr-xr-xdownload-tilesets.sh12
-rwxr-xr-xfiles-ppmtopng.sh9
-rwxr-xr-xppmtopng.sh14
-rw-r--r--src/gen_tiles.c26
-rw-r--r--src/main.c148
-rw-r--r--src/tilemap.c59
-rw-r--r--src/tilemap.h8
-rw-r--r--src/tiles.c76
-rw-r--r--src/tiles.h11
-rw-r--r--src/typedef.h2
-rw-r--r--src/wfc.c159
-rw-r--r--src/wfc.h18
13 files changed, 327 insertions, 245 deletions
diff --git a/build.sh b/build.sh
index a93e242..2295b55 100755
--- a/build.sh
+++ b/build.sh
@@ -2,12 +2,11 @@
cd ${0%/*} # go to project root
-FLAGS="-Wall -Wextra -g -pedantic"
+FLAGS="-std=c99 -Wall -Wextra -g -pedantic"
SRCD="src"
ODIR="obj"
BIN="bin"
FILES="files"
-VALGRND=""
RUN=0
function __run__ {
@@ -23,27 +22,38 @@ function __clean__ {
rm -rf $BIN
rm -rf $ODIR
rm -rf $FILES
- kill $( ps -q $$ -o pgid= ) # exit
+ exit 0
+}
+
+function __setup__ {
+ ./download-tilesets.sh $FILES
+ exit 0
+}
+
+function __topng__ {
+ ./ppmtopng.sh $FILES
+ exit 0
}
set -xe
+mkdir -p $BIN
+mkdir -p $ODIR
+mkdir -p $FILES
+
if ! { [[ $# -eq 0 ]]; } 2> /dev/null
then
__$1__
fi
-mkdir -p $BIN
-mkdir -p $ODIR
-mkdir -p $FILES
-
-gcc -c $SRCD/gen_tiles.c -o $ODIR/gen_tiles.o $FLAGS -DPATH=files/tilesets
+gcc -c $SRCD/gen_tiles.c -o $ODIR/gen_tiles.o $FLAGS -DPATH=$FILES
gcc -c $SRCD/ppm.c -o $ODIR/ppm.o $FLAGS
gcc -c $SRCD/tilemap.c -o $ODIR/tilemap.o $FLAGS
-gcc -c $SRCD/tiles.c -o $ODIR/tiles.o $FLAGS
+gcc -c $SRCD/tiles.c -o $ODIR/tiles.o $FLAGS -DPATH=\"$FILES\"
+gcc -c $SRCD/wfc.c -o $ODIR/wfc.o $FLAGS -DPATH=\"$FILES\"
gcc -c $SRCD/main.c -o $ODIR/main.o $FLAGS
-gcc -o $BIN/wfc $ODIR/main.o $ODIR/ppm.o $ODIR/tiles.o $ODIR/tilemap.o $FLAGS
+gcc -o $BIN/wfc $ODIR/main.o $ODIR/wfc.o $ODIR/tiles.o $ODIR/tilemap.o $ODIR/ppm.o $FLAGS
gcc -o $BIN/gen_tiles $ODIR/gen_tiles.o $FLAGS
if ! { [[ $RUN -eq 0 ]]; } 2> /dev/null
diff --git a/download-tilesets.sh b/download-tilesets.sh
index f6e477b..a97031b 100755
--- a/download-tilesets.sh
+++ b/download-tilesets.sh
@@ -2,14 +2,18 @@
cd ${0%/*} # go to project root
+if [ $# -eq 0 ]; then
+ echo "Please provide the path"
+ exit 1
+fi
+
URL="https://ftp.batnako.net/tilesets"
+FILES=$1
-mkdir -p "files"
-mkdir -p "files/tilesets"
+mkdir -p "$FILES/tilesets"
function download {
- path="files/tilesets/$name"
-
+ path="$FILES/tilesets/$name"
rm -rf "$path"
mkdir "$path"
diff --git a/files-ppmtopng.sh b/files-ppmtopng.sh
deleted file mode 100755
index df33236..0000000
--- a/files-ppmtopng.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-cd ${0%/*} # go to project root
-set -xe
-
-for i in files/file*.ppm
-do
- pnmtopng "$i" >> "${i%.*}.png"
-done
diff --git a/ppmtopng.sh b/ppmtopng.sh
new file mode 100755
index 0000000..f73dcd1
--- /dev/null
+++ b/ppmtopng.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+cd ${0%/*} # go to project root
+
+if [ $# -eq 0 ]; then
+ echo "Please provide the path"
+ exit 1
+fi
+
+set -xe
+
+for i in $1/file*.ppm; do
+ pnmtopng "$i" >> "${i/ppm/png}"
+done
diff --git a/src/gen_tiles.c b/src/gen_tiles.c
index 5d6cba3..22b385f 100644
--- a/src/gen_tiles.c
+++ b/src/gen_tiles.c
@@ -1,40 +1,42 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
#include "typedef.h"
+#define TILESET_NAME (STR(TILESET))
+
typedef struct tile {
char name[64];
char symetry;
small_t connections[SIDES_MAX];
} tile;
-#include "config.h"
#define STR_AUX(a) #a
#define STR(a) STR_AUX(a)
-#define TILESET_PATH(name) STR(../PATH/name/tileset.h)
-// include the tileset header configuration
+#define TILESET_PATH(name) STR(../PATH/tilesets/name/tileset.h)
+
+#include "config.h"
#include TILESET_PATH(TILESET)
-#define TILESET_NAME STR(TILESET)
+#define MKDIR_FILES_SLASH_TILES STR(mkdir PATH/tiles)
+#define TILES_DOT_DAT STR(PATH/tiles/tiles.dat)
+#define COMMAND STR(cp PATH/tilesets/%s/%s.ppm PATH/tiles/tile_%d.ppm)
void copy(char *tile_set, char *name, int n)
{
char command[512];
- sprintf(command, "cp files/tilesets/%s/%s.ppm files/tiles/tile_%d.ppm",
+ sprintf(command, COMMAND,
tile_set, name, n);
system(command);
}
void gen()
{
- system("mkdir files");
- system("mkdir files/tiles");
+ system(MKDIR_FILES_SLASH_TILES);
- FILE *fp = fopen("files/tiles/tiles.dat", "wb");
+ FILE *fp = fopen(TILES_DOT_DAT, "wb");
if(!fp) {
- fprintf(stderr, "ERROR: Could not open file files/tiles/tiles.dat");
+ err("Could not open file: %s", TILES_DOT_DAT);
exit(EXIT_FAILURE);
}
@@ -58,8 +60,8 @@ void gen()
int main(void)
{
- puts("INFO: Generating Tile Data");
+ info("Generating Tile Data");
gen();
- puts("INFO: Successful");
+ info("INFO: Successful");
return 0;
}
diff --git a/src/main.c b/src/main.c
index bba2087..bea3531 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,95 +1,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <time.h>
-#include <unistd.h>
+#include <getopt.h>
#include "typedef.h"
-#include "ppm.h"
-#include "tiles.h"
-#include "tilemap.h"
-
-// amount of different tiles and their rotations
-size_t TILES;
-
-// width and height of a single tile
-size_t TILE_WIDTH;
-size_t TILE_HEIGHT;
-
-// width and height of the tilemap
-// to generate
-size_t SWIDTH = 15;
-size_t SHEIGHT = 15;
-
-time_t SEED;
-size_t 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);
-}
+#include "wfc.h"
void manage_arguments(int argc, char **argv)
{
@@ -99,14 +13,14 @@ void manage_arguments(int argc, char **argv)
switch(opt)
{
case 'd':
- SWIDTH = atoi(strtok(optarg, "x"));
- SHEIGHT = atoi(strtok(NULL, "x"));
+ width = atoll(strtok(optarg, "x"));
+ height = atoll(strtok(NULL, "x"));
break;
case 's':
- SEED = atoi(optarg);
+ SEED = atoll(optarg);
break;
case 'm':
- SCALE = atoi(optarg);
+ SCALE = atoll(optarg);
break;
case 'h':
default:
@@ -128,54 +42,22 @@ void manage_arguments(int argc, char **argv)
int main(int argc, char **argv)
{
- SEED = time(0);
+ default_values();
+
manage_arguments(argc, argv);
srand(SEED);
- info("Starting With:\n\tWidth: %ld\n\tHeight: %ld\n\tSeed: %ld\n\tScale: %ld", SWIDTH, SHEIGHT, SEED, SCALE);
-
- load_tiles();
- info("Tiles Loaded");
- init_tilemap();
- info("Tilemap Initiated");
- generate_tile_masks(get_tile_connections());
- info("Tile Masks Generated");
+ info("Starting With:\n\tWidth: %ld\n\tHeight: %ld\n\tSeed: %ld\n\tScale: %ld", width, height, SEED, SCALE);
- // print_tiles();
- // printf("%ld\n", TILES);
-
- for(int lei = get_least_entropy_index(); !has_collapsed(lei); lei = get_least_entropy_index())
- collapse_this(lei);
+ init_wfc();
+ info("WFC Initialized");
+ wfc();
info("Tilemap Successfully Generated");
- 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);
- }
- }
-
- free_tiles();
- destroy_tilemap();
-
- char file_name[64] = {0};
-
- sprintf(file_name, "files/file_%ld.ppm", SEED);
- save_as_ppm(file_name, image, img_wdt, img_hgt, SCALE);
- info("Saved file with name: %s\n", file_name);
+ save_wfc();
- free(image);
+ deinit_wfc();
+ info("WFC Deinitialized");
return 0;
}
diff --git a/src/tilemap.c b/src/tilemap.c
index df1c1c6..8cb78f9 100644
--- a/src/tilemap.c
+++ b/src/tilemap.c
@@ -7,12 +7,15 @@
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define BIG_SZ (sizeof(big_t) * 8)
-#define INDEX (typeof(n))(n / BIG_SZ)
-#define OFFSET (typeof(n))(n % BIG_SZ)
+#define INDEX ((__typeof(n))(n / BIG_SZ))
+#define OFFSET ((__typeof(n))(n % BIG_SZ))
+// from tiles.c
extern size_t TILES;
-extern size_t SWIDTH;
-extern size_t SHEIGHT;
+extern small_t tile_connections[TILES_CAP][SIDES_MAX];
+
+size_t SWIDTH;
+size_t SHEIGHT;
big_t (*tilemap)[TILEMAP_CAP];
size_t tsz = 0;
@@ -25,6 +28,27 @@ size_t tsz = 0;
// least significant bit is tile index 0
big_t (*tile_masks)[TILES_CAP][SIDES_MAX];
+void generate_tile_masks()
+{
+ tile_masks = malloc(sizeof(big_t[tsz][TILES_CAP][SIDES_MAX]));
+ memset(tile_masks, 0, sizeof(big_t[tsz][TILES_CAP][SIDES_MAX]));
+
+ for(size_t n = 0; n < TILES; n++)
+ {
+ for(size_t j = 0; j < TILES; j++) {
+ for(size_t i = 0; i < SIDES; i++) {
+ // current solution for circuits :(
+ // if(n == j && (n == 3 || n == 4 || n == 5 || n ==6))
+ // tile_masks[INDEX][j][i] |= (tc[n][3-i] != tc[j][i]) << OFFSET;
+ // else if(n == j && (n == 7|| n == 8 || n == 9 || n == 10))
+ // tile_masks[INDEX][j][i] |= 0 << OFFSET;
+ // else
+ tile_masks[INDEX][j][i] |= (tile_connections[n][3-i] == tile_connections[j][i]) << OFFSET;
+ }
+ }
+ }
+}
+
void set(int t, int n)
{
tilemap[INDEX][t] |= ((big_t)1 << OFFSET);
@@ -35,8 +59,11 @@ int is_set(int t, int n)
return (tilemap[INDEX][t] >> OFFSET) & 1;
}
-void init_tilemap()
+void init_tilemap(size_t width, size_t height)
{
+ SWIDTH = width;
+ SHEIGHT = height;
+
tsz = (TILES/BIG_SZ) + 1;
tilemap = malloc(sizeof(big_t[tsz][TILEMAP_CAP]));
@@ -44,6 +71,8 @@ void init_tilemap()
for(size_t n = 0; n < SWIDTH * SHEIGHT; n++)
for(size_t i = 0; i < tsz; i++)
tilemap[i][n] = (((big_t)1 << MIN(BIG_SZ, (TILES - (i*BIG_SZ)))) - 1);
+
+ generate_tile_masks();
}
void destroy_tilemap()
@@ -90,26 +119,6 @@ void mask(int t, int m, int r)
tilemap[i][t] &= tile_masks[i][m][r];
}
-void generate_tile_masks(small_t (*tc)[SIDES_MAX])
-{
- tile_masks = malloc(sizeof(big_t[tsz][TILES_CAP][SIDES_MAX]));
- memset(tile_masks, 0, sizeof(big_t[tsz][TILES_CAP][SIDES_MAX]));
-
- for(size_t n = 0; n < TILES; n++)
- {
- for(size_t j = 0; j < TILES; j++) {
- for(size_t i = 0; i < SIDES; i++) {
- // current solution for circuits :(
- // if(n == j && (n == 3 || n == 4 || n == 5 || n ==6))
- // tile_masks[INDEX][j][i] |= (tc[n][3-i] != tc[j][i]) << OFFSET;
- // else if(n == j && (n == 7|| n == 8 || n == 9 || n == 10))
- // tile_masks[INDEX][j][i] |= 0 << OFFSET;
- // else
- tile_masks[INDEX][j][i] |= (tc[n][3-i] == tc[j][i]) << OFFSET;
- }
- }
- }
-}
// void print_tilemap()
// {
// printf("tsz: %ld\n", tsz);
diff --git a/src/tilemap.h b/src/tilemap.h
index 533c3d5..a8154e1 100644
--- a/src/tilemap.h
+++ b/src/tilemap.h
@@ -1,6 +1,9 @@
#ifndef TILEMAP_H
#define TILEMAP_H
+extern size_t SWIDTH;
+extern size_t SHEIGHT;
+
// set bit n in tile t in tilemap
void set(int t, int n);
// is bit n set in tile t in tilemap
@@ -15,10 +18,11 @@ size_t count_entropy(int t);
void init_tilemap();
void destroy_tilemap();
-void generate_tile_masks(small_t (*tile_connections)[SIDES_MAX]);
-
// applly a mask m, r (from tile_masks)
// to tile t in tilemap
void mask(int t, int m, int r);
+void print_tilemap();
+
+
#endif
diff --git a/src/tiles.c b/src/tiles.c
index 0c31c05..61fa98f 100644
--- a/src/tiles.c
+++ b/src/tiles.c
@@ -4,12 +4,10 @@
#include "tiles.h"
#include "ppm.h"
-extern size_t TILES;
+size_t TILES;
+size_t TILE_WIDTH;
+size_t TILE_HEIGHT;
-extern size_t TILE_WIDTH;
-extern size_t TILE_HEIGHT;
-
-small_t DIMENTIONS = 0;
small_t *(tiles[TILES_CAP]);
small_t tile_connections[TILES_CAP][SIDES_MAX];
@@ -46,43 +44,29 @@ static void rotate_connections(small_t (*tc)[SIDES_MAX], int i, int n, int r)
tile_connections[n][y*2 + x] = tc[i][rotate(x, y, r, 2)];
}
-static void load_tile_data(small_t (*tc)[SIDES_MAX], char *ts, size_t *tid)
-{
- char file_path[32] = "files/tiles/tiles.dat";
- FILE *fp = fopen(file_path, "rb");
- if(!fp) {
- err("Could not open file: %s\n", file_path);
- exit(EXIT_FAILURE);
- }
-
- fread(&DIMENTIONS, sizeof(DIMENTIONS), 1, fp);
- fread(tid, sizeof(size_t), 1, fp);
-
- for(size_t i = 0; i < *tid; i++) {
- fread(tc[i], sizeof(small_t), SIDES, fp);
- fread(&(ts[i]), sizeof(char), 1, fp);
- }
-
- fclose(fp);
-}
-
-void load_tiles()
+void load_tiles(FILE *fp)
{
size_t tid = 0;
small_t tile_con[TILES_CAP][SIDES_MAX] = {0};
char tile_sym[TILES_CAP];
- load_tile_data(tile_con, tile_sym, &tid);
+ fread(&tid, sizeof(size_t), 1, fp);
if(tid == 0) {
- fprintf(stderr, "ERROR: No tiles could be loaded\n");
+ err("Tiles could not be loaded");
exit(EXIT_FAILURE);
}
+ for(size_t i = 0; i < tid; i++) {
+ fread(tile_con[i], sizeof(small_t), SIDES, fp);
+ fread(&(tile_sym[i]), sizeof(char), 1, fp);
+ }
+
+
size_t n = 0;
for(size_t i = 0; i < tid; i++, n++)
{
char file_path[128];
- sprintf(file_path, "files/tiles/tile_%ld.ppm", i);
+ sprintf(file_path, "%s/tiles/tile_%ld.ppm", PATH, i);
char *t = load_from_ppm(file_path, &TILE_WIDTH, &TILE_HEIGHT);
switch(tile_sym[i])
@@ -134,23 +118,23 @@ void free_tiles()
free(tiles[i]);
}
-void print_tiles()
-{
- for(size_t i = 0; i < TILES; i++)
- {
- printf("Tile: %ld\n", i);
- for(int n = 0; n < 4; n++) {
- printf("%d", tile_connections[i][n]);
- } printf("\n");
- for(size_t y = 0; y < TILE_HEIGHT; y++)
- {
- for(size_t x = 0; x < TILE_WIDTH; x++)
- putchar((tiles[i][(y * TILE_WIDTH + x)*3 + 0]) == 0 ? '#' : '.');
- putchar('\n');
- }
- putchar('\n');
- }
-}
+// void print_tiles()
+// {
+// for(size_t i = 0; i < TILES; i++)
+// {
+// printf("Tile: %ld\n", i);
+// for(int n = 0; n < 4; n++) {
+// printf("%d", tile_connections[i][n]);
+// } printf("\n");
+// for(size_t y = 0; y < TILE_HEIGHT; y++)
+// {
+// for(size_t x = 0; x < TILE_WIDTH; x++)
+// putchar((tiles[i][(y * TILE_WIDTH + x)*3 + 0]) == 0 ? '#' : '.');
+// putchar('\n');
+// }
+// putchar('\n');
+// }
+// }
int get_tile_pixel(size_t t, size_t x, size_t y, int k)
{
diff --git a/src/tiles.h b/src/tiles.h
index 6a4a223..ce67ea5 100644
--- a/src/tiles.h
+++ b/src/tiles.h
@@ -1,10 +1,15 @@
#ifndef TILES_H
#define TILES_H
-void load_tiles();
-void free_tiles();
+extern size_t TILES;
+extern size_t TILE_WIDTH;
+extern size_t TILE_HEIGHT;
+
+extern small_t tile_connections[TILES_CAP][SIDES_MAX];
+extern small_t *(tiles[]);
-void print_tiles();
+void load_tiles(FILE *fp);
+void free_tiles();
int get_tile_pixel(size_t t, size_t x, size_t y, int k);
small_t (*get_tile_connections())[SIDES_MAX];
diff --git a/src/typedef.h b/src/typedef.h
index 5dff622..8189240 100644
--- a/src/typedef.h
+++ b/src/typedef.h
@@ -1,7 +1,7 @@
#ifndef TYPEDEF_H
#define TYPEDEF_H
-// useful definitions
+// useful definition
#include <stdint.h>
#include <stddef.h>
typedef unsigned char small_t;
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();
+}
diff --git a/src/wfc.h b/src/wfc.h
new file mode 100644
index 0000000..529b0d5
--- /dev/null
+++ b/src/wfc.h
@@ -0,0 +1,18 @@
+#ifndef WFC_H
+#define WFC_H
+
+extern size_t width;
+extern size_t height;
+
+extern size_t SEED;
+extern size_t SCALE;
+
+void default_values();
+
+void init_wfc();
+void deinit_wfc();
+
+void wfc();
+void save_wfc();
+
+#endif