binding-of-isaac/src/hash.c

158 lines
4.2 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"
// ------------------------------------------------------------------------------------------------------- //
bool linkedList_mem(linkedList lst, int chx, int chy) {
if(lst == NULL) {
return false ;
} else if(lst->chx == chx && lst->chy == chy) {
return true ;
}
return linkedList_mem(lst->next, chx, chy) ;
}
room linkedList_find(linkedList lst, int chx, int chy) {
if(lst == NULL) {
fprintf(stderr, "ERROR : (%d, %d) is not a valid key in hash\n", chx, chy);
exit(1);
} else if(lst->chx == chx && lst->chy == chy) {
return *(lst->area) ;
}
return linkedList_find(lst->next, chx, chy) ;
}
room* linkedList_find_opt(linkedList lst, int chx, int chy) {
if(lst == NULL) {
return NULL ;
} else if(lst->chx == chx && lst->chy == chy) {
return (lst->area) ;
}
return linkedList_find_opt(lst->next, chx, chy) ;
}
void linkedList_add(linkedList lst, int chx, int chy, room* area) {
if(lst == NULL) {
fprintf(stderr, "ERROR : cannot add to NULL\n");
exit(1) ;
} else if(lst->next == NULL) {
cell* nex = malloc(sizeof(cell));
nex->area = area ;
nex->chx = chx ;
nex->chy = chy ;
nex->next = NULL ;
lst->next = nex ;
} else {
linkedList_add(lst->next, chx, chy, area) ;
}
}
void free_all_cubes(room* r) {
for(int k = 0; k < r->map_size; k++) {
free(r->map[k]);
}
for(int k = 0; k < r->tps_size; k++) {
free(r->tps[k]->hitbox);
free(r->tps[k]);
}
for(int k = 0; k < r->ent_memlen; k++) {
//free(r->ents[k]->metach1);
//free(r->ents[k]->metach2);
free(r->ents[k]->hitpoints);
free(r->ents[k]->pos);
free(r->ents[k]);
}
free(r->ents);
free(r->tps);
free(r->map);
}
void linkedList_free(linkedList lst) {
// frees rooms as well (requires all created rooms to be there)
if(lst != NULL) {
printf("freeing (%d, %d)\n", lst->chx, lst->chy);
free_all_cubes(lst->area);
linkedList_free(lst->next);
free(lst->area);
free(lst);
}
}
// ------------------------------------------------------------------------------------------------------- //
int cantor(int x, int y) {
return ((x + y) * (x + y + 1) / 2) + y;
}
int generate_hash(int x, int y) {
if (x < 0) {
x = -2*x - 1;
} else {
x = 2 * x;
}
if (y < 0) {
y = -2*y - 1;
} else {
y = 2 * y;
}
return cantor(x, y);
}
hashtbl hashtbl_generate(int initial_size) {
hashtbl h = malloc(sizeof(hashtbl_0));
h->insertedElts = 0 ;
h->tabLength = initial_size ;
h->maxInserted = initial_size/2 ;
h->tab = malloc(sizeof(linkedList)*initial_size) ;
for(int k = 0; k < initial_size; k++) {
h->tab[k] = NULL ;
}
return h ;
}
bool hashtbl_mem(hashtbl tbl, int chx, int chy) {
int id = generate_hash(chx, chy)%(tbl->tabLength) ;
return linkedList_mem(tbl->tab[id], chx, chy) ;
}
room hashtbl_find(hashtbl tbl, int chx, int chy) {
int id = generate_hash(chx, chy)%(tbl->tabLength) ;
return linkedList_find(tbl->tab[id], chx, chy) ;
}
room* hashtbl_find_opt(hashtbl tbl, int chx, int chy) {
int id = generate_hash(chx, chy)%(tbl->tabLength) ;
return linkedList_find_opt(tbl->tab[id], chx, chy) ;
}
void hashtbl_add(hashtbl tbl, int chx, int chy, room* area) {
int id = generate_hash(chx, chy)%(tbl->tabLength) ;
tbl->insertedElts += 1 ;
if(tbl->tab[id] != NULL) {
linkedList_add(tbl->tab[id], chx, chy, area);
} else {
linkedList nex = malloc(sizeof(cell));
nex->area = area ;
nex->chx = chx ;
nex->chy = chy ;
nex->next = NULL ;
tbl->tab[id] = nex ;
}
}
void hashtbl_free(hashtbl tbl) {
for(int k = 0; k < tbl->tabLength; k++) {
linkedList_free(tbl->tab[k]);
}
free(tbl->tab);
free(tbl);
}