- Secret Fortune Teller Room: arcade lantern toggle, sliding timber panel, dedicated staircase and compact cellar chamber - Lived-in den pass v3: cloth hangings, draped workbench, props/clutter, centered entrance, and custom light sources - Bar camera stabilization: remove alcohol horizon sway while retaining drink animations - Synchronize binaries and update launcher hash to EADBA9C8C9BD5B7E3CC4CE486ED647C1CE9383D1DCB6EBC94FE755EA1F4BF927
92 lines
3.8 KiB
Python
92 lines
3.8 KiB
Python
"""Offline map compiler; collision and rendering consume the same MASM data."""
|
|
from collections import deque
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def reachable(grid, start):
|
|
visited, pending = {start}, deque([start])
|
|
while pending:
|
|
x, y = pending.popleft()
|
|
for point in ((x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)):
|
|
a, b = point
|
|
if 0 <= a < 32 and 0 <= b < 32 and not grid[b][a] and point not in visited:
|
|
visited.add(point)
|
|
pending.append(point)
|
|
return visited
|
|
|
|
|
|
def main():
|
|
hall = [[1 if x in (0, 31) or y in (0, 31) else 0 for x in range(32)] for y in range(32)]
|
|
# Cabaret enclosure, arcade divider, central pillars and rear reception.
|
|
for y in range(1, 7):
|
|
hall[y][9] = hall[y][22] = 2
|
|
for x in range(9, 23):
|
|
hall[1][x] = 2
|
|
for y in (7, 8, 9, 10, 14, 15, 18, 19, 20):
|
|
hall[y][9] = 1
|
|
for x, y in ((11, 11), (24, 11), (11, 19), (24, 19)):
|
|
hall[y][x] = 2
|
|
for x in range(13, 19):
|
|
hall[30][x] = 4
|
|
for x in range(27, 31):
|
|
hall[8][x] = hall[12][x] = 1
|
|
targets = [(12, 8), (16, 10), (20, 8), (24, 8), (6, 8), (6, 11),
|
|
(6, 14), (10, 15), (14, 15), (18, 15), (22, 15), (28, 10),
|
|
(28, 14), (29, 14), (12, 22), (20, 22), (16, 25), (18, 25),
|
|
(16, 29), (6, 25), (27, 25)]
|
|
assert all(point in reachable(hall, (16, 27)) for point in targets)
|
|
# Dedicated indoor concrete, never a street facade or refuse-container texture.
|
|
bunker = [[92] * 32 for _ in range(32)]
|
|
for y in range(11, 24):
|
|
for x in range(14, 20):
|
|
bunker[y][x] = 0
|
|
for y in range(24, 29):
|
|
for x in range(15, 18):
|
|
bunker[y][x] = 0
|
|
assert (16, 12) in reachable(bunker, (16, 26))
|
|
upper = [[125]*32 for _ in range(32)]
|
|
for y in range(13,25):
|
|
for x in range(3,16):
|
|
upper[y][x] = 0
|
|
# Enclosed, manually traversed stairwells with level landings at either end.
|
|
up_stairs = [[102]*32 for _ in range(32)]
|
|
for y in range(20,22):
|
|
for x in range(2,18):
|
|
up_stairs[y][x] = 0
|
|
down_stairs = [[92]*32 for _ in range(32)]
|
|
for y in range(20,23):
|
|
for x in range(2,18):
|
|
down_stairs[y][x] = 0
|
|
for y in range(13,23):
|
|
for x in range(15,18):
|
|
down_stairs[y][x] = 0
|
|
fortune = [[132]*32 for _ in range(32)]
|
|
for y in range(9,13):
|
|
for x in range(13,18):
|
|
fortune[y][x] = 0
|
|
fortune_stairs = [[132]*32 for _ in range(32)]
|
|
for y in range(9,11):
|
|
for x in range(16,31):
|
|
fortune_stairs[y][x] = 0
|
|
for grid, start, targets in ((upper,(4,21),[(7,18),(12,20),(9,23),(13,16)]),
|
|
(up_stairs,(3,21),[(16,21)]),
|
|
(down_stairs,(3,21),[(16,21),(16,14)]),
|
|
(fortune,(17,10),[(14,10),(16,12),(17,10)]),
|
|
(fortune_stairs,(29,10),[(17,10)])):
|
|
assert all(point in reachable(grid,start) for point in targets)
|
|
output = ["; Generated by make_hall_layout.py. Doorways and interactable approaches are checked.", ".data"]
|
|
for name, grid in (("hallLayout3D", hall), ("bunkerMap3D", bunker),
|
|
("upperLoungeMap3D",upper), ("upperStairMap3D",up_stairs),
|
|
("basementStairMap3D",down_stairs), ("fortuneRoomMap3D",fortune),
|
|
("fortuneStairMap3D",fortune_stairs)):
|
|
for index, row in enumerate(grid):
|
|
output.append((name if index == 0 else " " * len(name)) + " db " + ",".join(map(str, row)))
|
|
output.append(".code")
|
|
(ROOT / "src_graphics/hall_layout.inc").write_text("\n".join(output) + "\n", encoding="ascii")
|
|
print("Hall and bunker: every interaction approach is reachable")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|