345 lines
8.6 KiB
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);
|
|
}
|
|
} |