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
|
#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();
}
|