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