#include #include #include #include #include "tiles.h" #include "ppm.h" #define TILES_CAP 63 size_t TILES; size_t TILE_WIDTH; size_t TILE_HEIGHT; small_t *(tiles[TILES_CAP]) = {0}; // each bit is if the tile has a connections or not // from most signifact to least it is up, right, left, down small_t tile_connections[TILES_CAP]; // 0 up 1 right // 2 left 3 down // each bit of the numbers is for every tiles // if the tile is a possibility // least significant bit is tile index 0 size_t tile_masks[TILES_CAP][4] = {0}; #define WIDTH_SCALER 100 #define HEIGHT_SCALER 100 size_t tiles_board[WIDTH_SCALER * HEIGHT_SCALER] = {0}; void generate_tile_masks() { size_t wt_con[4] = {0}; size_t no_con[4] = {0}; for(int n = 0; n < 4; n++) { for(size_t i = 0; i < TILES; i++) wt_con[n] |= ((tile_connections[i] >> n) & 1) << i; no_con[n] = (~wt_con[n]) & ((1 << TILES) - 1); } for(size_t i = 0; i < TILES; i++) { for(int n = 0; n < 4; n++) { if((tile_connections[i] >> (3-n)) & 1) tile_masks[i][n] = wt_con[n]; else tile_masks[i][n] = no_con[n]; } } } size_t count_1s(int v) { if(((v >> TILES) & 1) == 1) return TILES+1; v &= (1 << TILES) - 1; size_t c = 0; for (c = 0; v; v >>= 1) c += v & 1; return c; } int get_least_entropy_index() { // array of indexes with the least entropy int least_entpy[WIDTH_SCALER * HEIGHT_SCALER]; size_t least_entpy_sz = 0; for(int i = 0; i < HEIGHT_SCALER; i++) { for (int j = 0; j < WIDTH_SCALER; j++) { int index = i * WIDTH_SCALER + j; if(least_entpy_sz == 0) { least_entpy[least_entpy_sz++] = index; continue; } int b1s = count_1s(tiles_board[index]); int l1s = count_1s(tiles_board[least_entpy[least_entpy_sz-1]]); if(b1s == l1s) { 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 set_index(int i) { int n = 0; if(count_1s(tiles_board[i]) == 0) { fprintf(stderr, "ERROR: No possible tiles for this position: %d\n", i); exit(EXIT_FAILURE); } // this bad do { n = rand() % TILES; if(((tiles_board[i] >> n) & 1) != 1) continue; tiles_board[i] = 0; tiles_board[i] |= (1 << n); tiles_board[i] |= (1 << TILES); } while(((tiles_board[i] >> TILES) & 1) != 1); if(i / WIDTH_SCALER != 0) // up if(count_1s(tiles_board[i-WIDTH_SCALER]) != (TILES + 1)) tiles_board[i-WIDTH_SCALER] &= tile_masks[n][0]; if(i % WIDTH_SCALER != (WIDTH_SCALER - 1)) // right if(count_1s(tiles_board[i+1]) != (TILES + 1)) tiles_board[i+1] &= tile_masks[n][1]; if(i % WIDTH_SCALER != 0) // left if(count_1s(tiles_board[i-1]) != (TILES + 1)) tiles_board[i-1] &= tile_masks[n][2]; if(i / WIDTH_SCALER != (HEIGHT_SCALER - 1)) // down if(count_1s(tiles_board[i+WIDTH_SCALER]) != (TILES + 1)) tiles_board[i+WIDTH_SCALER] &= tile_masks[n][3]; } int main(void) { TILES = calc_tiles(); if(TILES > TILES_CAP) { printf("ERROR: Too many tiles: %ld\n", TILES); exit(EXIT_FAILURE); } time_t seed = time(0); srand(seed); printf("The Seed is %ld\n", seed); load_connections(); generate_tile_masks(); // init tiles board for(int i = 0; i < WIDTH_SCALER * HEIGHT_SCALER; i++) tiles_board[i] = (1 << TILES) - 1; while(1) { int lei; lei = get_least_entropy_index(); if(count_1s(tiles_board[lei]) == TILES+1) break; // every index is set else set_index(lei); } load_tiles(); size_t img_wdt = TILE_WIDTH * WIDTH_SCALER; size_t img_hgt = TILE_HEIGHT * HEIGHT_SCALER; small_t *image = malloc(img_wdt * img_hgt); memset(image, 0, img_wdt * img_hgt); for(size_t i = 0; i < HEIGHT_SCALER; i++) { for(size_t j = 0; j < WIDTH_SCALER; j++) { size_t t; for(t = 0; t < TILES; t++) if(((tiles_board[i * WIDTH_SCALER + j] >> t) & 1) == 1) break; for(size_t y = 0; y < TILE_HEIGHT; y++) { for(size_t x = 0; x < TILE_WIDTH; x++) { image[(y+(i*TILE_HEIGHT)) * img_wdt + (x+(j*TILE_WIDTH))] = tiles[t][y * TILE_WIDTH + x]; } } } } free_tiles(); char file_name[64] = {0}; sprintf(file_name, "files/file_%ld.ppm", seed); save_as_ppm(file_name, image, img_wdt, img_hgt, 10); printf("Saved file with name: %s\n", file_name); free(image); return 0; }