Thomas Gill / Mbed 2 deprecated LabyrinthOfTheMinotaur

Dependencies:   N5110 PowerControl mbed

WorldBuilder/WorldBuilder.cpp

Committer:
ThomasBGill
Date:
2015-05-11
Revision:
36:b64696135142
Parent:
35:2c290fa78f1d

File content as of revision 36:b64696135142:

#include "WorldBuilder.h"

int map[MAP_WIDTH][MAP_HEIGHT];

//Enterance coordinates
int enx;
int eny;

//Exit coordinates
int exx;
int exy;

int sx;
int sy;


int level;

//Player coordinates
int px;
int py;

void Walls()
{
    //Fill map with walls
    for (int i = 0; i<MAP_WIDTH; i++) {
        for (int j = 0; j<MAP_HEIGHT; j++) {

            map[i][j] = WALL;
        }
    }
}

void FirstRoom()
{
    //Create initial room
    
    //Generate starting coordinates
    int si = rand()%25 + 1;
    int sj = rand()%15 + 1;

    int sw = rand()%5 + 5;
    int sh = rand()%5 + 5;

    for (int i = si; i < si + sw; i++) {
        for (int j = sj; j < sj + sh; j++) {
            map[i][j] = FLOOR;
        }
    }
    
    //Create enterance in room
    enx = rand()% sw + si;
    eny = rand()% sh + sj;
    map[enx][eny] = ENTER;
    
}

void ExitRoom()
{
    //Create exit room
    
    //Generate starting coordinates
    int si = rand()%50 + 30;
    int sj = rand()%25 + 20;

    int sw = rand()%5 + 5;
    int sh = rand()%5 + 5;

    for (int i = si; i < si + sw; i++) {
        for (int j = sj; j < sj + sh; j++) {
            map[i][j] = FLOOR;
        }
    }
    
    //Create exit in room
    exx = rand()% sw + si;
    exy = rand()% sh + sj;
    map[exx][exy] = EXIT;
}

void DungeonRoomBuilder()
{
    //Generate starting coordinates
    sx = rand() % (MAP_WIDTH - 1) + 1;
    sy = rand() % (MAP_HEIGHT - 1) + 1;

    //Get length
    int sw = rand() % 5 + 5;
    int sh = rand() % 5 + 5;

    for (int i = sx; i < sx + sw; i++) {
        for (int j = sy; j < sy + sh; j++) {
            if (i < MAP_WIDTH - 1 && j < MAP_HEIGHT - 1) {
                if (map[i][j] == WALL) {
                    map[i][j] = FLOOR;
                }
            }
        }
    }

    if (rand() % 3 == 0) {
        //Build chest at random coordinate in room
        int i = rand() % sw + sx;
        int j = rand() % sh + sy;
        map[i][j] = CHEST;
    }
}

int Neighbours(int i, int j)
{
    //Check neighbours
    int n = 0;

    if (map[i + 1][j] == FLOOR) {
        n++;
    }
    if (map[i - 1][j] == FLOOR) {
        n++;
    }
    if (map[i][j + 1] == FLOOR) {
        n++;
    }
    if (map[i][j - 1] == FLOOR) {
        n++;
    }

    return n;
}

void DeadEnds(int d)
{
    for (int del = d; del > 0; del--) { //Iterate the code d amount of times
    
        for (int i = 0; i < 84; i++) {
            for (int j = 0; j < 48; j++) {

                if (Neighbours(i, j) < 2) { //If an island or dead end then turn the floor into a wall
                    map[i][j] = WALL;
                }
            }
        }
    }
}

void Border()
{
    for (int i = 0; i < 84; i++) {
        for (int j = 0; j < 48; j++) {

            if (i == 0 || i == 83 || j == 0 || j == 47) {

                map[i][j] = WALL;

            }
        }
    }
}

void RandFloor(int r)
{

    for (int space = rand() % 50 + r; space > 0; space--) { //Iterate code r amount of times

        //Randomly generate coordinates
        int i = rand() % 84;
        int j = rand() % 48;

        if (rand() % 2 == 0 && map[i][j] == WALL) {
            map[i][j] = FLOOR;
        }
    }

}

