Exemplo n.º 1
0
 // Returns the maze, making the zones that belong to the road.
 private bool SolveMaze(ref Zone zone)
 {
     if (zone.x == end.x && zone.y == end.y)
     {
         zone.isPath = true;
         return(true);
     }
     if (zone.isPath)
     {
         return(false);
     }
     zone.isPath = true;
     for (Direction dir = Direction.NORTH; dir <= Direction.WEST; dir += (int)dir)
     {
         if ((zone.walls & (int)dir) != 0)   // If does not exist a wall.
         {
             if (SolveMaze(ref zones[zone.x + DirectionFuncs.GetX(dir), zone.y + DirectionFuncs.GetY(dir)]))
             {
                 return(true);
             }
         }
     }
     zone.isPath = false;
     return(false);
 }
Exemplo n.º 2
0
    // Marks the zones that have keys and/or doors.
    private void CreateDoorsAndKeys(ref Zone zone, Direction from, ref int region, ref int order)
    {
        List <Direction> dirs = GetAvailableDirections(zone, from);

        if (dirs.Count == 0)
        {
            // Put a key.
            zone.key    = ++region;
            zone.region = region;
            zone.order  = ++order;
            order       = 0;
        }
        else
        {
            // Continue iterating.
            int lastRegion = region;
            foreach (Direction dir in dirs)
            {
                if (lastRegion != region && dirs.Count > 1)
                {
                    // Put a door.
                    lastRegion = region;
                    switch (dir)
                    {
                    case Direction.NORTH:
                        zone.northDoor = region;
                        break;

                    case Direction.EAST:
                        zone.eastDoor = region;
                        break;

                    case Direction.SOUTH:
                        zone.southDoor = region;
                        break;

                    case Direction.WEST:
                        zone.westDoor = region;
                        break;
                    }
                }

                if (zone.region == 0)
                {
                    zone.region = region + 1;
                    zone.order  = ++order;
                }
                CreateDoorsAndKeys(ref zones[zone.x + DirectionFuncs.GetX(dir), zone.y + DirectionFuncs.GetY(dir)], DirectionFuncs.GetOpposite(dir), ref region, ref order);
            }
        }
    }
Exemplo n.º 3
0
    // Generate a path between 2 rooms in a simple and direct way.
    private void GeneratePathBetweenRooms(Vec2i start, Vec2i end)
    {
        // Choose the directions towards the end room.
        Direction directionX = (end.x > start.x) ? Direction.EAST : Direction.WEST;
        Direction directionY = (end.y > start.y) ? Direction.NORTH : Direction.SOUTH;

        Vec2i current = start;
        Vec2i last    = current;

        while (current != end)
        {
            int axis = Random.Range(0, 2);
            if (axis == 0 && current.x == end.x)
            {
                axis = 1;
            }
            else if (axis == 1 && current.y == end.y)
            {
                axis = 0;
            }
            if (axis == 0)
            {
                // Take an X direction.
                current.x += (directionX == Direction.EAST) ? 1 : -1;
                // Connect the rooms.
                if (current.x >= 0 && current.x < width && current.y >= 0 && current.y < height)
                {
                    rooms[last.x, last.y].walls       |= (int)directionX;
                    rooms[current.x, current.y].walls |= (int)DirectionFuncs.GetOpposite(directionX);
                }
            }
            else
            {
                // Take the Y direction.
                current.y += (directionY == Direction.NORTH) ? 1 : -1;
                // Connect the rooms.
                if (current.x >= 0 && current.x < width && current.y >= 0 && current.y < height)
                {
                    rooms[last.x, last.y].walls       |= (int)directionY;
                    rooms[current.x, current.y].walls |= (int)DirectionFuncs.GetOpposite(directionY);
                }
            }
            if (current != end)
            {
                rooms[current.x, current.y].isPath = true;
                rooms[current.x, current.y].isNull = false;
            }
            last = current;
        }
    }
