#include #include #include #include #include #include #include #include #include #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); }