void MazeKill()
{
    //Array which stores the order in which directions whill be checked
    int move[4] = { UP, DOWN, LEFT, RIGHT };

    bool moved = true;

    while (moved == true) {

        moved = false;

        for (int s = 0; s < 3; s++) { //Shuffle array

            int r = rand() % 4;

            int temp = move[s];

            move[s] = move[r];

            move[r] = temp;
        }

        for (int i = 0; i < 3; i++) {
            //For (direction) check if there are walls 2 tiles in that directions 
            //and check that they do not interfere with any part of the maze that has already been built
            
            if (move[i] == UP) {
                if (map[sx][sy - 1] == WALL && Neighbours(sx, sy - 1) == 1 && map[sx][sy - 2] == WALL && Neighbours(sx, sy - 2) == 0 && sy > 3) {
                    map[sx][sy - 1] = FLOOR;
                    map[sx][sy - 2] = FLOOR;
                    sy = sy - 2;
                    moved = true;
                    break;
                }
            } else if (move[i] == DOWN) {
                if (map[sx][sy + 1] == WALL && Neighbours(sx, sy + 1) == 1 && map[sx][sy + 2] == WALL && Neighbours(sx, sy + 2) == 0 && sy < 45) {
                    map[sx][sy + 1] = FLOOR;
                    map[sx][sy + 2] = FLOOR;
                    sy = sy + 2;
                    moved = true;
                    break;
                }
            } else if (move[i] == LEFT) {
                if (map[sx - 1][sy] == WALL && Neighbours(sx - 1, sy) == 1 && map[sx - 2][sy] == WALL && Neighbours(sx - 2, sy) == 0 && sx > 3) {
                    map[sx - 1][sy] = FLOOR;
                    map[sx - 2][sy] = FLOOR;
                    sx = sx - 2;
                    moved = true;
                    break;
                }
            } else if (move[i] == RIGHT) {
                if (map[sx + 1][sy] == WALL && Neighbours(sx + 1, sy) == 1 && map[sx + 2][sy] == WALL && Neighbours(sx + 2, sy) == 0 && sx < 81) {
                    map[sx + 1][sy] = FLOOR;
                    map[sx + 2][sy] = FLOOR;
                    sx = sx + 2;
                    moved = true;
                    break;
                }
            }
        }
    }

}

void Maze()
{
    //Start in top left corner
    sx = 1;
    sy = 1;

    //Choose random direction
    //Check if 2 cells in direction have no neighbours (excluding current position)
    //If true then build and set new current position
    //If false chose next direction

    //If cannot move in any direction scan through each cell until there is one which can be built on
    //If scan completes END

    int end = false;

    while (end == false) {

        end = true;

        map[sx][sy] = FLOOR; //Set current tile to a floor

        MazeKill();

        //DrawMap();

        for (int i = 1; i < MAP_WIDTH - 1; i++) {
            for (int j = 1; j < MAP_HEIGHT-1; j++) {

                if (map[i][j] == WALL && Neighbours(i, j) == 1) {
                    sx = i;
                    sy = j;

                    end = false; //If a wall tile in the array has only one neighbouring space that is a floor then more of the maze can be built so the generation has not yet finished 
                }

            }
        }

    }
}

void DungeonBuilder()
{

    Maze();

    FirstRoom();
    ExitRoom();

    int rn = rand() % 15 + 6;

    for (int i = rn; i>0; i--) {
        DungeonRoomBuilder();
    }

    RandFloor(31);

    Border();

    DeadEnds(50); //Remove lots of dead ends to make the map less confusing

}

void LabyrinthBuilder()
{

    Maze();

    FirstRoom();
    ExitRoom();

    RandFloor(151);

    DeadEnds(1); //Only remove some of the dead ends so that the map is still a challenge

    Border();

}

void World()
{
    Walls();
    if(level%5 == 0) {
        LabyrinthBuilder();
    } else {
        DungeonBuilder();
    }

    px = enx;
    py = eny;
}