BackRoomsMaker/src/generation.c

345 lines
8.6 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 ;
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 ;
int* sorted_x ;
int* sorted_y ;
// yes Valentin I learned to use .h the intended way xD
// ------------------------------------------------------------------------ //
bool unpack_coord(uint8_t* lines, int cx, int cy) {
return (bool)((lines[cx]/pw(2, cy))%2);
}
template copy(template src) {
template new ;
new.id = src.id ;
new.eastsig = src.eastsig;
new.westsig = src.westsig;
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 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");
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 8; j++) {
printf("%d ", unpack_coord(configs[config_id].lines, i, j));
};
printf("\n");
};
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) {
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) {
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) {
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) {
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_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) {
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++ ;
}
}
}
};
//printf("generating %d at (%d, %d)...\n", idx, cx, cy);
//print_template(idx);
generate_chunk(cx, cy, idx);
}
void initialize(SDL_Renderer* renderer) {
map = newGrid();
import_letters(renderer);
import_digits(renderer);
full.lines = malloc(sizeof(uint8_t)*8);
full.eastsig = 255 ;
full.westsig = 255 ;
for(int i = 0; i < 8; i++) {
full.lines[i] = 255 ;
};
full.id = -1 ;
empty.lines = malloc(sizeof(uint8_t)*8);
empty.eastsig = 0 ;
empty.westsig = 0 ;
for(int i = 0; i < 8; i++) {
empty.lines[i] = 0 ;
};
empty.id = -2 ;
int xys = pw(2*render_distance+1, 2);
sorted_x = malloc(sizeof(int)*xys);
sorted_y = malloc(sizeof(int)*xys);
int i = 0 ;
for(int w = -render_distance; w <= render_distance; w++) {
for(int h = -render_distance; h <= render_distance; h++) {
sorted_x[i] = w ;
sorted_y[i] = h ;
i += 1;
}
}
for(int k = 0; k < xys-1; k++) {
for(int l = 0; l < xys-1; l++) {
if(abs(sorted_x[l]) + abs(sorted_y[l]) < abs(sorted_x[1+l]) + abs(sorted_y[1+l])) {
int tpx = sorted_x[l];
int tpy = sorted_y[l];
sorted_x[l] = sorted_x[l+1];
sorted_y[l] = sorted_y[l+1];
sorted_x[l+1] = tpx;
sorted_y[l+1] = tpy ;
}
}
}
for(int k = 0; k < xys; k++) {
printf("[%d, %d] -> (%d)\n", sorted_x[k], sorted_y[k], abs(sorted_x[k]) + abs(sorted_y[k]));
}
generate_chunk(0, 0, 2);
}
void destroy() {
freeGrid(map);
free_digits(digits);
free_digits(letters);
free(full.lines);
free(empty.lines);
free(sorted_x);
free(sorted_y);
}
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].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");
for(int k = 0; k < n_conf; k++) {
parse_one(ptr, ptr2, k);
}
}