498 lines
16 KiB
C
498 lines
16 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
#include <limits.h>
|
|
#include <time.h>
|
|
|
|
#include "hash.h"
|
|
#include "structure.h"
|
|
#include "base.h"
|
|
#include "entities.h"
|
|
#include "generation.h"
|
|
|
|
hashtbl visited ;
|
|
room* current_room ;
|
|
|
|
int player_chx ;
|
|
int player_chy ;
|
|
|
|
entry* pool ;
|
|
int pool_size ;
|
|
int total_weight ;
|
|
|
|
int coins ;
|
|
int fct_entry_size ;
|
|
|
|
fct_entry* hashtbl_entities ;
|
|
|
|
void init_ent_generator(int n) {
|
|
hashtbl_entities = malloc(sizeof(fct_entry)*n);
|
|
fct_entry_size = n;
|
|
for(int k = 0; k < 10; k++) {
|
|
hashtbl_entities[k].id = (-1) ;
|
|
}
|
|
|
|
hashtbl_entities[0].id = 0;
|
|
hashtbl_entities[0].name = "Coin"; // 0 = default
|
|
hashtbl_entities[0].updatePos = &speen2 ;
|
|
hashtbl_entities[0].onHit = &detectHit ;
|
|
hashtbl_entities[0].onDeath = NULL ;
|
|
|
|
hashtbl_entities[1].id = 1;
|
|
hashtbl_entities[1].name = "ExplosiveStill";
|
|
hashtbl_entities[1].updatePos = &speen2 ;
|
|
hashtbl_entities[1].onHit = &explodeOnHit ;
|
|
hashtbl_entities[1].onDeath = NULL ;
|
|
|
|
hashtbl_entities[2].id = 2;
|
|
hashtbl_entities[2].name = "ExplosiveSeek";
|
|
hashtbl_entities[2].updatePos = &go_to_player ;
|
|
hashtbl_entities[2].onHit = &explodeOnHit ;
|
|
hashtbl_entities[2].onDeath = NULL ;
|
|
|
|
hashtbl_entities[3].id = 3;
|
|
hashtbl_entities[3].name = "ExplosiveShoot";
|
|
hashtbl_entities[3].updatePos = &speen3 ;
|
|
hashtbl_entities[3].onHit = &explodeOnHit ;
|
|
hashtbl_entities[3].onDeath = NULL ;
|
|
}
|
|
|
|
fct_entry* get_entry(int k0) {
|
|
for(int k = 0; k < fct_entry_size; k++) {
|
|
if(hashtbl_entities[k].id == k0) {
|
|
return &(hashtbl_entities[k]);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void copy_room(room* src, room* dest, int chx, int chy) {
|
|
// considering dest has already been malloc'd
|
|
dest->chunk_x = chx ;
|
|
dest->chunk_y = chy ;
|
|
dest->map = malloc(sizeof(cube_0*)*src->map_size);
|
|
for(int k = 0; k < src->map_size; k++) {
|
|
dest->map[k] = create_cube_0(
|
|
src->map[k]->x, src->map[k]->y, src->map[k]->z,
|
|
src->map[k]->w, src->map[k]->h, src->map[k]->d,
|
|
src->map[k]->hz_angle, src->map[k]->vt_angle, src->map[k]->red, src->map[k]->green, src->map[k]->blue
|
|
);
|
|
}
|
|
dest->map_size = src->map_size ;
|
|
dest->tps = malloc(sizeof(teleporter*)*src->tps_size);
|
|
for(int k = 0; k < src->tps_size; k++) {
|
|
dest->tps[k] = malloc(sizeof(teleporter));
|
|
dest->tps[k]->hitbox = create_cube_0(
|
|
src->tps[k]->hitbox->x, src->tps[k]->hitbox->y, src->tps[k]->hitbox->z,
|
|
src->tps[k]->hitbox->w, src->tps[k]->hitbox->h, src->tps[k]->hitbox->d,
|
|
src->tps[k]->hitbox->hz_angle, src->tps[k]->hitbox->vt_angle, src->tps[k]->hitbox->red, src->tps[k]->hitbox->green, src->tps[k]->hitbox->blue
|
|
);
|
|
dest->tps[k]->dest_chx = src->tps[k]->dest_chx + chx;
|
|
dest->tps[k]->dest_chy = src->tps[k]->dest_chy + chy;
|
|
dest->tps[k]->dest_x = src->tps[k]->dest_x ;
|
|
dest->tps[k]->dest_y = src->tps[k]->dest_y ;
|
|
dest->tps[k]->dest_z = src->tps[k]->dest_z ;
|
|
}
|
|
dest->ents = malloc(sizeof(entity)*src->ent_memlen);
|
|
dest->ent_memlen = src->ent_memlen ;
|
|
dest->ent_len = src->ent_len ;
|
|
for(int k = 0; k < src->ent_len; k++) {
|
|
dest->ents[k].damage = src->ents[k].damage ;
|
|
dest->ents[k].hitpoints = malloc(sizeof(int));
|
|
*(dest->ents[k].hitpoints) = *(src->ents[k].hitpoints) ;
|
|
dest->ents[k].pos = create_cube_0(
|
|
(*(src->ents[k].pos)).x, (*(src->ents[k].pos)).y, (*(src->ents[k].pos)).z,
|
|
(*(src->ents[k].pos)).w, (*(src->ents[k].pos)).h, (*(src->ents[k].pos)).d,
|
|
(*(src->ents[k].pos)).hz_angle, (*(src->ents[k].pos)).vt_angle, (*(src->ents[k].pos)).red, (*(src->ents[k].pos)).green, (*(src->ents[k].pos)).blue
|
|
);
|
|
dest->ents[k].updatePos = src->ents[k].updatePos;
|
|
dest->ents[k].onHit = src->ents[k].onHit;
|
|
dest->ents[k].onDeath = src->ents[k].onDeath;
|
|
}
|
|
dest->tps_size = src->tps_size;
|
|
}
|
|
|
|
void build_starting_chunk(int chx, int chy) {
|
|
room* new = malloc(sizeof(room));
|
|
new->chunk_x = chx ;
|
|
new->chunk_y = chy ;
|
|
new->map = malloc(sizeof(cube_0*)*9);
|
|
new->map_size = 9 ;
|
|
new->tps = malloc(sizeof(teleporter*)*4);
|
|
new->tps_size = 4 ;
|
|
|
|
new->map[0] = create_cube_0(0.0, 0.0, 0.0, 5.0, 1.0, 5.0, 0.0, 0.0, 255, 255, 255);
|
|
new->map[1] = create_cube_0(0.0, 0.0, 0.0, 5.0, 1.0, 5.0, 0.0, 0.0, 255, 255, 255);
|
|
new->map[2] = create_cube_0(0.0, 0.0, 0.0, 5.0, 1.0, 5.0, 0.0, 0.0, 255, 255, 255);
|
|
new->map[3] = create_cube_0(0.0, 0.0, 0.0, 5.0, 1.0, 5.0, 0.0, 0.0, 255, 255, 255);
|
|
new->map[4] = create_cube_0(0.0, 1.0, 0.0, 1.0, 5.0, 1.0, 0.0, 0.0, 255, 255, 128);
|
|
new->map[5] = create_cube_0(4.0, 1.0, 0.0, 1.0, 5.0, 1.0, 0.0, 0.0, 255, 255, 128);
|
|
new->map[6] = create_cube_0(0.0, 1.0, 4.0, 1.0, 5.0, 1.0, 0.0, 0.0, 255, 255, 128);
|
|
new->map[7] = create_cube_0(4.0, 1.0, 4.0, 1.0, 5.0, 1.0, 0.0, 0.0, 255, 255, 128);
|
|
new->map[8] = create_cube_0(10.0, 10.0, 10.0, 2.0, 2.0, 2.0, 0.0, 0.0, 255, 128, 255);
|
|
|
|
new->tps[0] = create_teleporter(-1.0, 1.0, 2.0, 1.0, 2.0 + (double)(rand()%2), 1.0, 0.0, 0.0, 255, 0, 0 , chx-1, chy , 2.5, 2.5, 2.5);
|
|
new->tps[1] = create_teleporter(2.0, 1.0, -1.0, 1.0, 2.0 + (double)(rand()%2), 1.0, 0.0, 0.0, 255, 255, 0, chx , chy-1, 2.5, 2.5, 2.5);
|
|
new->tps[2] = create_teleporter(5.0, 1.0, 2.0, 1.0, 2.0 + (double)(rand()%2), 1.0, 0.0, 0.0, 0, 255, 0 , chx+1, chy , 2.5, 2.5, 2.5);
|
|
new->tps[3] = create_teleporter(2.0, 1.0, 5.0, 1.0, 2.0 + (double)(rand()%2), 1.0, 0.0, 0.0, 0, 0, 255 , chx , chy+1, 2.5, 2.5, 2.5);
|
|
|
|
new->ents = malloc(sizeof(entity)*128);
|
|
new->ent_len = 1 ;
|
|
new->ent_memlen = 128 ;
|
|
new->ents[0].pos = create_cube_0(-0.25, 8.25, -0.25, 0.5, 0.5, 0.5, 0.0, 0.0, 193, 128, 0);
|
|
new->ents[0].damage = 0 ;
|
|
new->ents[0].hitpoints = malloc(sizeof(int));
|
|
*(new->ents[0].hitpoints) = 5 ;
|
|
new->ents[0].onDeath = NULL ;
|
|
new->ents[0].onHit = *detectHit ;
|
|
new->ents[0].updatePos = *speen2 ;
|
|
|
|
hashtbl_add(visited, chx, chy, new);
|
|
}
|
|
|
|
void init_hashtbl() {
|
|
visited = hashtbl_generate(1789);
|
|
build_starting_chunk(0, 0);
|
|
current_room = hashtbl_find_opt(visited, 0, 0);
|
|
player_chx = 0 ;
|
|
player_chy = 0 ;
|
|
total_weight = 0 ;
|
|
coins = 0 ;
|
|
}
|
|
|
|
void get_number_blocks(int* ret_cubes, int* ret_tps, int* ret_ent, FILE* ptr) {
|
|
*ret_cubes = 0 ;
|
|
*ret_tps = 0 ;
|
|
*ret_ent = 0 ;
|
|
|
|
int in_blocks = 0 ;
|
|
char c = fgetc(ptr) ;
|
|
while(c != EOF && c != '$') {
|
|
//printf("%c", c);
|
|
if(c == 'B') {
|
|
in_blocks = 0 ;
|
|
} else if(c == 'T') {
|
|
in_blocks = 1 ;
|
|
} else if(c == 'E') {
|
|
in_blocks = 2 ;
|
|
} else if(c == '[') {
|
|
if(in_blocks == 0) {
|
|
*ret_cubes += 1 ;
|
|
} else if(in_blocks == 1) {
|
|
*ret_tps += 1 ;
|
|
} else {
|
|
*ret_ent += 1;
|
|
}
|
|
}
|
|
c = fgetc(ptr);
|
|
}
|
|
|
|
fclose(ptr);
|
|
}
|
|
|
|
void align_to(FILE* ptr, char ch) {
|
|
char c = fgetc(ptr);
|
|
while(c != EOF && c != ch) {
|
|
c = fgetc(ptr);
|
|
}
|
|
}
|
|
|
|
int read_int(FILE* ptr, bool print) {
|
|
bool is_reading = false;
|
|
int buffer = 0 ;
|
|
int sign = 1 ;
|
|
char c = fgetc(ptr);
|
|
while(c != EOF) {
|
|
if(c == '-') {
|
|
sign = -1 ;
|
|
} else if((int)c >= 48 && (int)c <= 57) {
|
|
is_reading = true ;
|
|
buffer = 10*buffer + (int)c - 48 ;
|
|
} else if(is_reading) {
|
|
/*if(print) {
|
|
printf("%d ; ", buffer*sign);
|
|
}*/
|
|
return buffer*sign;
|
|
}
|
|
c = fgetc(ptr);
|
|
}
|
|
return buffer*sign ;
|
|
}
|
|
|
|
double sign(double __x) {
|
|
if(__x >= 0.0) {
|
|
return 1.0;
|
|
}
|
|
return -1.0;
|
|
}
|
|
|
|
double read_float(FILE* ptr) {
|
|
int ent = read_int(ptr, false);
|
|
int frac = read_int(ptr, false);
|
|
//printf("%d.%d ; ", ent, frac);
|
|
if(ent != 0.0) {
|
|
return (ent/abs(ent))*(absf((double)ent) + ((double)frac)/(pow(10.0, (double)ln_baseN(frac, 10))));
|
|
} else {
|
|
//printf("%d, %d\n", ent, frac);
|
|
return ((double)frac)/(pow(10.0, (double)ln_baseN(frac, 10)));
|
|
}
|
|
}
|
|
|
|
void parse_one_room(int id, char* filename) {
|
|
//printf(" parsing %s...", filename);
|
|
FILE* ptr = fopen(filename, "r");
|
|
|
|
pool[id].area = malloc(sizeof(room));
|
|
int ncubes ;
|
|
int ntps ;
|
|
int nent ;
|
|
|
|
FILE* ptr2 = fopen(filename, "r") ;
|
|
get_number_blocks(&ncubes, &ntps, &nent, ptr2);
|
|
printf("(%d, %d, %d)\n", ncubes, ntps, nent);
|
|
|
|
int nmemlen = 128 ;
|
|
while(nmemlen < nent) {
|
|
nmemlen *= 2.;
|
|
}
|
|
|
|
pool[id].area->map = malloc(sizeof(cube_0*)*ncubes);
|
|
pool[id].area->map_size = ncubes;
|
|
pool[id].area->tps = malloc(sizeof(teleporter*)*ntps);
|
|
for(int k = 0; k < ntps; k++) {
|
|
pool[id].area->tps[k] = malloc(sizeof(teleporter));
|
|
}
|
|
pool[id].area->tps_size = ntps;
|
|
pool[id].area->ents = malloc(sizeof(entity)*nmemlen);
|
|
pool[id].area->ent_len = nent ;
|
|
pool[id].area->ent_memlen = nmemlen ;
|
|
|
|
printf("0/3...\n");
|
|
fflush(stdout);
|
|
|
|
for(int k = 0; k < ncubes; k++) {
|
|
align_to(ptr, '[');
|
|
double cx = read_float(ptr);
|
|
double cy = read_float(ptr);
|
|
double cz = read_float(ptr);
|
|
double cw = read_float(ptr);
|
|
double ch = read_float(ptr);
|
|
double cd = read_float(ptr);
|
|
double chz = read_float(ptr);
|
|
double cvt = read_float(ptr);
|
|
int red = read_int(ptr, true);
|
|
int green = read_int(ptr, true);
|
|
int blue = read_int(ptr, true);
|
|
pool[id].area->map[k] = create_cube_0(cx, cy, cz, cw, ch, cd, chz, cvt, red, green, blue);
|
|
//printf("\n");
|
|
}
|
|
|
|
printf("1/3...\n");
|
|
fflush(stdout);
|
|
|
|
for(int k = 0; k < ntps; k++) {
|
|
align_to(ptr, '[');
|
|
double cx = read_float(ptr);
|
|
double cy = read_float(ptr);
|
|
double cz = read_float(ptr);
|
|
double cw = read_float(ptr);
|
|
double ch = read_float(ptr);
|
|
double cd = read_float(ptr);
|
|
double chz = read_float(ptr);
|
|
double cvt = read_float(ptr);
|
|
int red = read_int(ptr, true);
|
|
int green = read_int(ptr, true);
|
|
int blue = read_int(ptr, true);
|
|
pool[id].area->tps[k]->hitbox = create_cube_0(cx, cy, cz, cw, ch, cd, chz, cvt, red, green, blue);
|
|
pool[id].area->tps[k]->dest_chx = read_int(ptr, true);
|
|
pool[id].area->tps[k]->dest_chy = read_int(ptr, true);
|
|
//printf("\n");
|
|
}
|
|
|
|
printf("2/3...\n");
|
|
fflush(stdout);
|
|
|
|
for(int k = 0; k < nent; k++) {
|
|
align_to(ptr, '[');
|
|
double cx = read_float(ptr);
|
|
double cy = read_float(ptr);
|
|
double cz = read_float(ptr);
|
|
double cw = read_float(ptr);
|
|
double ch = read_float(ptr);
|
|
double cd = read_float(ptr);
|
|
double chz = read_float(ptr);
|
|
double cvt = read_float(ptr);
|
|
int red = read_int(ptr, true);
|
|
int green = read_int(ptr, true);
|
|
int blue = read_int(ptr, true);
|
|
int hp = read_int(ptr, true);
|
|
int dmg = read_int(ptr, true);
|
|
int fid = read_int(ptr, true);
|
|
fct_entry* entry = get_entry(fid);
|
|
if(entry == NULL) {
|
|
entry = get_entry(0);
|
|
}
|
|
pool[id].area->ents[k].pos = create_cube_0(cx, cy, cz, cw, ch, cd, chz, cvt, red, green, blue);
|
|
pool[id].area->ents[k].damage = dmg ;
|
|
pool[id].area->ents[k].hitpoints = malloc(sizeof(int));
|
|
*(pool[id].area->ents[k].hitpoints) = hp ;
|
|
|
|
pool[id].area->ents[k].updatePos = entry->updatePos ;
|
|
pool[id].area->ents[k].onHit = entry->onHit ;
|
|
pool[id].area->ents[k].onDeath = entry->onDeath ;
|
|
//pool[id].area->ents[k].updatePos = &speen2 ;
|
|
//pool[id].area->ents[k].onHit = &detectHit ;
|
|
//pool[id].area->ents[k].onDeath = NULL ;
|
|
//printf("\n");
|
|
}
|
|
|
|
printf("3/3...\n");
|
|
fflush(stdout);
|
|
|
|
// debug
|
|
for(int k = 0; k < ncubes; k++) {
|
|
printf("(%lf, %lf, %lf), (%lf, %lf, %lf), (%lf, %lf), (%d, %d, %d)\n",
|
|
pool[id].area->map[k]->x,
|
|
pool[id].area->map[k]->y,
|
|
pool[id].area->map[k]->z,
|
|
pool[id].area->map[k]->w,
|
|
pool[id].area->map[k]->h,
|
|
pool[id].area->map[k]->d,
|
|
pool[id].area->map[k]->hz_angle,
|
|
pool[id].area->map[k]->vt_angle,
|
|
pool[id].area->map[k]->red,
|
|
pool[id].area->map[k]->green,
|
|
pool[id].area->map[k]->blue
|
|
);
|
|
}
|
|
|
|
printf("OK\n");
|
|
fflush(stdout);
|
|
printf("\n\n");
|
|
|
|
pool[id].weight = read_int(ptr, true);
|
|
total_weight += pool[id].weight ;
|
|
|
|
fclose(ptr);
|
|
}
|
|
|
|
void parse_rooms(int n_rooms) {
|
|
char* name = malloc(sizeof(char)*19); // 1000 rooms max
|
|
name[0] = 't' ;
|
|
name[1] = 'e' ;
|
|
name[2] = 'm' ;
|
|
name[3] = 'p' ;
|
|
name[4] = 'l' ;
|
|
name[5] = 'a' ;
|
|
name[6] = 't' ;
|
|
name[7] = 'e' ;
|
|
name[8] = 's' ;
|
|
name[9] = '/' ;
|
|
name[10] = 'r' ;
|
|
name[11] = 'o' ;
|
|
name[12] = 'o' ;
|
|
name[13] = 'm' ;
|
|
name[14] = '_' ;
|
|
name[15] = '0' ;
|
|
name[16] = '\0' ;
|
|
name[17] = '\0' ;
|
|
name[18] = '\0' ;
|
|
|
|
pool = malloc(sizeof(entry)*n_rooms);
|
|
pool_size = n_rooms ;
|
|
|
|
printf("Parsing...\n");
|
|
|
|
for(int k = 0; k < n_rooms; k++) {
|
|
if(k < 10) {
|
|
name[15] = (char)(k%10 + 48) ;
|
|
} else if(k < 100) {
|
|
name[15] = (char)((k/10)%10 + 48) ;
|
|
name[16] = (char)(k%10 + 48) ;
|
|
}
|
|
parse_one_room(k, name);
|
|
}
|
|
|
|
printf("\nDone.\n");
|
|
printf("Total sum : %d\n", total_weight);
|
|
|
|
free(name);
|
|
}
|
|
|
|
int divider = 8;
|
|
void generate_terrain(room* r) {
|
|
int rsize = 4*(room_width/divider)*(room_width/divider)*(room_depth/divider)*(room_depth/divider); // floor size (with 1x1 cubes)
|
|
|
|
cube** newMap = malloc(sizeof(cube_0*)*(rsize+r->map_size));
|
|
for(int k = 0; k < rsize+r->map_size; k++) {
|
|
newMap[k] = malloc(sizeof(cube_0));
|
|
|
|
}
|
|
|
|
for(int k = 0; k < r->map_size; k++) {
|
|
copy_cube(r->map[k], newMap[k]);
|
|
free(r->map[k]);
|
|
}
|
|
free(r->map);
|
|
|
|
// use whatever noise funtcion here
|
|
int i = r->map_size;
|
|
for(int l = -room_width; l < room_width; l+=divider) {
|
|
for(int d = -room_depth; d < room_depth; d+=divider) {
|
|
newMap[i] = create_cube_0((double)l, -20.0, (double)d, (double)divider, 1.0, (double)divider, 0.0, 0.0,32, 128, 32);
|
|
i+=1;
|
|
}
|
|
}
|
|
|
|
r->map = newMap;
|
|
r->map_size += rsize;
|
|
}
|
|
|
|
void generate_nearby_chunks(int render_dist) {
|
|
for(int w = -render_dist; w <= render_dist; w++) {
|
|
for(int h = -render_dist; h <= render_dist; h++) {
|
|
if(!hashtbl_mem(visited, player_chx + w, player_chy + h)) {
|
|
printf("generating (%d, %d)... ", player_chx + w, player_chy + h);
|
|
//build_starting_chunk(player_chx + w, player_chy + h);
|
|
int pick = rand()%total_weight ;
|
|
int sum = 0 ;
|
|
for(int k = 0; k < pool_size; k++) {
|
|
sum += pool[k].weight ;
|
|
if(pick < sum) {
|
|
printf("chose %d\n", k);
|
|
room* new = malloc(sizeof(room));
|
|
copy_room(pool[k].area, new, player_chx + w, player_chy + h);
|
|
generate_terrain(new);
|
|
hashtbl_add(visited, player_chx + w, player_chy + h, new);
|
|
k = pool_size+1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void free_pool() {
|
|
for(int k0 = 0; k0 < pool_size; k0++) {
|
|
for(int k = 0; k < pool[k0].area->map_size; k++) {
|
|
free(pool[k0].area->map[k]);
|
|
}
|
|
for(int k = 0; k < pool[k0].area->tps_size; k++) {
|
|
free(pool[k0].area->tps[k]->hitbox);
|
|
free(pool[k0].area->tps[k]);
|
|
}
|
|
for(int k = 0; k < pool[k0].area->ent_len; k++) {
|
|
free(pool[k0].area->ents[k].hitpoints);
|
|
free(pool[k0].area->ents[k].pos);
|
|
}
|
|
free(pool[k0].area->ents);
|
|
free(pool[k0].area->tps);
|
|
free(pool[k0].area->map);
|
|
free(pool[k0].area);
|
|
}
|
|
free(pool);
|
|
} |