Exemplo n.º 4
0
    // Generate the maze using the Growing Tree algorithm.
    private void GenerateMaze()
    {
        int x = Random.Range(0, width);
        int y = Random.Range(0, height);

        List <Zone> cells = new List <Zone>();

        cells.Add(zones[x, y]);

        Direction[] directions = { Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST };

        while (cells.Count > 0)
        {
            int index = ChooseIndex(cells.Count);
            x = cells[index].x;
            y = cells[index].y;

            Utils.Shuffle <Direction>(directions);

            foreach (Direction direction in directions)
            {
                int newX = x + DirectionFuncs.GetX(direction);
                int newY = y + DirectionFuncs.GetY(direction);
                if (newX >= 0 && newX < width && newY >= 0 && newY < height && zones[newX, newY].walls == 0)
                {
                    zones[x, y].walls       |= (int)direction;
                    zones[newX, newY].walls |= (int)DirectionFuncs.GetOpposite(direction);
                    cells.Add(zones[newX, newY]);
                    index = -1;
                    break;
                }
            }
            if (index > -1)
            {
                cells.RemoveAt(index);
            }
        }
    }
Exemplo n.º 5
0
    // Return a list with the available directions to continue navigating through the maze.
    private List <Direction> GetAvailableDirections(Zone zone, Direction from)
    {
        List <Direction> dirs = new List <Direction>();

        Direction lastDirection = Direction.NONE;

        for (Direction dir = Direction.NORTH; dir <= Direction.WEST; dir += (int)dir)
        {
            if (dir != from)
            {
                if ((zone.walls & (int)dir) != 0)                                                           // If does not exist a wall.
                {
                    if (zones[zone.x + DirectionFuncs.GetX(dir), zone.y + DirectionFuncs.GetY(dir)].isPath) // Always take the last the zone that leads to the last zone.
                    {
                        lastDirection = dir;
                    }
                    else
                    {
                        dirs.Add(dir);
                    }
                }
            }
        }

        // Shuffle to not always take the same direction.
        if (dirs.Count > 1)
        {
            Utils.Shuffle <Direction>(dirs);
        }

        if (lastDirection != Direction.NONE)
        {
            dirs.Add(lastDirection);
        }

        return(dirs);
    }
Exemplo n.º 6
0
    // Generate filling rooms.
    private void GenerateFilling()
    {
        List <Room> fillingRooms = new List <Room>();

        // NOTE: If a room has walls == 15, it means that nothing can be added to the room.

        // In the first iteration exists a possibility of creating a filling room touching some of the path rooms.
        // Store the rooms in a list to continue iterating later.
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                if (rooms[i, j].isPath && rooms[i, j].walls < 15)   // 15 means that is not completely surrounded.
                {
                    for (Direction dir = Direction.NORTH; dir <= Direction.WEST; dir += (int)dir)
                    {
                        int x = i + DirectionFuncs.GetX(dir);
                        int y = j + DirectionFuncs.GetY(dir);
                        if (x >= 0 && x < width && y >= 0 && y < height)
                        {
                            if (rooms[x, y].isNull)
                            {
                                if (Random.value > 0.5f)
                                {
                                    rooms[x, y].filling = 1;
                                    rooms[x, y].isNull  = false;
                                    rooms[i, j].walls  |= (int)dir;
                                    rooms[x, y].walls  |= (int)DirectionFuncs.GetOpposite(dir);
                                    fillingRooms.Add(rooms[x, y]);
                                }
                            }
                        }
                    }
                }
            }
        }

        // IMPORTANT: This is similar to the Drunkard Walk algorithm (Random Walk).
        int iterations = Random.Range(0, 4);
        int filling    = 2;

        while (iterations > 0)
        {
            List <Room> nextFillingRooms = new List <Room>();
            for (int i = 0; i < fillingRooms.Count; i++)
            {
                if (fillingRooms[i].walls < 15)
                {
                    for (Direction dir = Direction.NORTH; dir <= Direction.WEST; dir += (int)dir)
                    {
                        int x = fillingRooms[i].x + DirectionFuncs.GetX(dir);
                        int y = fillingRooms[i].y + DirectionFuncs.GetY(dir);
                        if (x >= 0 && x < width && y >= 0 && y < height)
                        {
                            if (rooms[x, y].isNull)
                            {
                                if (Random.value > 0.5f)
                                {
                                    rooms[x, y].filling = filling;
                                    rooms[x, y].isNull  = false;
                                    rooms[fillingRooms[i].x, fillingRooms[i].y].walls |= (int)dir;
                                    rooms[x, y].walls |= (int)DirectionFuncs.GetOpposite(dir);
                                    nextFillingRooms.Add(rooms[x, y]);
                                }
                            }
                        }
                    }
                }
            }
            fillingRooms = nextFillingRooms;
            filling++;
            iterations--;
        }
    }