Skip to content
Merged
22 changes: 5 additions & 17 deletions src/floors/floor.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,22 +131,10 @@ def add_room_next_to(
@param direction: direction in which the new room is placed
@param room_type: type for the room
"""
if direction == Direction.UP:
self.add_room(room[0], room[1] - 1, room_type)
elif direction == Direction.DOWN:
self.add_room(room[0], room[1] + 1, room_type)
elif direction == Direction.LEFT:
self.add_room(room[0] - 1, room[1], room_type)
elif direction == Direction.RIGHT:
self.add_room(room[0] + 1, room[1], room_type)
elif direction == Direction.UP_RIGHT:
self.add_room(room[0] + 1, room[1] - 1, room_type)
elif direction == Direction.UP_LEFT:
self.add_room(room[0] - 1, room[1] - 1, room_type)
elif direction == Direction.DOWN_RIGHT:
self.add_room(room[0] + 1, room[1] + 1, room_type)
elif direction == Direction.DOWN_LEFT:
self.add_room(room[0] - 1, room[1] + 1, room_type)
x, y = utils.util_functions.add_direction_to_coordinates(
direction, (room[0], room[1])
)
self.add_room(x, y, room_type)

def add_teleport_room(self, room: Room) -> None:
"""
Expand Down Expand Up @@ -252,7 +240,7 @@ def _get_room(self, coordinates: Tuple[int, int]) -> Optional[Room]:
return room
return None

def has_boos_room_as_neighbour(self, coordinates: Tuple[int, int]) -> bool:
def has_boss_room_as_neighbour(self, coordinates: Tuple[int, int]) -> bool:
"""
Checks if the given coordinates have a boss room as neighbour.
@param coordinates: coordinates to check
Expand Down
1 change: 0 additions & 1 deletion src/floors/tkinter_floor.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def __init__(self, height: int, width: int, canvas, name: str, seed: str):
"""
super().__init__(height, width, seed)
self._canvas = canvas
self._first_draw = True
self.name = name
self._after_id: Optional[str] = None

Expand Down
22 changes: 0 additions & 22 deletions src/generators/floor_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
from collections import deque
from typing import Deque

from utils import globals as my_globals

from floors.tkinter_floor import TkinterFloor


Expand All @@ -30,26 +28,6 @@ def __init__(self, output_file_name: str) -> None:
self.next_seed = tk.StringVar()
self.next_seed.set(secrets.token_hex(16))

def add_new_floor(self, floor: TkinterFloor, canvas) -> None:
"""
Adds a new floor to the floor manager.
@param floor: floor to add
@param canvas: canvas to draw on
"""
self._floors.append(
TkinterFloor(
my_globals.FLOOR_HEIGHT,
my_globals.FLOOR_WIDTH,
canvas=canvas,
name=my_globals.DEFAULT_FLOOR_NAME + my_globals.JSON_SUFFIX,
seed=floor.seed,
)
)
self.current_floor_index = len(self._floors) - 1
current = self._floors[self.current_floor_index]
self.current_floor_name.set(current.name)
self.current_floor_seed_var.set(current.seed)

def add_floor(self, floor: TkinterFloor) -> None:
"""
Adds a floor to the floor manager.
Expand Down
20 changes: 9 additions & 11 deletions src/generators/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def __init__(
self._output_file_name = output_file_name
self._output_file_path = output_file_path
self._floor: Floor = Floor(
my_globals.FLOOR_WIDTH, my_globals.FLOOR_HEIGHT, seed
my_globals.FLOOR_HEIGHT, my_globals.FLOOR_WIDTH, seed
)
self._random = random.Random(seed)

Expand Down Expand Up @@ -112,7 +112,10 @@ def generate(self, new_seed=None) -> None:
)

# Add start room
start_room: tuple = (self._random.randint(0, 8), self._random.randint(0, 7))
start_room: tuple = (
self._random.randint(0, my_globals.FLOOR_WIDTH - 1),
self._random.randint(0, my_globals.FLOOR_HEIGHT - 1),
)
floor.add_room(start_room[0], start_room[1], RoomType.START_ROOM)
number_of_current_rooms = 1
room_tuple_queue: deque = deque([]) # Room coordinates
Expand All @@ -130,12 +133,8 @@ def generate(self, new_seed=None) -> None:
if len(room_tuple_queue) == 0 and number_of_current_rooms < number_of_rooms:
room_tuple_queue.append(room_tuple_list.pop(0))

# room_tuple_queue.remove(start_room)
while len(room_tuple_queue) > 0:
room_tuple_list.append(room_tuple_queue.pop())
while len(room_tuple_queue) > 0:
room_tuple = room_tuple_queue.pop()
room_tuple_list.append(room_tuple)
room_tuple_list.remove(start_room)
while len(room_tuple_list) > 0:
room_tuple = room_tuple_list.pop()
Expand Down Expand Up @@ -336,7 +335,7 @@ def place_super_secret_room(self) -> None:
if (
floor.is_within_border(neighbour)
and not floor.contains_room(neighbour)
and not floor.has_boos_room_as_neighbour(neighbour)
and not floor.has_boss_room_as_neighbour(neighbour)
and floor.count_neighbours(neighbour[0], neighbour[1]) == 1
):
distance = util_functions.calculate_distance(boss_room, neighbour)
Expand Down Expand Up @@ -381,7 +380,7 @@ def _check_directions_for_secret_room(
current_neighbour = floor.count_neighbours(neighbour[0], neighbour[1])
if (
current_neighbour >= neighbour_rooms
and not floor.has_boos_room_as_neighbour(neighbour)
and not floor.has_boss_room_as_neighbour(neighbour)
):
floor.add_room(neighbour[0], neighbour[1], RoomType.SECRET_ROOM)
return True
Expand All @@ -398,7 +397,6 @@ def save(self, path: str = "") -> str:
n = self._output_file_name + time + my_globals.JSON_SUFFIX
output = os.path.join(self._output_file_path, n)

f = open(output, "w", encoding="utf-8")
f.write(self.to_json(1))
f.close()
with open(output, "w", encoding="utf-8") as file:
file.write(self.to_json(1))
return output
12 changes: 4 additions & 8 deletions src/generators/tkinter_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ def __init__(
)
self._path = tk.StringVar()
self._path.set(self._output_file_path)
self._menu_bar = tk.Menu(self._tk)
self._theme_handler = ThemeHandler(self._tk, self._canvas)
self._floor_manager = FloorManager(output_file_name)
self._tk.protocol("WM_DELETE_WINDOW", self.quit)
Expand All @@ -62,18 +61,15 @@ def _create_floor(self) -> None:
my_globals.DEFAULT_FLOOR_NAME + my_globals.JSON_SUFFIX,
self._seed,
)
self._floor_manager.add_new_floor(self._floor, self._canvas)
self._floor = self._floor_manager.get_current_floor()
self._floor_manager.add_floor(self._floor)

def _generate_and_draw_floor(self) -> None:
"""
Cals the generate method and the draw method of the floor.
Calls the generate method and the draw method of the floor.
"""
self._floor.stop_drawing()
self.generate(self._floor_manager.next_seed.get())
self._floor_manager.next_seed.set(self._floor_manager.next_seed.get())
self._floor_manager.next_seed.set(secrets.token_hex(16))
# self._floors[self._current_floor].draw(tk)
self._floor_manager.get_current_floor().draw_step_by_step()
self._floor = self._floor_manager.get_current_floor()

Expand All @@ -84,7 +80,7 @@ def open(self) -> None:
"""
options = util_functions.json_file_options.copy()
options["initialdir"] = self._output_file_path
options["title"] = "Open File"
options["title"] = util_functions.open_file_text
path = filedialog.askopenfilename(**options)
if len(path) > 0:
self._output_file_path = os.path.dirname(path)
Expand Down Expand Up @@ -130,7 +126,7 @@ def save(self, path: str = "") -> str:
options = util_functions.json_file_options.copy()
options["initialdir"] = self._output_file_path
options["initialfile"] = self._output_file_name
options["title"] = "Save File"
options["title"] = util_functions.save_file_text
file_path = filedialog.asksaveasfilename(**options)
if len(file_path) > 0:
self._output_file_path = os.path.dirname(file_path)
Expand Down
116 changes: 64 additions & 52 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,65 @@
Parses the command line arguments and calls the generator.
"""

import argparse
import os.path
import secrets
import sys
from typing import List, Optional

from utils import globals as my_globals
from generators.generator import Generator
from generators.tkinter_generator import TkinterGenerator

HELP_MESSAGE = """Creates a dungeon floor and saves it to a json file.
Options:
-h, --help: Prints this message.
-s, --seed: Sets the seed for the random number generator.
-o, --output: Sets the output file name, default is output.json.
-u, --ui: Enables the UI, default is disabled.
-f --floor: Sets the id for the floor, default is 0. (Must be 0 or greater)

def _floor_id(value: str) -> int:
"""
Parses a floor id from the command line.
@param value: value to parse
@return: floor id
"""
try:
floor_id = int(value)
except ValueError as error:
raise argparse.ArgumentTypeError(f"{value} is not a valid number") from error
if floor_id < 0:
raise argparse.ArgumentTypeError("the floor id must be 0 or greater")
return floor_id


def main(seed: str, output: str, ui: bool, floor_id):
def parse_arguments(argv: Optional[List[str]] = None) -> argparse.Namespace:
"""
Parses the command line arguments.
@param argv: arguments to parse, defaults to the command line arguments
@return: parsed arguments
"""
parser = argparse.ArgumentParser(
description="Creates a dungeon floor and saves it to a json file."
)
parser.add_argument(
"-s",
"--seed",
default="",
help="seed for the random number generator, default is a random seed",
)
parser.add_argument(
"-o",
"--output",
default=my_globals.DEFAULT_FLOOR_NAME,
help="output file name, default is %(default)s",
)
parser.add_argument(
"-u", "--ui", action="store_true", help="enables the UI, default is disabled"
)
parser.add_argument(
"-f",
"--floor",
type=_floor_id,
default=2,
help="id for the floor, must be 0 or greater, default is %(default)s",
)
return parser.parse_args(argv)


def main(seed: str, output: str, ui: bool, floor_id: int) -> None:
"""
Main function for the dungeon generator.
@param seed: Seed for the random number generator.
Expand All @@ -33,57 +73,29 @@ def main(seed: str, output: str, ui: bool, floor_id):
output = os.path.join(output_folder, output)

if not os.path.exists(output_folder):
os.mkdir(output_folder)
os.makedirs(output_folder)
print("No output folder found. Creating specific folder")

if ui:
# Imported here so the command line works without tkinter
# pylint: disable=import-outside-toplevel
from generators.tkinter_generator import TkinterGenerator

TkinterGenerator(
seed, my_globals.DEFAULT_FLOOR_NAME, output_folder, floor_id
).run()
else:
generator = Generator(seed=seed, output_file_name=output, stage_id=floor_id)
generator.generate()
generator.save()
print("Floor saved to " + output)
path = generator.save()
print("Floor saved to " + path)


if __name__ == "__main__":
_seed: str = ""
_output: str = "floor"
_show_ui: bool = False
_floor_id: int = 2
i: int = 1
while i < len(sys.argv):
if sys.argv[i] == "-s" or sys.argv[i] == "--seed":
if i + 1 < len(sys.argv):
_seed = sys.argv[i + 1]
i += 1
elif sys.argv[i] == "-u" or sys.argv[i] == "--ui":
_show_ui = True
elif sys.argv[i] == "-h" or sys.argv[i] == "--help":
print(HELP_MESSAGE)
sys.exit(0)
elif sys.argv[i] == "-o" or sys.argv[i] == "--output":
if i + 1 < len(sys.argv):
_output = sys.argv[i + 1]
i += 1
elif sys.argv[i] == "-f" or sys.argv[i] == "--floor":
if i + 1 < len(sys.argv):
try:
_floor_id = int(sys.argv[i + 1])
i += 1
if _floor_id < 0:
print("The floor id must be greater than 0!")
sys.exit(-1)
except ValueError:
print(sys.argv[i + 1] + " is not a valid number!")
sys.exit(-1)
else:
print(sys.argv[i] + " is not a valid argument!")
sys.exit(-1)
i += 1

if _seed == "":
_seed = secrets.token_hex(16)

main(_seed, _output, _show_ui, _floor_id)
arguments = parse_arguments()
main(
arguments.seed or secrets.token_hex(16),
arguments.output,
arguments.ui,
arguments.floor,
)
2 changes: 1 addition & 1 deletion src/rooms/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __getitem__(self, index: int) -> int:
@return: Returns x if index equals 0 and y if index equals 1
"""
if index < 0 or index > 1:
raise ValueError(str(index) + "is not a valid index")
raise IndexError(f"{index} is not a valid index")
if index == 0:
return self._x
return self._y
Expand Down
17 changes: 6 additions & 11 deletions src/utils/room_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,12 @@ def is_special(self) -> bool:
- Secret room
@return: True if special otherwise False
"""
switcher = {
self.NORMAL_ROOM: False,
self.DEAD_END: False,
self.ITEM_ROOM: True,
self.SHOP_ROOM: True,
self.START_ROOM: False,
self.TELEPORT_ROOM: False,
self.BOSS_ROOM: True,
self.SECRET_ROOM: True,
}
return switcher[self]
return self in (
RoomType.ITEM_ROOM,
RoomType.SHOP_ROOM,
RoomType.BOSS_ROOM,
RoomType.SECRET_ROOM,
)

def get_color(self) -> Color:
"""
Expand Down
14 changes: 14 additions & 0 deletions test/floor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from utils.globals import DoorFace
from rooms.room import Room
from utils.room_type import RoomType
from utils.direction import Direction


class FloorTest(unittest.TestCase):
Expand All @@ -32,6 +33,19 @@ def test_add_two_floor_grid(self):
self._floor.add_to_floor_grid(2, 3)
self.assertTrue(self._floor.contains_room((2, 3)))

def test_add_room_next_to_places_the_room_in_the_given_direction(self):
room = Room(5, 5, 0, RoomType.NORMAL_ROOM)
for direction in Direction:
with self.subTest(direction=direction):
floor = Floor(20, 30, "1")

floor.add_room_next_to(room, direction, RoomType.BOSS_ROOM)

expected = (5 + direction.value[0], 5 + direction.value[1])
added = floor.get_rooms()[0]
self.assertEqual(expected, (added[0], added[1]))
self.assertEqual(RoomType.BOSS_ROOM, added.get_type())

def test_add_room(self):
self._floor.add_room(1, 1)
self.assertTrue(self._floor.contains_room((1, 1)))
Expand Down
Loading
Loading