//updated file builder.c
//cell structure
//each cell has 4 walls
//each wall is divided into 3 for 3 model sections
//p.s check for doubled walls
typedef struct
{
VECTOR right_walls;//right wall start vector
VECTOR right_walle;//right wall end vector
VECTOR left_walls;//left wall start vector
VECTOR left_walle;//left wall end vector
VECTOR lower_walls;//lower wall start vector
VECTOR lower_walle;//lower wall end vector
VECTOR upper_walls;//upper wall start vector
VECTOR upper_walle;//upper wall end vector
VECTOR pos;//center of cell
int index;//cell index
}cell;
int totcells=0;//total cells
var spc=0;//space between cell centers
cell *cells;//cell array
var w;//width of grid
var h;//height of grid
/*
typedef struct
{
ENTITY* section_ent;
}section;
section* T_sections;//T shaped intersections
section* cross_sections;//+ shaped intersections;
section* corner_sections;//corner shaped intersections
section* hallway_section;//hallway sections
*/
void on_t_intersection_topleft(int cell_index,VECTOR *pos);
void on_t_intersection_bottomleft(int cell_index,VECTOR* pos);
void on_t_intersection_topleftside(int cell_index,VECTOR* pos);
void on_t_intersection_toprightside(int cell_index,VECTOR* pos);
void on_cross_intersection(int cell_index,VECTOR* pos);
void on_corner_topleft(int cell_index,VECTOR* pos);
void on_corner_topright(int cell_index,VECTOR* pos);
void on_corner_bottomleft(int cell_index,VECTOR* pos);
void on_corner_bottomright(int cell_index,VECTOR* pos);
void on_upward_straight_leftmiddle(int cell_index,VECTOR* pos);
void on_upward_straight_lefttop(int cell_index,VECTOR* pos);
void on_upward_straight_leftbottom(int cell_index,VECTOR* pos);
void on_sideways_straight_topmiddle(int cell_index,VECTOR* pos);
void on_sideways_straight_topright(int cell_index,VECTOR* pos);
void on_sideways_straight_bottomleft(int cell_index,VECTOR* pos);
////////////////////////////////////////////////////////check walls
//cur_cell has upper wall?
int has_upper_wall(int cur_cell)
{
if((cells[cur_cell].upper_walls.x!=0 && cells[cur_cell].upper_walle.x!=0)&&(cells[cur_cell].upper_walls.y!=0 && cells[cur_cell].upper_walle.y!=0))
return 1;
else return 0;
}
//cur_cell has lower wall?
int has_lower_wall(int cur_cell)
{
if((cells[cur_cell].lower_walls.x!=0 && cells[cur_cell].lower_walle.x!=0)&&(cells[cur_cell].lower_walls.y!=0 && cells[cur_cell].lower_walle.y!=0))
return 1;
else return 0;
}
//cur_cell has right wall?
int has_right_wall(int cur_cell)
{
if((cells[cur_cell].right_walls.x!=0 && cells[cur_cell].right_walle.x!=0)&&(cells[cur_cell].right_walls.y!=0 && cells[cur_cell].right_walle.y!=0))
return 1;
else return 0;
}
//cur_cell has left wall?
int has_left_wall(int cur_cell)
{
if((cells[cur_cell].left_walls.x!=0 && cells[cur_cell].left_walle.x!=0)&&(cells[cur_cell].left_walls.y!=0 && cells[cur_cell].left_walle.y!=0))
return 1;
else return 0;
}
////////////////////////////////////////////////////////neigbours
//cur_cell is on right of targetcell?
int is_on_right(int targetcell,int cur_cell)
{
if(cells[targetcell].pos.y<cells[cur_cell].pos.y)// &&(cells[targetcell].pos.x==cells[curcell].pos.x))//right of curcell
return 1;
else return 0;
}
//cur_cell is on left of targetcell?
int is_on_left(int targetcell,int cur_cell)
{
if(cells[targetcell].pos.y>cells[cur_cell].pos.y)//&& (cells[targetcell].pos.x==cells[curcell].pos.x))//left of curcell
return 1;
else return 0;
}
//cur_cell is on top of targetcell?
int is_on_top(int targetcell,int cur_cell)
{
if(cells[targetcell].pos.x>cells[cur_cell].pos.x)//&& (cells[targetcell].pos.y==cells[curcell].pos.y))//top of curcell
return 1;
else return 0;
}
//cur_cell is on bottom of targetcell?
int is_on_bottom(int targetcell,int cur_cell)
{
if(cells[targetcell].pos.x<cells[cur_cell].pos.x)//&& (cells[targetcell].pos.y==cells[curcell].pos.y))//bottom of curcell
return 1;
else return 0;
}
//return the index of the cell ontop of curcell
int get_upper_cell(int cur_cell)
{
int i;
for(i=0;i<totcells;i++)
{
if(vec_dist(cells[cur_cell].pos,cells[i].pos)==spc)//in neighbour range?
{
if(is_on_top(i,cur_cell))return i;//cells[i].index;//cell index ontop of current cell
}
}
return -1;//no cell found
}
//return the index of the cell below curcell
int get_lower_cell(int cur_cell)
{
int i;
for(i=0;i<totcells;i++)
{
if(vec_dist(cells[cur_cell].pos,cells[i].pos)==spc)//in neighbour range?
{
if(is_on_bottom(i,cur_cell))return i;//cells[i].index;//cell index bellow of current cell
}
}
return -1;//no cell found
}
//return the index of the cell left of curcell
int get_left_cell(int cur_cell)
{
int i;
for(i=0;i<totcells;i++)
{
if(vec_dist(cells[cur_cell].pos,cells[i].pos)==spc)//in neighbour range?
{
if(is_on_left(i,cur_cell))return i;//cells[i].index;//cell index left of current cell
}
}
return -1;//no cell found
}
//return the index of the cell right of curcell
int get_right_cell(int cur_cell)
{
int i;
for(i=0;i<totcells;i++)
{
if(vec_dist(cells[cur_cell].pos,cells[i].pos)==spc)//in neighbour range?
{
if(is_on_right(i,cur_cell))return i;//cells[i].index;//cell index right of current cell
}
}
return -1;//no cell found
}
////////////////////////////////////////////////////////remove walls
//remove curcell left wall
void remove_left_wall(int cur_cell)
{
vec_set(cells[cur_cell].left_walls,nullvector);
vec_set(cells[cur_cell].left_walle,nullvector);
}
//remove curcell right wall
void remove_right_wall(int cur_cell)
{
vec_set(cells[cur_cell].right_walls,nullvector);
vec_set(cells[cur_cell].right_walle,nullvector);
}
//remove curcell upper wall
void remove_upper_wall(int cur_cell)
{
vec_set(cells[cur_cell].upper_walls,nullvector);
vec_set(cells[cur_cell].upper_walle,nullvector);
}
//remove curcell lower wall
void remove_lower_wall(int cur_cell)
{
vec_set(cells[cur_cell].lower_walls,nullvector);
vec_set(cells[cur_cell].lower_walle,nullvector);
}
////////////////////////////////////////////////////////add walls
var d=2;
void add_left_wall(int cur_cell)
{
if(!has_left_wall(cur_cell))
{
vec_set(cells[cur_cell].left_walls,vector(cells[cur_cell].pos.x-spc/d,cells[cur_cell].pos.y+spc/d,0));
vec_set(cells[cur_cell].left_walle,vector(cells[cur_cell].pos.x+spc/d,cells[cur_cell].pos.y+spc/d,0));
}
}
void add_right_wall(int cur_cell)
{
if(!has_right_wall(cur_cell))
{
vec_set(cells[cur_cell].right_walls,vector(cells[cur_cell].pos.x-spc/d,cells[cur_cell].pos.y-spc/d,0));
vec_set(cells[cur_cell].right_walle,vector(cells[cur_cell].pos.x+spc/d,cells[cur_cell].pos.y-spc/d,0));
}
}
void add_upper_wall(int cur_cell)
{
if(!has_upper_wall(cur_cell))
{
vec_set(cells[cur_cell].upper_walls,vector(cells[cur_cell].pos.x+spc/d,cells[cur_cell].pos.y-spc/d,0));
vec_set(cells[cur_cell].upper_walle,vector(cells[cur_cell].pos.x+spc/d,cells[cur_cell].pos.y+spc/d,0));
}
}
void add_lower_wall(int cur_cell)
{
if(!has_lower_wall(cur_cell))
{
vec_set(cells[cur_cell].lower_walls,vector(cells[cur_cell].pos.x-spc/d,cells[cur_cell].pos.y-spc/d,0));
vec_set(cells[cur_cell].lower_walle,vector(cells[cur_cell].pos.x-spc/d,cells[cur_cell].pos.y+spc/d,0));
}
}
////////////////////////////////////////////////////////make grid
//void generate_grid(length of a straight section,amount of cells eg. 10x10 3x3)
//creates a grid of cells of value NxN
void generate_grid(var l,int tot)
{
var segment_length=l; //segment length of a straight segment model
int amount=tot;//amount of cells =amount x amount eg.3x3 grid
w=(segment_length*3)*amount;//width
h=(segment_length*3)*amount;//height
spc=segment_length*3;//space between cells centers
totcells=(int)(amount*amount);
cells=malloc(sizeof(cell)*totcells);
//create cells in grid
int i=0;
var d=2;
var xx=0,yy=0;
for(xx=0;xx<w;xx+=spc)
{
for(yy=0;yy<h;yy+=spc)
{
vec_set(cells[i].pos,vector(xx,yy,0));//cell pos
vec_set(cells[i].right_walls,vector(xx-spc/d,yy-spc/d,0));//r wall start
vec_set(cells[i].right_walle,vector(xx+spc/d,yy-spc/d,0));//r wall end
vec_set(cells[i].left_walls,vector(xx-spc/d,yy+spc/d,0));//l wall start
vec_set(cells[i].left_walle,vector(xx+spc/d,yy+spc/d,0));//l wall end
vec_set(cells[i].lower_walls,vector(xx-spc/d,yy-spc/d,0));//lower wall start
vec_set(cells[i].lower_walle,vector(xx-spc/d,yy+spc/d,0));//lower wall end
vec_set(cells[i].upper_walls,vector(xx+spc/d,yy-spc/d,0));//upper wall start
vec_set(cells[i].upper_walle,vector(xx+spc/d,yy+spc/d,0));//upper wall end
cells[i].index=i;
i+=1;
}
}
}
////////////////////////////////////////////////////////make maze
///////////////////////////
//create non-solvable maze
//by removing random cell walls
void do_maze()
{
int curcell=0;
for(curcell=0;curcell<totcells;curcell++)
{
int pick=random(4);//to remove a wall at random position(left/right/up/down walls)
if(pick==0)
{
//if not on border
//if has cell left of it
int neigbour=get_left_cell(curcell);
if(neigbour!=-1)
{
//if unvisited
if(has_right_wall(curcell) && has_upper_wall(curcell) && has_lower_wall(curcell))
{
//remove wall between
if(has_left_wall(curcell))remove_left_wall(curcell);
if(has_right_wall(neigbour))remove_right_wall(neigbour);
}
}
}
//picked neigbour right of curcell
if(pick==1)
{
//if not on border
//if has cell right of it
int neigbour=get_right_cell(curcell);
if(neigbour!=-1)
{
//if unvisited
if(has_left_wall(curcell) && has_upper_wall(curcell) && has_lower_wall(curcell))
{
//remove wall between
if(has_right_wall(curcell))remove_right_wall(curcell);
if(has_left_wall(neigbour))remove_left_wall(neigbour);
}
}
}
//picked neigbour ontop of curcell
if(pick==2)
{
//if not on border
//if has cell ontop of it
int neigbour=get_upper_cell(curcell);
if(neigbour!=-1)
{
//if unvisited
if(has_left_wall(curcell) && has_right_wall(curcell) && has_lower_wall(curcell))
{
//remove wall between
if(has_upper_wall(curcell))remove_upper_wall(curcell);
if(has_lower_wall(neigbour))remove_lower_wall(neigbour);
}
}
}
//picked neigbour below of curcell
if(pick==3)
{
//if not on border
//if has cell below it
int neigbour=get_lower_cell(curcell);
if(neigbour!=-1)
{
//if unvisited
if(has_left_wall(curcell) && has_right_wall(curcell) && has_upper_wall(curcell))
{
//remove wall between
if(has_lower_wall(curcell))remove_lower_wall(curcell);
if(has_upper_wall(neigbour))remove_upper_wall(neigbour);
}
}
}
}
////////////////////////////////////////////////////////make solvable
//if theres cells with less than min_walls add walls to it
//to prevent non-solvable mazes
for(curcell=0;curcell<totcells;curcell++)
{
int min_walls=2;
int total_cell_walls=0;
if(has_left_wall(curcell)) total_cell_walls+=1;
if(has_right_wall(curcell)) total_cell_walls+=1;
if(has_upper_wall(curcell)) total_cell_walls+=1;
if(has_lower_wall(curcell)) total_cell_walls+=1;
if(total_cell_walls<=min_walls)
{
if(total_cell_walls<=min_walls && !has_left_wall(curcell))
{
int neighbour=get_left_cell(curcell);
if(neighbour!=-1)
{
add_left_wall(curcell);
add_right_wall(neighbour);
total_cell_walls+=1;
}
}
if(total_cell_walls<=min_walls && !has_right_wall(curcell))
{
int neighbour=get_right_cell(curcell);
if(neighbour!=-1)
{
add_right_wall(curcell);
add_left_wall(neighbour);
total_cell_walls+=1;
}
}
if(total_cell_walls<=min_walls && !has_upper_wall(curcell))
{
int neighbour=get_upper_cell(curcell);
if(neighbour!=-1)
{
add_upper_wall(curcell);
add_lower_wall(neighbour);
total_cell_walls+=1;
}
}
if(total_cell_walls<=min_walls && !has_lower_wall(curcell))
{
int neighbour=get_lower_cell(curcell);
if(neighbour!=-1)
{
add_lower_wall(curcell);
add_upper_wall(neighbour);
total_cell_walls+=1;
}
}
}
}
}
////////////////////////
//create intersections and corners entities
void find_sections()
{
int curcell;
int pick=0;
for(curcell=0;curcell<totcells;curcell++)
{
//upperwallend -leftt top of cell
//upperwallstart -right top of cell
//lowerwallend -left bottom of cell
//lowerwallstart -right bottom of cell
//leftwallstart - bottom left of cell
//leftwallend - top left of cell
//rightwallstart - bottom right of cell
//rightwallend - top right of cell
//all shapes to build the maze-like structure are ceated and placed inside these functions
//iterate through neigbours
pick=get_left_cell(curcell);
if(pick!=-1)
{
//check for intersection T shaped at top left of cell
if(has_left_wall(curcell))
{
if(has_upper_wall(curcell)&& has_upper_wall(pick))
{
int a=get_upper_cell(curcell);
if(a!=-1)
{
if(!has_left_wall(a))//topleft T intersection
{
on_t_intersection_topleft(curcell,cells[curcell].upper_walle);
}
if(has_left_wall(a))//+ intersection
{
on_cross_intersection(curcell,cells[curcell].upper_walle);
}
}
}
}
//check for intersection T shaped at bottom left of cell
if(has_left_wall(curcell))
{
if(has_lower_wall(curcell)&& has_lower_wall(pick))
{
int a=get_lower_cell(curcell);
if(a!=-1)
{
if(!has_left_wall(a))//bottomleft inverted T _|_ intersection
{
on_t_intersection_bottomleft(curcell,cells[curcell].lower_walle);
}
}
}
}
}
pick=get_upper_cell(curcell);
if(pick!=-1)
{
//check for intersection T |-- shaped at top left of cell
if(has_left_wall(curcell)&& has_left_wall(pick))
{
if(has_upper_wall(curcell))
{
int a=get_left_cell(curcell);
if(a!=-1)
{
if(!has_upper_wall(a))//topleft on side |-- intersection
{
on_t_intersection_topleftside(curcell,cells[curcell].upper_walle);
}
}
}
}
//check for intersection T --| shaped at top right of cell
if(has_right_wall(curcell)&& has_right_wall(pick))
{
if(has_upper_wall(curcell))
{
int a=get_right_cell(curcell);
if(a!=-1)
{
if(!has_upper_wall(a))//topright on side --| intersection
{
on_t_intersection_toprightside(curcell,cells[curcell].right_walle);
}
}
}
}
}
//find corners
pick=get_left_cell(curcell);
if(pick!=-1)
{
if(has_left_wall(curcell))
{
if(has_upper_wall(curcell)&& !has_upper_wall(pick))
{
int a=get_upper_cell(curcell);
if(a!=-1)
{
if(!has_left_wall(a))//topleft corner
{
on_corner_topleft(curcell,cells[curcell].upper_walle);
}
}
}
}
}
pick=get_right_cell(curcell);
if(pick!=-1)
{
if(has_right_wall(curcell))
{
if(has_upper_wall(curcell)&& !has_upper_wall(pick))
{
int a=get_upper_cell(curcell);
if(a!=-1)
{
if(!has_right_wall(a))//topright corner intersection
{
on_corner_topright(curcell,cells[curcell].right_walle);
}
}
}
}
}
pick=get_left_cell(curcell);
if(pick!=-1)
{
if(has_left_wall(curcell))
{
if(has_lower_wall(curcell)&& !has_lower_wall(pick))
{
int a=get_lower_cell(curcell);
if(a!=-1)
{
if(!has_left_wall(a))//bottomleft corner intersection
{
on_corner_bottomleft(curcell,cells[curcell].left_walls);
}
}
}
}
}
pick=get_right_cell(curcell);
if(pick!=-1)
{
if(has_right_wall(curcell))
{
if(has_lower_wall(curcell)&& !has_lower_wall(pick))
{
int a=get_lower_cell(curcell);
if(a!=-1)
{
if(!has_right_wall(a))//bottomright corner intersection
{
on_corner_bottomright(curcell,cells[curcell].right_walls);
}
}
}
}
}
//x axis hallway sections
pick=get_left_cell(curcell);
if(pick!=-1)
{
if(has_left_wall(curcell)&& has_right_wall(pick))
{
on_upward_straight_leftmiddle(curcell,vector(cells[curcell].pos.x,cells[curcell].pos.y+spc/2,cells[curcell].pos.z));
if(!has_upper_wall(curcell) && !has_upper_wall(pick))
{
on_upward_straight_lefttop(curcell,vector(cells[curcell].pos.x+spc/3,cells[curcell].pos.y+spc/2,cells[curcell].pos.z));
}
if(!has_lower_wall(curcell) && !has_lower_wall(pick))
{
on_upward_straight_leftbottom(curcell,vector(cells[curcell].pos.x-spc/3,cells[curcell].pos.y+spc/2,cells[curcell].pos.z));
}
}
}
//y axis hallway sections
pick=get_upper_cell(curcell);
if(pick!=-1)
{
if(has_upper_wall(curcell)&& has_lower_wall(pick))
{
on_sideways_straight_topmiddle(curcell,vector(cells[curcell].pos.x+spc/2,cells[curcell].pos.y,cells[curcell].pos.z));
if(!has_right_wall(curcell) && !has_right_wall(pick))
{
on_sideways_straight_topright(curcell,vector(cells[curcell].pos.x+spc/2,cells[curcell].pos.y-spc/3,cells[curcell].pos.z));
}
if(!has_left_wall(curcell) && !has_left_wall(pick))
{
on_sideways_straight_bottomleft(curcell,vector(cells[curcell].pos.x+spc/2,cells[curcell].pos.y+spc/3,cells[curcell].pos.z));
}
}
}
}
}