Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 23 additions & 27 deletions src/floors/floor.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,33 +63,23 @@ def bottom_right(self) -> Tuple[int, int]:
"""
return self._width - 1, self._height - 1

def to_json(self, indent: int):
def to_dict(self) -> dict:
"""
Creates a json string for the current room object.
Creates a dictionary representation of the floor object.
@return: dictionary with the seed and the rooms of the floor
"""
return {
"_seed": self.seed,
"_rooms": [room.to_dict() for room in self._rooms],
}

def to_json(self, indent: int = 1) -> str:
"""
Creates a json string for the current floor object.
@param indent: Number of indentation levels per nesting level
@return: json string
"""
indent_s: str = my_globals.BASE_INDENT * indent
current_index: int = 0
max_index: int = len(self._rooms)
json_string = (
"{\n"
+ f'{indent_s}"_seed": "{self.seed}",\n'
+ indent_s
+ '"_rooms"'
+ ": ["
)
if len(self._rooms) == 0:
json_string += "]"
else:
json_string += "\n"
for room in self._rooms:
if current_index < max_index - 1:
json_string += room.to_json(indent + 2) + ",\n"
else:
json_string += room.to_json(indent + 2)
current_index += 1
json_string += "\n" + indent_s + "]"
return json_string + "\n}"
return json.dumps(self.to_dict(), indent=len(my_globals.BASE_INDENT) * indent)

@classmethod
def from_json(cls, json_string: str):
Expand All @@ -100,9 +90,15 @@ def from_json(cls, json_string: str):
floor = Floor(
json_dict["_height"], json_dict["_width"], json_dict["_floor"]["_seed"]
)
rooms = json_dict["_floor"]["_rooms"]
for room in rooms:
floor._rooms.append(Room.from_dict(room))
for room_dict in json_dict["_floor"]["_rooms"]:
room = (
TeleportRoom.from_dict(room_dict)
if "_connected_room_id" in room_dict
else Room.from_dict(room_dict)
)
floor._rooms.append(room)
floor.add_to_floor_grid(room[0], room[1])
floor._room_id = max((room.get_id() for room in floor._rooms), default=-1) + 1
return floor

def add_to_floor_grid(self, x: int, y: int) -> None:
Expand Down
21 changes: 16 additions & 5 deletions src/floors/tkinter_floor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from floors.floor import Floor
from rooms.room import Room
from rooms.teleport_room import TeleportRoom

from rooms.tkinter.tkinter_room import TkinterRoom
from rooms.tkinter.tkinter_teleport_room import TkinterTeleportRoom
Expand Down Expand Up @@ -55,17 +56,27 @@ def from_floor(cls, floor: Floor, canvas, name: str):
@param name: name of the floor
@return: new TkinterFloor
"""
# pylint: disable=protected-access
tkinter_floor = TkinterFloor(
floor._height,
floor._width,
canvas,
name,
floor.seed, # pylint: disable=protected-access
floor.seed,
)
for room in floor._rooms: # pylint: disable=protected-access
tkinter_floor._rooms.append(
TkinterRoom.from_room(room)
) # pylint: disable=protected-access
for room in floor.get_rooms():
tkinter_room: TkinterRoom
if isinstance(room, TeleportRoom):
tkinter_room = TkinterTeleportRoom(
room[0], room[1], room.get_id(), room.get_connected_room_id()
)
for door in room.get_doors():
tkinter_room.add_door(door)
else:
tkinter_room = TkinterRoom.from_room(room)
tkinter_floor._rooms.append(tkinter_room)
tkinter_floor._floor_grid = floor.get_floor_grid().copy()
tkinter_floor._room_id = floor._room_id
return tkinter_floor

def _tkinter_rooms(self) -> List[TkinterRoom]:
Expand Down
38 changes: 16 additions & 22 deletions src/generators/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""

import itertools
import json
import os
import random
from collections import deque
Expand Down Expand Up @@ -48,32 +49,25 @@ def __init__(
)
self._random = random.Random(seed)

def to_json(self, indent: int) -> str:
def to_dict(self) -> dict:
"""
Creates a dictionary representation of the generator object.
@return: dictionary with the size and the floor of the generator
"""
return {
"_width": my_globals.FLOOR_WIDTH,
"_height": my_globals.FLOOR_HEIGHT,
"_floor": self._floor.to_dict(),
"_generated_by": "python",
}

def to_json(self, indent: int = 1) -> str:
"""
Creates a string representation of the generator object.
@param indent: Number of indentation levels per nesting level
@return: json string of the generator
"""
indent_s = my_globals.BASE_INDENT * indent

j = (
"{\n"
+ indent_s
+ '"_width": '
+ str(my_globals.FLOOR_WIDTH)
+ ",\n"
+ indent_s
+ '"_height": '
+ str(my_globals.FLOOR_HEIGHT)
+ ",\n"
+ indent_s
+ '"_floor": '
+ self._floor.to_json(indent + 1)
+ ",\n"
+ indent_s
+ '"_generated_by": "python"'
+ "\n}"
)
return j
return json.dumps(self.to_dict(), indent=len(my_globals.BASE_INDENT) * indent)

def _create_floor(self) -> None:
"""
Expand Down
58 changes: 18 additions & 40 deletions src/rooms/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
A room has a type, coordinates and doors.
"""

import json
from typing import List

from utils import globals as my_globals
Expand Down Expand Up @@ -44,49 +45,26 @@ def __getitem__(self, index: int) -> int:
return self._x
return self._y

