#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 = 30; size_t SHEIGHT = 30; 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) { fprintf(stderr, "ERROR: 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) { if(argc == 1) return; for(int n = 1; n < argc; n++) { char *arg = argv[n]; if((strcmp(arg, "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { puts("Usage: wfc [OPTION] [VALUE(S)]...\n"); puts("The options are the following: (No option is mandatory)\n"); puts("-h, --help Get help"); puts("-d Change width and height of the tilemap, defaut is 30x30"); puts(" args: 2 numbers; width and height seperated by space"); puts("-s Change the seed for generating the tilemap, 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); } else if(strcmp(arg, "-d") == 0) { if(!(n+2 < argc)) goto error; SWIDTH = atoi(argv[++n]); SHEIGHT = atoi(argv[++n]); } else if(strcmp(arg, "-s") == 0) { if(!(n+1 < argc)) goto error; SEED = atoi(argv[++n]); } else if(strcmp(arg, "-m") == 0) { if(!(n+1 < argc)) goto error; SCALE = atoi(argv[++n]); } else goto error; } return; error: fputs("ERROR: An error has accured with the given arguments", stderr); exit(EXIT_FAILURE); } int main(int argc, char **argv) { // SEED = 4; SEED = time(0); manage_arguments(argc, argv); srand(SEED); printf("The Seed is %ld\n", SEED); load_tiles(); init_tilemap(); generate_tile_masks(get_tile_connections()); while(1) { int lei; lei = get_least_entropy_index(); if(has_collapsed(lei)) break; // every index is set else collapse_this(lei); } 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); printf("Saved file with name: %s\n", file_name); free(image); return 0; }