BackRoomsMaker/src/generation.c

372 lines
9.9 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <ncurses.h>
#include <unistd.h>
#include <termios.h>
#include <limits.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "hash.h"
#include "structure.h"
#include "base.h"
#include "generation.h"
// ------------------------------------------------------------------------ //
Grid map ;
int emptyChance = 75 ; // 1 out of this number for empty chunk override
int sizeIncreaseChance = 15 ; // % for an empty chunk to increase in size
template* configs ;
array** matches ;
int n_configs = 18;
int render_distance = 4 ;
int player_x = 4;
int player_y = 4;
int player_cx = 0;
int player_cy = 0;
int zoom = 75 ;
int draw_par = 1;
int __width__ = 1000 ;
int __height__ = 1000 ;
imgs digits ;
imgs letters ;
template full ;
template empty ;
// yes Valentin I learned to use .h the intended way xD
// ------------------------------------------------------------------------ //
bool unpack_coord(uint8_t* lines, int cx, int cy) {
return (bool)((lines[cy]/pw(2, cx))%2);
}
template copy(template src) {
template new ;
new.id = src.id ;
new.eastsig = src.eastsig;
new.westsig = src.westsig;
new.checkCompat = src.checkCompat ;
new.lines = malloc(sizeof(uint8_t)*8);
for(int i = 0; i < 8; i++) {
new.lines[i] = src.lines[i];
};
return new;
}
void generate_chunk(int x, int y, int config_id) {
chunk* new = malloc(sizeof(chunk)) ;
new->chx = x ;
new->chy = y ;
new->draw_id = draw_par - 2;
if(config_id >= 0) {
new->chdata = copy(configs[config_id]);
} else {
new->chdata = copy(full) ;
};
//printf("inserting chunk (%d, %d)[%d]\n", new->chx, new->chy, new->draw_id);
gridInsert(map, x, y, new);
}
void generate_chunk_raw(int x, int y, template tpl) {
chunk* new = malloc(sizeof(chunk)) ;
new->chx = x ;
new->chy = y ;
new->draw_id = draw_par - 2;
new->chdata = copy(tpl);
//printf("%d\n", new->chdata.checkCompat);
gridInsert(map, x, y, new);
}
void print_template(int config_id) {
for(int i = 0; i < 8; i++) {
uint8_t rem = configs[config_id].lines[i];
for(int j = 0; j < 8; j++) {
if(rem%2 == 1) {
printf("X ");
} else {
printf(" ");
};
rem = rem/2 ;
};
printf("(%d)\n", configs[config_id].lines[i]);
};
printf("\n");
}
void rotateTemplateClockWise(int config_id) {
// 1st line become last column ... last line become 1st column
uint8_t* new = malloc(sizeof(uint8_t)*8);
configs[config_id].westsig = configs[config_id].lines[7];
configs[config_id].eastsig = configs[config_id].lines[0];
for(int i = 0; i < 8; i++) {
new[i] = configs[config_id].lines[i];
configs[config_id].lines[i] = 0;
};
for(int i = 0; i < 8; i++) {
uint8_t rem = new[i];
for(int j = 0; j < 8; j++) {
configs[config_id].lines[j] *= 2 ;
configs[config_id].lines[j] += rem%2 ;
rem = rem / 2 ;
}
};
if(config_id >= 9 ) {
//print_template(config_id);
}
free(new);
}
bool is_compat_sig_north(int cx, int cy, int idx) {
chunk* cp = gridGet(map, cx, cy-1);
if(cp == NULL || !cp->chdata.checkCompat) {
return true;
} else {
return cp->chdata.lines[7] == configs[idx].lines[0];
}
}
bool is_compat_sig_south(int cx, int cy, int idx) {
chunk* cp = gridGet(map, cx, cy+1);
if(cp == NULL || !cp->chdata.checkCompat) {
return true;
} else {
return cp->chdata.lines[0] == configs[idx].lines[7];
}
}
bool is_compat_sig_east(int cx, int cy, int idx) {
chunk* cp = gridGet(map, cx+1, cy);
if(cp == NULL || !cp->chdata.checkCompat) {
return true;
} else {
return cp->chdata.westsig == configs[idx].eastsig;
}
}
bool is_compat_sig_west(int cx, int cy, int idx) {
chunk* cp = gridGet(map, cx-1, cy);
if(cp == NULL || !cp->chdata.checkCompat) {
return true;
} else {
return cp->chdata.eastsig == configs[idx].westsig;
}
}
void signature(template t) {
printf("[NORTH] %d\n", t.lines[0]);
printf("[EAST] %d\n", t.eastsig);
printf("[SOUTH] %d\n", t.lines[7]);
printf("[WEST] %d\n\n", t.westsig);
}
bool is_compat_with_spins(int cx, int cy, int idx) {
for(int k = 0; k < 4; k++) {
if(is_compat_sig_north(cx, cy, idx) && is_compat_sig_east(cx, cy, idx) && is_compat_sig_south(cx, cy, idx) && is_compat_sig_west(cx, cy, idx)) {
return true ;
} else {
rotateTemplateClockWise(idx);
}
};
return false;
}
bool is_compat_with_spins_uno(int cx, int cy, int idx) {
if(is_compat_sig_north(cx, cy, idx) && is_compat_sig_east(cx, cy, idx) && is_compat_sig_south(cx, cy, idx) && is_compat_sig_west(cx, cy, idx)) {
return true ;
} else {
rotateTemplateClockWise(idx);
return false;
}
}
void generate_chunk_all(int cx, int cy) {
int i = 1 + (rand()%(4*n_configs));
int idx = 1 ;
int turn = 0 ;
int k = 0 ;
while(i > 0) {
if(turn > 100*n_configs) {
i = 0 ;
idx = 0 ;
printf("failed\n");
} else {
if(is_compat_with_spins_uno(cx, cy, idx)) {
i -= 1;
if(i != 0) {
rotateTemplateClockWise(idx);
if(k == 3) {
idx = (idx+1)%n_configs;
k = 0 ;
} else {
k++ ;
};
}
} else {
if(k == 3) {
idx += 1;
if(idx == n_configs) {
idx = 1;
};
turn += 1;
k = 0 ;
} else {
k++ ;
}
}
}
};
int R = rand()%emptyChance;
if(R != 0) {
generate_chunk(cx, cy, idx);
} else {
generate_chunk_raw(cx, cy, empty);
if(rand()%100 < sizeIncreaseChance) {
if(!(gridMem(map, cx+1, cy) || gridMem(map, cx+1, cy+1) || gridMem(map, cx, cy+1))) {
generate_chunk_raw(cx+1, cy, empty);
generate_chunk_raw(cx, cy+1, empty);
generate_chunk_raw(cx+1, cy+1, empty);
} else if(!(gridMem(map, cx+1, cy) || gridMem(map, cx+1, cy-1) || gridMem(map, cx, cy-1))) {
generate_chunk_raw(cx+1, cy, empty);
generate_chunk_raw(cx, cy-1, empty);
generate_chunk_raw(cx+1, cy-1, empty);
} else if(!(gridMem(map, cx-1, cy) || gridMem(map, cx-1, cy-1) || gridMem(map, cx, cy-1))) {
generate_chunk_raw(cx-1, cy, empty);
generate_chunk_raw(cx, cy-1, empty);
generate_chunk_raw(cx-1, cy-1, empty);
} else if(!(gridMem(map, cx-1, cy) || gridMem(map, cx-1, cy+1) || gridMem(map, cx, cy+1))) {
generate_chunk_raw(cx-1, cy, empty);
generate_chunk_raw(cx, cy+1, empty);
generate_chunk_raw(cx-1, cy+1, empty);
}
}
}
}
void initialize(SDL_Renderer* renderer) {
map = newGrid();
import_letters(renderer);
import_digits(renderer);
full.lines = malloc(sizeof(uint8_t)*8);
full.westsig = 255 ;
full.eastsig = 255 ;
full.checkCompat = false ;
for(int i = 0; i < 8; i++) {
full.lines[i] = 255 ;
};
full.id = -1 ;
empty.lines = malloc(sizeof(uint8_t)*8);
empty.westsig = 0 ;
empty.eastsig = 0 ;
empty.checkCompat = false ;
empty.lines[0] = 0 ;
empty.lines[1] = 0 ;
empty.lines[2] = 0 ;
empty.lines[3] = 24 ;
empty.lines[4] = 24 ;
empty.lines[5] = 0 ;
empty.lines[6] = 0 ;
empty.lines[7] = 0 ;
empty.id = -1 ;
generate_chunk(0, 0, 2);
}
void destroy() {
freeGrid(map);
free_digits(digits);
free_digits(letters);
free(full.lines);
free(empty.lines);
}
void parse_one(FILE* ptr, FILE* ptr2, int index) {
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 8; j++) {
int xres = get_integer_plus_align(ptr, ptr2);
configs[index].lines[i] *= 2 ;
configs[index].lines[i] += xres ;
if(j == 7) {
//configs[index].westsig *= 2;
//configs[index].westsig += xres;
configs[index].westsig += pw(2, i) * xres ;
} else if(j == 0) {
//configs[index].eastsig *= 2;
//configs[index].eastsig += xres;
configs[index].eastsig += pw(2, i) * xres ;
}
}
};
terminate_line(ptr);
terminate_line(ptr2);
printf("-----| Template %d (line %d) |-----\n", index, 9*index);
print_template(index);
printf("sigs : (%d, %d, %d, %d) (N, E, S, W)\n", configs[index].lines[0], configs[index].eastsig, configs[index].lines[7], configs[index].westsig);
printf("\n");
}
void parse_configs(char* filename, int n_conf) {
// Initializing everything //
n_configs = n_conf ;
configs = malloc(sizeof(template)*n_conf);
// data for each template
for(int i = 0; i < n_conf; i++) {
configs[i].id = i;
configs[i].eastsig = 0 ;
configs[i].westsig = 0 ;
configs[i].checkCompat = doCheck ;
configs[i].lines = malloc(sizeof(uint8_t)*8);
for(int j = 0; j < 8; j++) {
configs[i].lines[j] = 0;
}
}
// Now for the fun part //
FILE* ptr = fopen(filename, "r");
FILE* ptr2 = fopen(filename, "r");
// one pointer for data
// one pointer for counting
for(int k = 0; k < n_conf; k++) {
parse_one(ptr, ptr2, k);
}
}
void change_configs(char* new_filename, int n_conf) {
for(int i = 0; i < n_conf; i++) {
free(configs[i].lines);
}
free(configs);
parse_configs(new_filename, n_conf);
}