232 lines
5.9 KiB
C
232 lines
5.9 KiB
C
#include <grrlib.h>
|
|
#include <wiiuse/wpad.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
#include "maze.h"
|
|
#include "vars.h"
|
|
#include "player.h"
|
|
|
|
/** An Implementation of the Depth-First Search Recursive Backtracker Maze generator algorithm based on my work at:
|
|
* https://github.com/EmaMaker/recursive-backtracker/tree/c-implementation **/
|
|
|
|
cell* current;
|
|
cell* grid[W_GRID][H_GRID];
|
|
|
|
int stackX[W_GRID*H_GRID];
|
|
int stackY[W_GRID*H_GRID];
|
|
int cv = 0;
|
|
|
|
// int todraw[w_GRID][h_GRID];
|
|
|
|
void startNewLevel(){
|
|
srand(time(NULL));
|
|
generateMaze();
|
|
prepareShow();
|
|
setupPlayers();
|
|
setupEndPoint();
|
|
}
|
|
|
|
void initMazeGrid(){
|
|
for(int i = 0; i < W_GRID; i++){
|
|
for(int j = 0; j < H_GRID; j++){
|
|
cell* c = malloc(sizeof(cell));
|
|
grid[i][j] = c;
|
|
}
|
|
}
|
|
}
|
|
|
|
void generateMaze(){
|
|
//Init random
|
|
|
|
//Reset the counter for the stack when generating new maze or it will go over the array size!!!!
|
|
cv = 0;
|
|
|
|
for(int i = 0; i < W_GRID; i++){
|
|
for(int j = 0; j < H_GRID; j++){
|
|
grid[i][j]->visited=false;
|
|
grid[i][j]->up=true;
|
|
grid[i][j]->down=true;
|
|
grid[i][j]->right=true;
|
|
grid[i][j]->left=true;
|
|
grid[i][j]->x = i;
|
|
grid[i][j]->y = j;
|
|
}
|
|
}
|
|
|
|
//Pick a current cell
|
|
current = grid[0][0];
|
|
|
|
//while there are unvisited cells. This is gonna change when adding a stack
|
|
while(!allCellVisited()){
|
|
current->visited=true;
|
|
|
|
//Get unvisited neighbours
|
|
int un = 0;
|
|
int x = current->x;
|
|
int y = current->y;
|
|
if(x-1 >= 0 && !grid[x-1][y]->visited) un++;
|
|
if(x+1 < W_GRID && !grid[x+1][y]->visited) un++;
|
|
if(y-1 >= 0 && !grid[x][y-1]->visited) un++;
|
|
if(y+1 < H_GRID && !grid[x][y+1]->visited) un++;
|
|
|
|
//If there are any
|
|
if(un > 0){
|
|
int xs[un], ys[un];
|
|
|
|
int tun = 0;
|
|
if(x-1 >= 0 && !grid[x-1][y]->visited){
|
|
xs[tun] = x-1;
|
|
ys[tun] = y;
|
|
tun++;
|
|
}
|
|
if(x+1 < W_GRID && !grid[x+1][y]->visited){
|
|
xs[tun] = x+1;
|
|
ys[tun] = y;
|
|
tun++;
|
|
}
|
|
if(y-1 >= 0 && !grid[x][y-1]->visited){
|
|
xs[tun] = x;
|
|
ys[tun] = y-1;
|
|
tun++;
|
|
}
|
|
if(y+1 < H_GRID && !grid[x][y+1]->visited) {
|
|
xs[tun] = x;
|
|
ys[tun] = y+1;
|
|
tun++;
|
|
}
|
|
|
|
//Randomly choose one
|
|
int c = (int)(rand()) % un;
|
|
|
|
//Delete walls
|
|
//Right
|
|
if(grid[xs[c]][ys[c]]->x == current->x+1){
|
|
current->right=false;
|
|
grid[xs[c]][ys[c]]->left=false;
|
|
}
|
|
//Left
|
|
if(grid[xs[c]][ys[c]]->x == current->x-1){
|
|
current->left=false;
|
|
grid[xs[c]][ys[c]]->right=false;
|
|
}
|
|
//Up
|
|
if(grid[xs[c]][ys[c]]->y == current->y-1){
|
|
current->up=false;
|
|
grid[xs[c]][ys[c]]->down=false;
|
|
}
|
|
//Up
|
|
if(grid[xs[c]][ys[c]]->y == current->y+1){
|
|
current->down=false;
|
|
grid[xs[c]][ys[c]]->up=false;
|
|
}
|
|
|
|
//Push current cell to the stack
|
|
push(current->x, current->y);
|
|
|
|
current = grid[xs[c]][ys[c]];
|
|
}else if(cv > 0){
|
|
//Else if stack is not empty
|
|
current = grid[getX()][getY()];
|
|
pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
//Setup end point in a random location. At a distance of EP_DIST from every player
|
|
void setupEndPoint(){
|
|
//Randomly spawns all the players
|
|
//For a spawn location to be valid, it has to be free from both walls and players
|
|
int x = (rand() % (w_GRID));
|
|
int y = (rand() % (h_GRID));
|
|
|
|
//while there's a wall in current location pick new location
|
|
while(thereIsPlayerInPos(x, y) ||
|
|
((todraw[(x-1+w_GRID)%w_GRID][y] == 1 && todraw[(x+1+w_GRID)%w_GRID][y] == 1) ||
|
|
(todraw[x][(y+1+h_GRID)%h_GRID] == 1 && todraw[x][(y-1+h_GRID)%h_GRID] == 1)) || areTherePlayersNearby(x, y, EP_DIST)) {
|
|
x = (rand() % (w_GRID));
|
|
y = (rand() % (h_GRID));
|
|
}
|
|
todraw[x][y] = 2;
|
|
}
|
|
|
|
void prepareShow(){
|
|
for(int i = 0; i < w_GRID; i++){
|
|
for(int j = 0; j < h_GRID; j++){
|
|
todraw[i][j] = 1;
|
|
}
|
|
}
|
|
|
|
for(int i = 0; i < W_GRID; i++){
|
|
for(int j = 0; j < H_GRID; j++){
|
|
|
|
int x = 2*i+1;
|
|
int y = 2*j+1;
|
|
|
|
//current cell
|
|
todraw[x][y] = 0;
|
|
if(!grid[i][j]->up)todraw[x][y-1]=0;
|
|
if(!grid[i][j]->right)todraw[x+1][y]=0;
|
|
if(!grid[i][j]->down)todraw[x][y+1]=0;
|
|
if(!grid[i][j]->left)todraw[x-1][y]=0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void showMaze(){
|
|
for(int j = 0; j < h_GRID; j++){
|
|
for(int i = 0; i < w_GRID; i++){
|
|
if(todraw[i][j] == 1){
|
|
//wall
|
|
GRRLIB_Rectangle(M_XOFF + D_OFFSET + i*rSizeW, D_OFFSET + j*rSizeH, rSizeW, rSizeH, MAZE_WALL_COL, 1);
|
|
}else if(todraw[i][j] == 0){
|
|
//corridor
|
|
GRRLIB_Rectangle(M_XOFF + D_OFFSET + i*rSizeW, D_OFFSET + j*rSizeH, rSizeW, rSizeH, MAZE_CORRIDOR_COL, 1);
|
|
}else if(todraw[i][j] == 2){
|
|
//end point
|
|
GRRLIB_Rectangle(M_XOFF + D_OFFSET + i*rSizeW, D_OFFSET + j*rSizeH, rSizeW, rSizeH, MAZE_EP_COL, 1);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
bool allCellVisited() {
|
|
for(int i = 0; i < W_GRID; i++){
|
|
for(int j = 0; j < H_GRID; j++){
|
|
if(!grid[i][j]->visited) return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*STUCK STUFF*/
|
|
//Pushes to stackX and stackY
|
|
void push(int x, int y){
|
|
if(cv < W_GRID*H_GRID && cv >= 0){
|
|
stackX[cv] = x;
|
|
stackY[cv] = y;
|
|
cv++;
|
|
}
|
|
}
|
|
|
|
void pop(){
|
|
if(cv < W_GRID*H_GRID && cv >= 0){
|
|
cv--;
|
|
stackX[cv] = -1;
|
|
stackY[cv] = -1;
|
|
}
|
|
}
|
|
|
|
int getX(){
|
|
return stackX[cv-1];
|
|
}
|
|
|
|
int getY(){
|
|
return stackY[cv-1];
|
|
}
|