def to_json(self, indent: int) -> str:
def to_dict(self) -> dict:
"""
Creates a dictionary representation of the room object.
@return: dictionary with the values of the room
"""
return {
"_doors": [door.value for door in self._doors],
"_id": self._id,
"_type": self._type.value,
"_x": self._x,
"_y": self._y,
}

def to_json(self, indent: int = 1) -> str:
"""
Creates a json representation of the room object.
@param indent: Amount of indentation the json representation should have
@param indent: Number of indentation levels per nesting level
@return: json string
"""
indent_s: str = my_globals.BASE_INDENT * indent
json_string: str = (
str(my_globals.BASE_INDENT * (indent - 1))
+ "{\n"
+ indent_s
+ '"_doors": [\n'
)
i = 0
while i < len(self._doors):
json_string += indent_s + my_globals.BASE_INDENT + str(self._doors[i].value)
if i != len(self._doors) - 1:
json_string += ",\n"
i += 1
json_string += (
"\n"
+ indent_s
+ "],\n"
+ indent_s
+ '"_id": '
+ str(self._id)
+ ",\n"
+ indent_s
+ '"_type": '
+ str(self._type.value)
+ ",\n"
+ indent_s
+ '"_x": '
+ str(self._x)
+ ",\n"
+ indent_s
+ '"_y": '
+ str(self._y)
+ "\n"
+ str(my_globals.BASE_INDENT * (indent - 1))
+ "}"
)
return json_string
return json.dumps(self.to_dict(), indent=len(my_globals.BASE_INDENT) * indent)

@classmethod
def from_dict(cls, json_dict: dict):
Expand Down Expand Up @@ -169,4 +147,4 @@ def __str__(self) -> str:
Returns a string representation of a room object.
@return: String representation
"""
return self.to_json(0)
return self.to_json()
25 changes: 25 additions & 0 deletions src/rooms/teleport_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

from rooms.room import Room
from utils.globals import DoorFace
from utils.room_type import RoomType


Expand Down Expand Up @@ -31,3 +32,27 @@ def get_connected_room_id(self) -> int:
@return: room id
"""
return self._connected_room

def to_dict(self) -> dict:
"""
Creates a dictionary representation of the teleport room object.
@return: dictionary with the values of the room and the connected room id
"""
room_dict = super().to_dict()
room_dict["_connected_room_id"] = self._connected_room
return room_dict

@classmethod
def from_dict(cls, json_dict: dict):
"""
Creates a teleport room object from a dictionary.
"""
room = TeleportRoom(
json_dict["_x"],
json_dict["_y"],
json_dict["_id"],
json_dict["_connected_room_id"],
)
for door in json_dict["_doors"]:
room.add_door(DoorFace(door))
return room
7 changes: 4 additions & 3 deletions src/rooms/tkinter/tkinter_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def from_room(cls, room: Room):
"""
Creates a new TkinterRoom from a room.
"""
return TkinterRoom(
room._x, room._y, room._id, room._type
) # pylint: disable=protected-access
tkinter_room = TkinterRoom(room[0], room[1], room.get_id(), room.get_type())
for door in room.get_doors():
tkinter_room.add_door(door)
return tkinter_room
54 changes: 54 additions & 0 deletions test/generator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import unittest
from collections import deque

import numpy

from floors.floor import Floor
from generators.generator import Generator
from rooms.teleport_room import TeleportRoom
Expand Down Expand Up @@ -242,6 +244,58 @@ def test_teleported_boss_rooms_are_isolated_and_on_the_grid(self):
0, floor.count_neighbours(boss_room[0], boss_room[1])
)

def test_from_json_restores_the_floor_grid(self):
self._generator.generate()

restored = Floor.from_json(self._generator.to_json(1))

self.assertTrue(
numpy.array_equal(
self._generator._floor.get_floor_grid(), restored.get_floor_grid()
)
)

def test_from_json_continues_the_room_ids(self):
self._generator.generate()
restored = Floor.from_json(self._generator.to_json(1))

restored.add_room(0, 0)

ids = [room.get_id() for room in restored.get_rooms()]
self.assertEqual(len(ids), len(set(ids)))

def test_from_json_restores_teleport_rooms(self):
generator = Generator("2", "test", "", 2)
generator.generate()
original = [
room
for room in generator._floor.get_rooms()
if isinstance(room, TeleportRoom)
]
self.assertEqual(1, len(original))

restored = Floor.from_json(generator.to_json(1))

teleport_rooms = [
room for room in restored.get_rooms() if isinstance(room, TeleportRoom)
]
self.assertEqual(1, len(teleport_rooms))
self.assertEqual(
original[0].get_connected_room_id(),
teleport_rooms[0].get_connected_room_id(),
)

def test_to_json_escapes_special_characters_in_the_seed(self):
for seed in ('a"b', "a\\b", "a\nb", "ä🙂"):
with self.subTest(seed=seed):
generator = Generator(seed, "test", "", 1)
generator.generate()

result = json.loads(generator.to_json(1))

self.assertEqual(seed, result["_floor"]["_seed"])
self.assertEqual(seed, Floor.from_json(generator.to_json(1)).seed)

def test_save_writes_the_generated_floor_to_the_given_path(self):
self._generator.generate()
with tempfile.TemporaryDirectory() as tmp_dir:
Expand Down
Loading
Loading