Doors #156
|
@ -2,17 +2,17 @@
|
||||||
####### #############
|
####### #############
|
||||||
#.H...# #...........#
|
#.H...# #...........#
|
||||||
#.....# #####...........#
|
#.....# #####...........#
|
||||||
#.....# #............H..#
|
#.....# #...&........H..#
|
||||||
#.##### #.###...........#
|
#.##### #.###...........#
|
||||||
#.# #.# #...........#
|
#.# #.# #...........#
|
||||||
#.# #.# #############
|
#.# #.# #############
|
||||||
#.# #.#
|
#.# #.#
|
||||||
#.#### #.#
|
#.#### #.#
|
||||||
#....# #.#
|
#....# #.#
|
||||||
####.###################.#
|
####&###################&#
|
||||||
#.....................# #################
|
#.....................# #################
|
||||||
#.....................# #...............#
|
#.....................# #...............#
|
||||||
#.....................#######...............#
|
#.....................#######...............#
|
||||||
#...........................................#
|
#.....................&.....&...............#
|
||||||
#.....................#######...............#
|
#.....................#######...............#
|
||||||
####################### #################
|
####################### #################
|
||||||
|
|
|
@ -82,6 +82,7 @@ TexturePack.ASCII_PACK = TexturePack(
|
||||||
BOW=')',
|
BOW=')',
|
||||||
CHEST='□',
|
CHEST='□',
|
||||||
CHESTPLATE='(',
|
CHESTPLATE='(',
|
||||||
|
DOOR='&',
|
||||||
EAGLE='µ',
|
EAGLE='µ',
|
||||||
EMPTY=' ',
|
EMPTY=' ',
|
||||||
EXPLOSION='%',
|
EXPLOSION='%',
|
||||||
|
@ -124,6 +125,8 @@ TexturePack.SQUIRREL_PACK = TexturePack(
|
||||||
BOW='🏹',
|
BOW='🏹',
|
||||||
CHEST='🧰',
|
CHEST='🧰',
|
||||||
CHESTPLATE='🦺',
|
CHESTPLATE='🦺',
|
||||||
|
DOOR=('🚪', curses.COLOR_WHITE, (1000, 1000, 1000),
|
||||||
|
curses.COLOR_WHITE, (1000, 1000, 1000)),
|
||||||
EAGLE='🦅',
|
EAGLE='🦅',
|
||||||
EMPTY=' ',
|
EMPTY=' ',
|
||||||
EXPLOSION='💥',
|
EXPLOSION='💥',
|
||||||
|
|
|
@ -6,7 +6,7 @@ from random import randint
|
||||||
from typing import Dict, Optional, Tuple
|
from typing import Dict, Optional, Tuple
|
||||||
|
|
||||||
from .items import Item
|
from .items import Item
|
||||||
from ..interfaces import FightingEntity, InventoryHolder
|
from ..interfaces import FightingEntity, InventoryHolder, Tile
|
||||||
from ..translations import gettext as _
|
from ..translations import gettext as _
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,6 +152,12 @@ class Player(InventoryHolder, FightingEntity):
|
||||||
return True
|
return True
|
||||||
elif entity.is_item():
|
elif entity.is_item():
|
||||||
entity.hold(self)
|
entity.hold(self)
|
||||||
|
tile = self.map.tiles[y][x]
|
||||||
|
if tile == Tile.DOOR and move_if_possible:
|
||||||
|
# Open door
|
||||||
|
self.map.tiles[y][x] = Tile.FLOOR
|
||||||
|
self.map.compute_visibility(y, x, self.vision)
|
||||||
|
return super().check_move(y, x, move_if_possible)
|
||||||
return super().check_move(y, x, move_if_possible)
|
return super().check_move(y, x, move_if_possible)
|
||||||
|
|
||||||
def save_state(self) -> dict:
|
def save_state(self) -> dict:
|
||||||
|
|
|
@ -199,7 +199,9 @@ class Game:
|
||||||
self.map_index = 0
|
self.map_index = 0
|
||||||
return
|
return
|
||||||
while self.map_index >= len(self.maps):
|
while self.map_index >= len(self.maps):
|
||||||
self.maps.append(broguelike.Generator().run())
|
m = broguelike.Generator().run()
|
||||||
|
m.logs = self.logs
|
||||||
|
self.maps.append(m)
|
||||||
new_map = self.map
|
new_map = self.map
|
||||||
new_map.floor = self.map_index
|
new_map.floor = self.map_index
|
||||||
old_map.remove_entity(self.player)
|
old_map.remove_entity(self.player)
|
||||||
|
@ -417,6 +419,7 @@ class Game:
|
||||||
self.maps = [Map().load_state(map_dict) for map_dict in d["maps"]]
|
self.maps = [Map().load_state(map_dict) for map_dict in d["maps"]]
|
||||||
for i, m in enumerate(self.maps):
|
for i, m in enumerate(self.maps):
|
||||||
m.floor = i
|
m.floor = i
|
||||||
|
m.logs = self.logs
|
||||||
except KeyError as error:
|
except KeyError as error:
|
||||||
self.message = _("Some keys are missing in your save file.\n"
|
self.message = _("Some keys are missing in your save file.\n"
|
||||||
"Your save seems to be corrupt. It got deleted.")\
|
"Your save seems to be corrupt. It got deleted.")\
|
||||||
|
|
|
@ -390,6 +390,7 @@ class Tile(Enum):
|
||||||
WALL = auto()
|
WALL = auto()
|
||||||
FLOOR = auto()
|
FLOOR = auto()
|
||||||
LADDER = auto()
|
LADDER = auto()
|
||||||
|
DOOR = auto()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_ascii_char(ch: str) -> "Tile":
|
def from_ascii_char(ch: str) -> "Tile":
|
||||||
|
@ -430,7 +431,7 @@ class Tile(Enum):
|
||||||
"""
|
"""
|
||||||
Is this Tile a wall?
|
Is this Tile a wall?
|
||||||
"""
|
"""
|
||||||
return self == Tile.WALL
|
return self == Tile.WALL or self == Tile.DOOR
|
||||||
|
|
||||||
def is_ladder(self) -> bool:
|
def is_ladder(self) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -26,9 +26,11 @@ DEFAULT_PARAMS = {
|
||||||
"spawn_per_region": [1, 2],
|
"spawn_per_region": [1, 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
def dist(level, y1, x1, y2, x2):
|
|
||||||
|
def dist(level: List[List[Tile]], y1: int, x1: int, y2: int, x2: int) -> int:
|
||||||
"""
|
"""
|
||||||
Compute the minimum walking distance between points (y1, x1) and (y2, x2) on a Tile grid
|
Compute the minimum walking distance between points (y1, x1) and (y2, x2)
|
||||||
|
on a Tile grid
|
||||||
"""
|
"""
|
||||||
# simple breadth first search
|
# simple breadth first search
|
||||||
copy = [[t for t in row] for row in level]
|
copy = [[t for t in row] for row in level]
|
||||||
|
@ -97,8 +99,7 @@ class Generator:
|
||||||
making (door_y, door_x) in the room correspond with (y, x) in the level
|
making (door_y, door_x) in the room correspond with (y, x) in the level
|
||||||
"""
|
"""
|
||||||
rh, rw = len(room), len(room[0])
|
rh, rw = len(room), len(room[0])
|
||||||
# maybe place Tile.DOOR here instead ?
|
level[y][x] = Tile.DOOR
|
||||||
level[y][x] = Tile.FLOOR
|
|
||||||
for ry in range(rh):
|
for ry in range(rh):
|
||||||
for rx in range(rw):
|
for rx in range(rw):
|
||||||
if room[ry][rx] == Tile.FLOOR:
|
if room[ry][rx] == Tile.FLOOR:
|
||||||
|
@ -248,8 +249,8 @@ class Generator:
|
||||||
if room[y][x] == Tile.EMPTY and \
|
if room[y][x] == Tile.EMPTY and \
|
||||||
Generator.build_door(room, y, x, dy, dx, length):
|
Generator.build_door(room, y, x, dy, dx, length):
|
||||||
break
|
break
|
||||||
else:
|
else: # pragma: no cover
|
||||||
return None, None
|
return None, None, None, None
|
||||||
|
|
||||||
return y + length * dy, x + length * dx, dy, dx
|
return y + length * dy, x + length * dx, dy, dx
|
||||||
|
|
||||||
|
@ -324,8 +325,8 @@ class Generator:
|
||||||
top left corner of the room on the level, then log them as a
|
top left corner of the room on the level, then log them as a
|
||||||
spawnable region
|
spawnable region
|
||||||
"""
|
"""
|
||||||
if self.queued_area != None:
|
if self.queued_area is not None:
|
||||||
translated_area = [[y+ry, x+rx] for ry, rx in self.queued_area]
|
translated_area = [[y + ry, x + rx] for ry, rx in self.queued_area]
|
||||||
self.spawn_areas.append(translated_area)
|
self.spawn_areas.append(translated_area)
|
||||||
self.queued_area = None
|
self.queued_area = None
|
||||||
|
|
||||||
|
@ -334,11 +335,6 @@ class Generator:
|
||||||
Populate every spawnable area with some randomly chosen, randomly
|
Populate every spawnable area with some randomly chosen, randomly
|
||||||
placed entity
|
placed entity
|
||||||
"""
|
"""
|
||||||
if self.queued_area is not None:
|
|
||||||
translated_area = [[y + ry, x + rx] for ry, rx in self.queued_area]
|
|
||||||
self.spawn_areas.append(translated_area)
|
|
||||||
self.queued_area = None
|
|
||||||
|
|
||||||
min_c, max_c = self.params["spawn_per_region"]
|
min_c, max_c = self.params["spawn_per_region"]
|
||||||
for region in self.spawn_areas:
|
for region in self.spawn_areas:
|
||||||
entity_count = randint(min_c, max_c)
|
entity_count = randint(min_c, max_c)
|
||||||
|
|
|
@ -134,13 +134,13 @@ class TestEntities(unittest.TestCase):
|
||||||
self.map.remove_entity(entity2)
|
self.map.remove_entity(entity2)
|
||||||
|
|
||||||
# Test following the player and finding the player as target
|
# Test following the player and finding the player as target
|
||||||
self.player.move(5, 5)
|
self.player.move(6, 5)
|
||||||
fam.move(4, 5)
|
fam.move(5, 5)
|
||||||
fam.target = None
|
fam.target = None
|
||||||
self.player.move_down()
|
self.player.move_down()
|
||||||
self.map.tick(self.player)
|
self.map.tick(self.player)
|
||||||
self.assertTrue(fam.target == self.player)
|
self.assertTrue(fam.target == self.player)
|
||||||
self.assertEqual(fam.y, 5)
|
self.assertEqual(fam.y, 6)
|
||||||
self.assertEqual(fam.x, 5)
|
self.assertEqual(fam.x, 5)
|
||||||
|
|
||||||
# Test random move
|
# Test random move
|
||||||
|
|
|
@ -728,6 +728,7 @@ class TestGame(unittest.TestCase):
|
||||||
self.game.player.inventory.clear()
|
self.game.player.inventory.clear()
|
||||||
ring = RingCritical()
|
ring = RingCritical()
|
||||||
ring.hold(self.game.player)
|
ring.hold(self.game.player)
|
||||||
|
self.game.display_actions(DisplayActions.REFRESH)
|
||||||
old_critical = self.game.player.critical
|
old_critical = self.game.player.critical
|
||||||
self.game.handle_key_pressed(KeyValues.EQUIP)
|
self.game.handle_key_pressed(KeyValues.EQUIP)
|
||||||
self.assertEqual(self.game.player.critical,
|
self.assertEqual(self.game.player.critical,
|
||||||
|
@ -951,3 +952,18 @@ class TestGame(unittest.TestCase):
|
||||||
# Exit the menu
|
# Exit the menu
|
||||||
self.game.handle_key_pressed(KeyValues.SPACE)
|
self.game.handle_key_pressed(KeyValues.SPACE)
|
||||||
self.assertEqual(self.game.state, GameMode.PLAY)
|
self.assertEqual(self.game.state, GameMode.PLAY)
|
||||||
|
|
||||||
|
def test_doors(self) -> None:
|
||||||
|
"""
|
||||||
|
Check that the user can open doors.
|
||||||
|
"""
|
||||||
|
self.game.state = GameMode.PLAY
|
||||||
|
|
||||||
|
self.game.player.move(9, 8)
|
||||||
|
self.assertEqual(self.game.map.tiles[10][8], Tile.DOOR)
|
||||||
|
# Open door
|
||||||
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
||||||
|
self.assertEqual(self.game.map.tiles[10][8], Tile.FLOOR)
|
||||||
|
self.assertEqual(self.game.player.y, 10)
|
||||||
|
self.assertEqual(self.game.player.x, 8)
|
||||||
|
self.game.display_actions(DisplayActions.REFRESH)
|
||||||
|
|
|
@ -26,16 +26,17 @@ class TestBroguelike(unittest.TestCase):
|
||||||
|
|
||||||
def is_connex(self, grid: List[List[Tile]]) -> bool:
|
def is_connex(self, grid: List[List[Tile]]) -> bool:
|
||||||
h, w = len(grid), len(grid[0])
|
h, w = len(grid), len(grid[0])
|
||||||
y, x = randint(0, h - 1), randint(0, w - 1)
|
y, x = -1, -1
|
||||||
while not (grid[y][x].can_walk()):
|
while not grid[y][x].can_walk():
|
||||||
y, x = randint(0, h - 1), randint(0, w - 1)
|
y, x = randint(0, h - 1), randint(0, w - 1)
|
||||||
queue = Map.neighbourhood(grid, y, x)
|
queue = Map.neighbourhood(grid, y, x)
|
||||||
while queue:
|
while queue:
|
||||||
y, x = queue.pop()
|
y, x = queue.pop()
|
||||||
if grid[y][x].can_walk():
|
if grid[y][x].can_walk() or grid[y][x] == Tile.DOOR:
|
||||||
grid[y][x] = Tile.WALL
|
grid[y][x] = Tile.WALL
|
||||||
queue += Map.neighbourhood(grid, y, x)
|
queue += Map.neighbourhood(grid, y, x)
|
||||||
return not any([t.can_walk() for row in grid for t in row])
|
return not any([t.can_walk() or t == Tile.DOOR
|
||||||
|
for row in grid for t in row])
|
||||||
|
|
||||||
def test_build_doors(self) -> None:
|
def test_build_doors(self) -> None:
|
||||||
m = self.stom(". .\n. .\n. .\n")
|
m = self.stom(". .\n. .\n. .\n")
|
||||||
|
|
Loading…
Reference in New Issue