#include #include #include #include #include #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); } void manage_arguments(int argc, char **argv) { int opt; while((opt = getopt(argc, argv, "hd:s:m:")) != -1) { switch(opt) { case 'd': SWIDTH = atoi(strtok(optarg, "x")); SHEIGHT = atoi(strtok(NULL, "x")); break; case 's': SEED = atoi(optarg); break; case 'm': SCALE = atoi(optarg); break; case 'h': default: puts("Usage: wfc [OPTION] [VALUE(S)]...\n"); puts("The options are the following: (No option is mandatory)"); puts("-h Get help"); puts("-d Change width and height of the tilemap, defaut is 30x30"); puts(" args: 2 numbers; width and height seperated by an 'x'"); puts("-s Change the seed, default is time(0)"); puts(" args: 1 number; the seed"); puts("-m Change the number, that the tilemap is scaled by"); puts(" args: 1 number; scaler"); exit(EXIT_SUCCESS); break; } } } int main(int argc, char **argv) { SEED = time(0); 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"); // print_tiles(); // printf("%ld\n", TILES); for(int lei = get_least_entropy_index(); !has_collapsed(lei); lei = get_least_entropy_index()) collapse_this(lei); 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); free(image); return 0; }