Refactor how large screen quadrants are stored in grids
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import copy
|
|
||||||
import logging
|
import logging
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
import random as _random
|
import random as _random
|
||||||
@@ -8,7 +7,7 @@ from OverworldShuffle import connect_two_way, validate_layout
|
|||||||
|
|
||||||
ENABLE_KEEP_SIMILAR_SPECIAL_HANDLING = False
|
ENABLE_KEEP_SIMILAR_SPECIAL_HANDLING = False
|
||||||
PREVENT_WRAPPED_LARGE_SCREENS = False
|
PREVENT_WRAPPED_LARGE_SCREENS = False
|
||||||
DRAW_IMAGE = False
|
DRAW_IMAGE = True
|
||||||
|
|
||||||
large_screen_ids = [0x00, 0x03, 0x05, 0x18, 0x1B, 0x1E, 0x30, 0x35] + [0x40, 0x43, 0x45, 0x58, 0x5B, 0x5E, 0x70, 0x75]
|
large_screen_ids = [0x00, 0x03, 0x05, 0x18, 0x1B, 0x1E, 0x30, 0x35] + [0x40, 0x43, 0x45, 0x58, 0x5B, 0x5E, 0x70, 0x75]
|
||||||
|
|
||||||
@@ -49,7 +48,7 @@ class WorldPiece:
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
screens: List[List[Optional[Screen]]],
|
screens: Optional[List[List[Optional[Screen]]]] = None,
|
||||||
grid: Optional[List[List[int]]] = None,
|
grid: Optional[List[List[int]]] = None,
|
||||||
width: int = 0,
|
width: int = 0,
|
||||||
height: int = 0,
|
height: int = 0,
|
||||||
@@ -62,7 +61,7 @@ class WorldPiece:
|
|||||||
west_edges_water: Optional[List[List[List[OWEdge]]]] = None,
|
west_edges_water: Optional[List[List[List[OWEdge]]]] = None,
|
||||||
east_edges_water: Optional[List[List[List[OWEdge]]]] = None
|
east_edges_water: Optional[List[List[List[OWEdge]]]] = None
|
||||||
):
|
):
|
||||||
self.screens = screens
|
self.screens = screens if screens is not None else []
|
||||||
self.grid = grid if grid is not None else []
|
self.grid = grid if grid is not None else []
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
@@ -154,7 +153,7 @@ class LayoutGeneratorOptions:
|
|||||||
"""
|
"""
|
||||||
Configuration options for layout generation.
|
Configuration options for layout generation.
|
||||||
"""
|
"""
|
||||||
__slots__ = ('horizontal_wrap', 'vertical_wrap',
|
__slots__ = ('horizontal_wrap', 'vertical_wrap', 'split_large_screens',
|
||||||
'large_screen_pool', 'distortion_chance', 'random_order',
|
'large_screen_pool', 'distortion_chance', 'random_order',
|
||||||
'multi_choice', 'max_delay', 'first_ignore_bonus_points',
|
'multi_choice', 'max_delay', 'first_ignore_bonus_points',
|
||||||
'penalty_full_edge_mismatch', 'penalty_partial_edge_mismatch', 'bonus_partial_edge_match',
|
'penalty_full_edge_mismatch', 'penalty_partial_edge_mismatch', 'bonus_partial_edge_match',
|
||||||
@@ -168,6 +167,7 @@ class LayoutGeneratorOptions:
|
|||||||
self,
|
self,
|
||||||
horizontal_wrap: bool = True,
|
horizontal_wrap: bool = True,
|
||||||
vertical_wrap: bool = True,
|
vertical_wrap: bool = True,
|
||||||
|
split_large_screens = False,
|
||||||
large_screen_pool: bool = False,
|
large_screen_pool: bool = False,
|
||||||
distortion_chance: float = 0.0,
|
distortion_chance: float = 0.0,
|
||||||
random_order: int = 0,
|
random_order: int = 0,
|
||||||
@@ -194,6 +194,7 @@ class LayoutGeneratorOptions:
|
|||||||
):
|
):
|
||||||
self.horizontal_wrap = horizontal_wrap
|
self.horizontal_wrap = horizontal_wrap
|
||||||
self.vertical_wrap = vertical_wrap
|
self.vertical_wrap = vertical_wrap
|
||||||
|
self.split_large_screens = split_large_screens
|
||||||
self.large_screen_pool = large_screen_pool
|
self.large_screen_pool = large_screen_pool
|
||||||
self.distortion_chance = distortion_chance
|
self.distortion_chance = distortion_chance
|
||||||
self.random_order = random_order
|
self.random_order = random_order
|
||||||
@@ -418,8 +419,8 @@ def create_piece_list(world: World, player: int, options: LayoutGeneratorOptions
|
|||||||
|
|
||||||
if castle_screen and central_bonk_screen and links_house_screen:
|
if castle_screen and central_bonk_screen and links_house_screen:
|
||||||
piece = create_piece(world, player, [
|
piece = create_piece(world, player, [
|
||||||
[0x1B, 0x1B],
|
[0x1B, 0x1C],
|
||||||
[0x1B, 0x1B],
|
[0x23, 0x24],
|
||||||
[0x2B, 0x2C]
|
[0x2B, 0x2C]
|
||||||
], overworld_screens)
|
], overworld_screens)
|
||||||
|
|
||||||
@@ -439,10 +440,18 @@ def create_piece_list(world: World, player: int, options: LayoutGeneratorOptions
|
|||||||
# Add large screens
|
# Add large screens
|
||||||
for screen in all_large_screens:
|
for screen in all_large_screens:
|
||||||
if screen not in used_screens_set:
|
if screen not in used_screens_set:
|
||||||
piece = create_piece(world, player, [[screen.id, screen.id], [screen.id, screen.id]], overworld_screens)
|
base_id = screen.id
|
||||||
if options.large_screen_pool:
|
if options.split_large_screens:
|
||||||
piece.restriction = [0x00, 0x03, 0x05, 0x18, 0x1B, 0x1E, 0x30, 0x35]
|
for quadrant_offset in [0x00, 0x01, 0x08, 0x09]:
|
||||||
piece_list.append(piece)
|
piece = create_piece(world, player, [[base_id + quadrant_offset]], overworld_screens)
|
||||||
|
if options.large_screen_pool:
|
||||||
|
piece.restriction = [large_screen_id + quadrant_offset for large_screen_id in [0x00, 0x03, 0x05, 0x18, 0x1B, 0x1E, 0x30, 0x35]]
|
||||||
|
piece_list.append(piece)
|
||||||
|
else:
|
||||||
|
piece = create_piece(world, player, [[base_id, base_id + 0x01], [base_id + 0x08, base_id + 0x09]], overworld_screens)
|
||||||
|
if options.large_screen_pool:
|
||||||
|
piece.restriction = [0x00, 0x03, 0x05, 0x18, 0x1B, 0x1E, 0x30, 0x35]
|
||||||
|
piece_list.append(piece)
|
||||||
used_screens_set.add(screen)
|
used_screens_set.add(screen)
|
||||||
if world.owParallel[player]:
|
if world.owParallel[player]:
|
||||||
used_screens_set.add(screen.parallel)
|
used_screens_set.add(screen.parallel)
|
||||||
@@ -478,43 +487,50 @@ def create_piece_list(world: World, player: int, options: LayoutGeneratorOptions
|
|||||||
for k in range(piece.height):
|
for k in range(piece.height):
|
||||||
for l in range(piece.width):
|
for l in range(piece.width):
|
||||||
piece.crossed_groups[k].append(-1)
|
piece.crossed_groups[k].append(-1)
|
||||||
screen_id = piece.main.grid[k][l]
|
screen = piece.main.screens[k][l]
|
||||||
if screen_id != -1:
|
if screen:
|
||||||
piece.crossed_groups[k][l] = 1 if screen_id in crossed_group_b else 0
|
piece.crossed_groups[k][l] = 1 if screen.id in crossed_group_b else 0
|
||||||
else:
|
else:
|
||||||
if piece.parallel and piece.parallel.screens[k][l]:
|
if piece.parallel and piece.parallel.screens[k][l]:
|
||||||
piece.crossed_groups[k][l] = 1 if piece.parallel.grid[k][l] in crossed_group_b else 0
|
piece.crossed_groups[k][l] = 1 if piece.parallel.screens[k][l].id in crossed_group_b else 0
|
||||||
|
|
||||||
return piece_list
|
return piece_list
|
||||||
|
|
||||||
def create_piece(world: World, player: int, grid: List[List[int]], overworld_screens: Dict[int, Screen]) -> Piece:
|
def create_piece(world: World, player: int, grid: List[List[int]], overworld_screens: Dict[int, Screen]) -> Piece:
|
||||||
"""
|
"""
|
||||||
Create piece from grid of screen IDs
|
Create piece from grid of cell IDs
|
||||||
Takes 2D array of screen IDs and creates main and parallel pieces
|
Takes 2D array of cell IDs and creates main and parallel pieces
|
||||||
"""
|
"""
|
||||||
piece = Piece(
|
piece = Piece(
|
||||||
main=WorldPiece(screens=[]),
|
main=WorldPiece(),
|
||||||
width=len(grid[0]),
|
width=len(grid[0]),
|
||||||
height=len(grid)
|
height=len(grid)
|
||||||
)
|
)
|
||||||
|
|
||||||
if world.owParallel[player]:
|
if world.owParallel[player]:
|
||||||
piece.parallel = WorldPiece(screens=[])
|
piece.parallel = WorldPiece()
|
||||||
|
|
||||||
found_screens = set()
|
found_screens = set()
|
||||||
|
|
||||||
for i in range(piece.height):
|
for i in range(piece.height):
|
||||||
new_row = []
|
new_row = []
|
||||||
|
new_screen_row = []
|
||||||
new_row_parallel = []
|
new_row_parallel = []
|
||||||
piece.main.screens.append(new_row)
|
new_screen_row_parallel = []
|
||||||
|
piece.main.grid.append(new_row)
|
||||||
|
piece.main.screens.append(new_screen_row)
|
||||||
if world.owParallel[player]:
|
if world.owParallel[player]:
|
||||||
piece.parallel.screens.append(new_row_parallel)
|
piece.parallel.grid.append(new_row_parallel)
|
||||||
|
piece.parallel.screens.append(new_screen_row_parallel)
|
||||||
|
|
||||||
for j in range(piece.width):
|
for j in range(piece.width):
|
||||||
screen = overworld_screens.get(grid[i][j])
|
cell_id = grid[i][j]
|
||||||
new_row.append(screen)
|
new_row.append(cell_id)
|
||||||
if world.owParallel[player]:
|
screen = overworld_screens.get(get_screen_id_from_cell(cell_id))
|
||||||
new_row_parallel.append(screen.parallel if screen else None)
|
new_screen_row.append(screen)
|
||||||
|
if world.owParallel[player] and screen:
|
||||||
|
new_row_parallel.append(cell_id - screen.id + screen.parallel.id)
|
||||||
|
new_screen_row_parallel.append(screen.parallel)
|
||||||
|
|
||||||
if screen and screen not in found_screens:
|
if screen and screen not in found_screens:
|
||||||
found_screens.add(screen)
|
found_screens.add(screen)
|
||||||
@@ -532,14 +548,14 @@ def create_piece(world: World, player: int, grid: List[List[int]], overworld_scr
|
|||||||
def add_piece_data(world: World, player: int, piece: Piece, large_screen_quadrant_info: Dict[int, Dict], large_screen_quadrant_info_land: Dict[int, Dict], large_screen_quadrant_info_water: Dict[int, Dict]) -> None:
|
def add_piece_data(world: World, player: int, piece: Piece, large_screen_quadrant_info: Dict[int, Dict], large_screen_quadrant_info_land: Dict[int, Dict], large_screen_quadrant_info_water: Dict[int, Dict]) -> None:
|
||||||
"""
|
"""
|
||||||
Add computed data to piece
|
Add computed data to piece
|
||||||
Calls add_piece_grid_info for main and parallel pieces
|
Calls add_world_piece_edge_info for main and parallel pieces
|
||||||
"""
|
"""
|
||||||
num_pieces = 2 if piece.parallel else 1
|
num_pieces = 2 if piece.parallel else 1
|
||||||
for p in range(num_pieces):
|
for p in range(num_pieces):
|
||||||
world_piece = piece.main if p == 0 else piece.parallel
|
world_piece = piece.main if p == 0 else piece.parallel
|
||||||
world_piece.width = len(world_piece.screens[0])
|
world_piece.width = piece.width
|
||||||
world_piece.height = len(world_piece.screens)
|
world_piece.height = piece.height
|
||||||
add_piece_grid_info(world, player, world_piece, large_screen_quadrant_info, large_screen_quadrant_info_land, large_screen_quadrant_info_water)
|
add_world_piece_edge_info(world, player, world_piece, large_screen_quadrant_info, large_screen_quadrant_info_land, large_screen_quadrant_info_water)
|
||||||
|
|
||||||
piece.width = piece.main.width
|
piece.width = piece.main.width
|
||||||
piece.height = piece.main.height
|
piece.height = piece.main.height
|
||||||
@@ -572,12 +588,11 @@ def add_piece_data(world: World, player: int, piece: Piece, large_screen_quadran
|
|||||||
piece.edge_sides = 0
|
piece.edge_sides = 0
|
||||||
piece.max_edges_per_side = 0
|
piece.max_edges_per_side = 0
|
||||||
|
|
||||||
def add_piece_grid_info(world: World, player: int, piece: WorldPiece, large_screen_quadrant_info: Dict[int, Dict], large_screen_quadrant_info_land: Dict[int, Dict], large_screen_quadrant_info_water: Dict[int, Dict]) -> None:
|
def add_world_piece_edge_info(world: World, player: int, piece: WorldPiece, large_screen_quadrant_info: Dict[int, Dict], large_screen_quadrant_info_land: Dict[int, Dict], large_screen_quadrant_info_water: Dict[int, Dict]) -> None:
|
||||||
"""
|
"""
|
||||||
Populate piece edge information
|
Populate piece edge information
|
||||||
Initializes 8x8 edge arrays and extracts edges from screens
|
Initializes 8x8 edge arrays and extracts edges from screens
|
||||||
"""
|
"""
|
||||||
piece.grid = [[] for _ in range(8)]
|
|
||||||
piece.north_edges = [[] for _ in range(8)]
|
piece.north_edges = [[] for _ in range(8)]
|
||||||
piece.south_edges = [[] for _ in range(8)]
|
piece.south_edges = [[] for _ in range(8)]
|
||||||
piece.west_edges = [[] for _ in range(8)]
|
piece.west_edges = [[] for _ in range(8)]
|
||||||
@@ -591,7 +606,6 @@ def add_piece_grid_info(world: World, player: int, piece: WorldPiece, large_scre
|
|||||||
|
|
||||||
for k in range(piece.height):
|
for k in range(piece.height):
|
||||||
for l in range(piece.width):
|
for l in range(piece.width):
|
||||||
piece.grid[k].append(piece.screens[k][l].id if piece.screens[k][l] else -1)
|
|
||||||
piece.north_edges[k].append([])
|
piece.north_edges[k].append([])
|
||||||
piece.south_edges[k].append([])
|
piece.south_edges[k].append([])
|
||||||
piece.west_edges[k].append([])
|
piece.west_edges[k].append([])
|
||||||
@@ -603,38 +617,41 @@ def add_piece_grid_info(world: World, player: int, piece: WorldPiece, large_scre
|
|||||||
piece.west_edges_water[k].append([])
|
piece.west_edges_water[k].append([])
|
||||||
piece.east_edges_water[k].append([])
|
piece.east_edges_water[k].append([])
|
||||||
|
|
||||||
done_large = set()
|
|
||||||
for k in range(piece.height):
|
for k in range(piece.height):
|
||||||
for l in range(piece.width):
|
for l in range(piece.width):
|
||||||
screen = piece.screens[k][l]
|
screen = piece.screens[k][l]
|
||||||
if not screen:
|
if not screen:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
cell_id = piece.grid[k][l]
|
||||||
|
|
||||||
if screen.big:
|
if screen.big:
|
||||||
if screen.id not in done_large:
|
# Determine quadrant by subtracting cell ID from screen ID
|
||||||
done_large.add(screen.id)
|
# 0x00 = NW (top-left), 0x01 = NE (top-right), 0x08 = SW (bottom-left), 0x09 = SE (bottom-right)
|
||||||
quadrant_info = (large_screen_quadrant_info[screen.id] if world.owTerrain[player]
|
quadrant_offset = cell_id - screen.id
|
||||||
else large_screen_quadrant_info_land[screen.id])
|
if quadrant_offset == 0x00:
|
||||||
|
quadrant_name = "NW"
|
||||||
|
elif quadrant_offset == 0x01:
|
||||||
|
quadrant_name = "NE"
|
||||||
|
elif quadrant_offset == 0x08:
|
||||||
|
quadrant_name = "SW"
|
||||||
|
else:
|
||||||
|
quadrant_name = "SE"
|
||||||
|
|
||||||
piece.north_edges[k][l] = [e for e in quadrant_info["NW"][Direction.North] if not e.dest]
|
quadrant_info = (large_screen_quadrant_info[screen.id] if world.owTerrain[player]
|
||||||
piece.north_edges[k][l + 1] = [e for e in quadrant_info["NE"][Direction.North] if not e.dest]
|
else large_screen_quadrant_info_land[screen.id])
|
||||||
piece.south_edges[k + 1][l] = [e for e in quadrant_info["SW"][Direction.South] if not e.dest]
|
|
||||||
piece.south_edges[k + 1][l + 1] = [e for e in quadrant_info["SE"][Direction.South] if not e.dest]
|
|
||||||
piece.west_edges[k][l] = [e for e in quadrant_info["NW"][Direction.West] if not e.dest]
|
|
||||||
piece.west_edges[k + 1][l] = [e for e in quadrant_info["SW"][Direction.West] if not e.dest]
|
|
||||||
piece.east_edges[k][l + 1] = [e for e in quadrant_info["NE"][Direction.East] if not e.dest]
|
|
||||||
piece.east_edges[k + 1][l + 1] = [e for e in quadrant_info["SE"][Direction.East] if not e.dest]
|
|
||||||
|
|
||||||
if not world.owTerrain[player]:
|
piece.north_edges[k][l] = [e for e in quadrant_info[quadrant_name][Direction.North] if not e.dest]
|
||||||
quadrant_info = large_screen_quadrant_info_water[screen.id]
|
piece.south_edges[k][l] = [e for e in quadrant_info[quadrant_name][Direction.South] if not e.dest]
|
||||||
piece.north_edges_water[k][l] = [e for e in quadrant_info["NW"][Direction.North] if not e.dest]
|
piece.west_edges[k][l] = [e for e in quadrant_info[quadrant_name][Direction.West] if not e.dest]
|
||||||
piece.north_edges_water[k][l + 1] = [e for e in quadrant_info["NE"][Direction.North] if not e.dest]
|
piece.east_edges[k][l] = [e for e in quadrant_info[quadrant_name][Direction.East] if not e.dest]
|
||||||
piece.south_edges_water[k + 1][l] = [e for e in quadrant_info["SW"][Direction.South] if not e.dest]
|
|
||||||
piece.south_edges_water[k + 1][l + 1] = [e for e in quadrant_info["SE"][Direction.South] if not e.dest]
|
if not world.owTerrain[player]:
|
||||||
piece.west_edges_water[k][l] = [e for e in quadrant_info["NW"][Direction.West] if not e.dest]
|
quadrant_info_water = large_screen_quadrant_info_water[screen.id]
|
||||||
piece.west_edges_water[k + 1][l] = [e for e in quadrant_info["SW"][Direction.West] if not e.dest]
|
piece.north_edges_water[k][l] = [e for e in quadrant_info_water[quadrant_name][Direction.North] if not e.dest]
|
||||||
piece.east_edges_water[k][l + 1] = [e for e in quadrant_info["NE"][Direction.East] if not e.dest]
|
piece.south_edges_water[k][l] = [e for e in quadrant_info_water[quadrant_name][Direction.South] if not e.dest]
|
||||||
piece.east_edges_water[k + 1][l + 1] = [e for e in quadrant_info["SE"][Direction.East] if not e.dest]
|
piece.west_edges_water[k][l] = [e for e in quadrant_info_water[quadrant_name][Direction.West] if not e.dest]
|
||||||
|
piece.east_edges_water[k][l] = [e for e in quadrant_info_water[quadrant_name][Direction.East] if not e.dest]
|
||||||
else:
|
else:
|
||||||
for edge in sorted(screen.edges.values(), key=lambda e: e.midpoint):
|
for edge in sorted(screen.edges.values(), key=lambda e: e.midpoint):
|
||||||
if not edge.dest:
|
if not edge.dest:
|
||||||
@@ -651,6 +668,19 @@ def add_piece_grid_info(world: World, player: int, piece: WorldPiece, large_scre
|
|||||||
target = piece.east_edges[k][l] if world.owTerrain[player] or edge.terrain != Terrain.Water else piece.east_edges_water[k][l]
|
target = piece.east_edges[k][l] if world.owTerrain[player] or edge.terrain != Terrain.Water else piece.east_edges_water[k][l]
|
||||||
target.append(edge)
|
target.append(edge)
|
||||||
|
|
||||||
|
def get_screen_id_from_cell(cell_id: int) -> int:
|
||||||
|
"""Get the base screen ID from a cell ID.
|
||||||
|
|
||||||
|
For large screens, returns the top-left corner ID.
|
||||||
|
For small screens, returns the cell ID unchanged.
|
||||||
|
"""
|
||||||
|
base_id = cell_id & 0xBF # Remove world bit if present
|
||||||
|
# Check if this is a quadrant of a large screen
|
||||||
|
for large_id in large_screen_ids:
|
||||||
|
if base_id in [large_id, large_id + 0x01, large_id + 0x08, large_id + 0x09]:
|
||||||
|
return large_id | (cell_id & 0x40) # Preserve world bit
|
||||||
|
return cell_id
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# PLACEMENT ALGORITHM
|
# PLACEMENT ALGORITHM
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -1316,11 +1346,22 @@ def format_grid_for_spoiler(grid: List[List[int]]) -> str:
|
|||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
def is_same_large_screen(grid: List[List[int]], row1: int, col1: int, row2: int, col2: int) -> bool:
|
def is_same_large_screen(grid: List[List[int]], row1: int, col1: int, row2: int, col2: int) -> bool:
|
||||||
id1 = grid[row1 % 8][col1 % 8]
|
"""Checks if two adjacent cells belong to the same large screen with correct quadrant positions."""
|
||||||
id2 = grid[row2 % 8][col2 % 8]
|
id1, id2 = grid[row1 % 8][col1 % 8], grid[row2 % 8][col2 % 8]
|
||||||
if id1 == -1 or id2 == -1:
|
if id1 == -1 or id2 == -1:
|
||||||
return False
|
return False
|
||||||
return id1 == id2 and id1 in large_screen_ids
|
base1, base2 = get_screen_id_from_cell(id1), get_screen_id_from_cell(id2)
|
||||||
|
if base1 != base2 or base1 not in large_screen_ids:
|
||||||
|
return False
|
||||||
|
# Get quadrant offsets (0x00=NW, 0x01=NE, 0x08=SW, 0x09=SE)
|
||||||
|
q1, q2 = (id1 & 0xBF) - (base1 & 0xBF), (id2 & 0xBF) - (base2 & 0xBF)
|
||||||
|
# Swap if cell2 is before cell1
|
||||||
|
if col1 > col2 or row1 > row2:
|
||||||
|
q1, q2 = q2, q1
|
||||||
|
# Check valid adjacency: east (0x00->0x01, 0x08->0x09) or south (0x00->0x08, 0x01->0x09)
|
||||||
|
if col1 != col2:
|
||||||
|
return (q1, q2) in [(0x00, 0x01), (0x08, 0x09)]
|
||||||
|
return (q1, q2) in [(0x00, 0x08), (0x01, 0x09)]
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# MAIN EXECUTION
|
# MAIN EXECUTION
|
||||||
@@ -1347,6 +1388,7 @@ def generate_random_grid_layout(world: World, player: int, connected_edges: List
|
|||||||
options = LayoutGeneratorOptions(
|
options = LayoutGeneratorOptions(
|
||||||
horizontal_wrap=horizontal_wrap,
|
horizontal_wrap=horizontal_wrap,
|
||||||
vertical_wrap=vertical_wrap,
|
vertical_wrap=vertical_wrap,
|
||||||
|
split_large_screens=False,
|
||||||
large_screen_pool=False,
|
large_screen_pool=False,
|
||||||
distortion_chance=0.0,
|
distortion_chance=0.0,
|
||||||
random_order=6 if world.owParallel[player] else 12,
|
random_order=6 if world.owParallel[player] else 12,
|
||||||
@@ -1385,19 +1427,9 @@ def generate_random_grid_layout(world: World, player: int, connected_edges: List
|
|||||||
connect_edges_for_screen_layout(world, player, result.grid_info, options, connected_edges, prio_edges, overworld_screens, True)
|
connect_edges_for_screen_layout(world, player, result.grid_info, options, connected_edges, prio_edges, overworld_screens, True)
|
||||||
grid = result.grid_info.grid
|
grid = result.grid_info.grid
|
||||||
|
|
||||||
# Make new grid containing cell IDs for the overworld map
|
world.owgrid[player] = grid
|
||||||
map_grid = copy.deepcopy(grid)
|
world.owlayoutmap_lw[player] = {id & 0xBF: i for i, id in enumerate(sum(grid[0], []))}
|
||||||
for w in range(2):
|
world.owlayoutmap_dw[player] = {id & 0xBF: i for i, id in enumerate(sum(grid[1], []))}
|
||||||
for i in range(8):
|
|
||||||
for j in range(8):
|
|
||||||
screen_id = map_grid[w][i][j]
|
|
||||||
if screen_id in large_screen_ids and map_grid[w][i][(j + 1) % 8] == screen_id and map_grid[w][(i + 1) % 8][j] == screen_id and map_grid[w][(i + 1) % 8][(j + 1) % 8] == screen_id:
|
|
||||||
map_grid[w][i][(j + 1) % 8] = screen_id + 0x01
|
|
||||||
map_grid[w][(i + 1) % 8][j] = screen_id + 0x08
|
|
||||||
map_grid[w][(i + 1) % 8][(j + 1) % 8] = screen_id + 0x09
|
|
||||||
world.owgrid[player] = map_grid
|
|
||||||
world.owlayoutmap_lw[player] = {id & 0xBF: i for i, id in enumerate(sum(map_grid[0], []))}
|
|
||||||
world.owlayoutmap_dw[player] = {id & 0xBF: i for i, id in enumerate(sum(map_grid[1], []))}
|
|
||||||
|
|
||||||
world.spoiler.set_map('layout_grid_lw', format_grid_for_spoiler(grid[0]), grid[0], player)
|
world.spoiler.set_map('layout_grid_lw', format_grid_for_spoiler(grid[0]), grid[0], player)
|
||||||
if not world.owParallel[player]:
|
if not world.owParallel[player]:
|
||||||
|
|||||||
@@ -4,7 +4,18 @@ from datetime import datetime
|
|||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
from BaseClasses import Direction, OWEdge
|
from BaseClasses import Direction, OWEdge
|
||||||
from source.overworld.LayoutGenerator import Screen
|
from source.overworld.LayoutGenerator import Screen, get_screen_id_from_cell
|
||||||
|
|
||||||
|
def get_quadrant_from_cell_id(cell_id: int, screen_id: int) -> str:
|
||||||
|
offset = (cell_id & 0xBF) - (screen_id & 0xBF)
|
||||||
|
if offset == 0x00:
|
||||||
|
return "NW"
|
||||||
|
elif offset == 0x01:
|
||||||
|
return "NE"
|
||||||
|
elif offset == 0x08:
|
||||||
|
return "SW"
|
||||||
|
else:
|
||||||
|
return "SE"
|
||||||
|
|
||||||
def get_edge_lists(grid: List[List[List[int]]],
|
def get_edge_lists(grid: List[List[List[int]]],
|
||||||
overworld_screens: Dict[int, Screen],
|
overworld_screens: Dict[int, Screen],
|
||||||
@@ -13,7 +24,7 @@ def get_edge_lists(grid: List[List[List[int]]],
|
|||||||
Get list of edges for each cell and direction.
|
Get list of edges for each cell and direction.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
grid: 3D list [world][row][col] containing screen IDs
|
grid: 3D list [world][row][col] containing cell IDs
|
||||||
overworld_screens: Dict of screen_id -> Screen objects
|
overworld_screens: Dict of screen_id -> Screen objects
|
||||||
large_screen_quadrant_info: Dict of screen_id -> quadrant info for large screens
|
large_screen_quadrant_info: Dict of screen_id -> quadrant info for large screens
|
||||||
|
|
||||||
@@ -24,47 +35,27 @@ def get_edge_lists(grid: List[List[List[int]]],
|
|||||||
GRID_SIZE = 8
|
GRID_SIZE = 8
|
||||||
edge_lists = {}
|
edge_lists = {}
|
||||||
|
|
||||||
# Large screen base IDs
|
|
||||||
large_screen_base_ids = [0x00, 0x03, 0x05, 0x18, 0x1B, 0x1E, 0x30, 0x35,
|
|
||||||
0x40, 0x43, 0x45, 0x58, 0x5B, 0x5E, 0x70, 0x75]
|
|
||||||
|
|
||||||
for world_idx in range(2):
|
for world_idx in range(2):
|
||||||
# Build a map of screen_id -> list of (row, col) positions for large screens
|
|
||||||
large_screen_positions = {}
|
|
||||||
for row in range(GRID_SIZE):
|
for row in range(GRID_SIZE):
|
||||||
for col in range(GRID_SIZE):
|
for col in range(GRID_SIZE):
|
||||||
screen_id = grid[world_idx][row][col]
|
cell_id = grid[world_idx][row][col]
|
||||||
if screen_id != -1 and screen_id in large_screen_base_ids:
|
|
||||||
if screen_id not in large_screen_positions:
|
|
||||||
large_screen_positions[screen_id] = []
|
|
||||||
large_screen_positions[screen_id].append((row, col))
|
|
||||||
|
|
||||||
for row in range(GRID_SIZE):
|
if cell_id == -1:
|
||||||
for col in range(GRID_SIZE):
|
|
||||||
screen_id = grid[world_idx][row][col]
|
|
||||||
|
|
||||||
if screen_id == -1:
|
|
||||||
# Empty cell - no edges
|
# Empty cell - no edges
|
||||||
for direction in [Direction.North, Direction.South, Direction.East, Direction.West]:
|
for direction in [Direction.North, Direction.South, Direction.East, Direction.West]:
|
||||||
edge_lists[(world_idx, row, col, direction)] = []
|
edge_lists[(world_idx, row, col, direction)] = []
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
screen_id = get_screen_id_from_cell(cell_id)
|
||||||
screen = overworld_screens.get(screen_id)
|
screen = overworld_screens.get(screen_id)
|
||||||
if not screen:
|
if not screen:
|
||||||
for direction in [Direction.North, Direction.South, Direction.East, Direction.West]:
|
for direction in [Direction.North, Direction.South, Direction.East, Direction.West]:
|
||||||
edge_lists[(world_idx, row, col, direction)] = []
|
edge_lists[(world_idx, row, col, direction)] = []
|
||||||
continue
|
continue
|
||||||
|
|
||||||
is_large = screen_id in large_screen_base_ids
|
if screen.big:
|
||||||
|
# For large screens, determine quadrant from cell ID
|
||||||
if is_large:
|
quadrant = get_quadrant_from_cell_id(cell_id, screen_id)
|
||||||
# For large screens, determine which quadrant this cell is
|
|
||||||
# Find all positions of this large screen and determine quadrant
|
|
||||||
positions = large_screen_positions.get(screen_id, [(row, col)])
|
|
||||||
|
|
||||||
# Determine quadrant by finding relative position
|
|
||||||
# The quadrant is determined by which cells are adjacent
|
|
||||||
quadrant = determine_large_screen_quadrant(row, col, positions, GRID_SIZE)
|
|
||||||
|
|
||||||
# Get edges for this quadrant
|
# Get edges for this quadrant
|
||||||
if screen_id in large_screen_quadrant_info:
|
if screen_id in large_screen_quadrant_info:
|
||||||
@@ -85,45 +76,6 @@ def get_edge_lists(grid: List[List[List[int]]],
|
|||||||
|
|
||||||
return edge_lists
|
return edge_lists
|
||||||
|
|
||||||
def determine_large_screen_quadrant(row: int, col: int, positions: List[tuple], grid_size: int) -> str:
|
|
||||||
"""
|
|
||||||
Determine which quadrant (NW, NE, SW, SE) a cell is in for a large screen.
|
|
||||||
Handles wrapping correctly by checking adjacency patterns.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
row: Current cell row
|
|
||||||
col: Current cell column
|
|
||||||
positions: List of all (row, col) positions for this large screen
|
|
||||||
grid_size: Size of the grid (8)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Quadrant string: "NW", "NE", "SW", or "SE"
|
|
||||||
"""
|
|
||||||
positions_set = set(positions)
|
|
||||||
|
|
||||||
# Check which adjacent cells also belong to this large screen
|
|
||||||
has_right = ((row, (col + 1) % grid_size) in positions_set)
|
|
||||||
has_below = (((row + 1) % grid_size, col) in positions_set)
|
|
||||||
has_left = ((row, (col - 1) % grid_size) in positions_set)
|
|
||||||
has_above = (((row - 1) % grid_size, col) in positions_set)
|
|
||||||
|
|
||||||
# Determine quadrant based on adjacency
|
|
||||||
# NW: has right and below neighbors
|
|
||||||
# NE: has left and below neighbors
|
|
||||||
# SW: has right and above neighbors
|
|
||||||
# SE: has left and above neighbors
|
|
||||||
|
|
||||||
if has_right and has_below:
|
|
||||||
return "NW"
|
|
||||||
elif has_left and has_below:
|
|
||||||
return "NE"
|
|
||||||
elif has_right and has_above:
|
|
||||||
return "SW"
|
|
||||||
elif has_left and has_above:
|
|
||||||
return "SE"
|
|
||||||
else:
|
|
||||||
raise Exception("?")
|
|
||||||
|
|
||||||
def is_crossed_edge(edge: OWEdge, overworld_screens: Dict[int, Screen]) -> bool:
|
def is_crossed_edge(edge: OWEdge, overworld_screens: Dict[int, Screen]) -> bool:
|
||||||
if edge.dest is None:
|
if edge.dest is None:
|
||||||
return False
|
return False
|
||||||
@@ -132,6 +84,40 @@ def is_crossed_edge(edge: OWEdge, overworld_screens: Dict[int, Screen]) -> bool:
|
|||||||
dest_screen = overworld_screens.get(edge.dest.owIndex)
|
dest_screen = overworld_screens.get(edge.dest.owIndex)
|
||||||
return source_screen.dark_world != dest_screen.dark_world
|
return source_screen.dark_world != dest_screen.dark_world
|
||||||
|
|
||||||
|
def are_large_screen_cells_connected(cell_id1: int, cell_id2: int, quadrant1: str, quadrant2: str, direction: str) -> bool:
|
||||||
|
"""
|
||||||
|
Check if two cells of a large screen are connected (should have no border between them).
|
||||||
|
|
||||||
|
For cells to be connected:
|
||||||
|
1. They must be from the same large screen (same base screen ID)
|
||||||
|
2. Their quadrants must be adjacent in the expected direction
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cell_id1: Cell ID of the first cell
|
||||||
|
cell_id2: Cell ID of the second cell
|
||||||
|
quadrant1: Quadrant of the first cell ("NW", "NE", "SW", "SE")
|
||||||
|
quadrant2: Quadrant of the second cell
|
||||||
|
direction: Direction from cell1 to cell2 ("east", "south")
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the cells should have no border between them
|
||||||
|
"""
|
||||||
|
# Must be from the same large screen
|
||||||
|
screen_id1 = get_screen_id_from_cell(cell_id1)
|
||||||
|
screen_id2 = get_screen_id_from_cell(cell_id2)
|
||||||
|
if screen_id1 != screen_id2:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Check if quadrants are properly adjacent
|
||||||
|
if direction == "east":
|
||||||
|
# For east connection: NW->NE or SW->SE
|
||||||
|
return (quadrant1 == "NW" and quadrant2 == "NE") or (quadrant1 == "SW" and quadrant2 == "SE")
|
||||||
|
elif direction == "south":
|
||||||
|
# For south connection: NW->SW or NE->SE
|
||||||
|
return (quadrant1 == "NW" and quadrant2 == "SW") or (quadrant1 == "NE" and quadrant2 == "SE")
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def visualize_layout(grid: List[List[List[int]]], output_dir: str,
|
def visualize_layout(grid: List[List[List[int]]], output_dir: str,
|
||||||
overworld_screens: Dict[int, Screen],
|
overworld_screens: Dict[int, Screen],
|
||||||
large_screen_quadrant_info: Dict[int, Dict]) -> None:
|
large_screen_quadrant_info: Dict[int, Dict]) -> None:
|
||||||
@@ -162,78 +148,42 @@ def visualize_layout(grid: List[List[List[int]]], output_dir: str,
|
|||||||
output_height = world_height
|
output_height = world_height
|
||||||
output_img = Image.new('RGB', (output_width, output_height), color='black')
|
output_img = Image.new('RGB', (output_width, output_height), color='black')
|
||||||
|
|
||||||
# Large screen base IDs (defined once for reuse)
|
|
||||||
large_screen_base_ids = [0x00, 0x03, 0x05, 0x18, 0x1B, 0x1E, 0x30, 0x35,
|
|
||||||
0x40, 0x43, 0x45, 0x58, 0x5B, 0x5E, 0x70, 0x75]
|
|
||||||
|
|
||||||
# Process both worlds
|
# Process both worlds
|
||||||
for world_idx in range(2):
|
for world_idx in range(2):
|
||||||
x_offset = 0 if world_idx == 0 else (world_width + gap)
|
x_offset = 0 if world_idx == 0 else (world_width + gap)
|
||||||
|
|
||||||
# Build a map of screen_id -> list of (row, col) positions for large screens
|
|
||||||
large_screen_positions = {}
|
|
||||||
for row in range(GRID_SIZE):
|
|
||||||
for col in range(GRID_SIZE):
|
|
||||||
screen_id = grid[world_idx][row][col]
|
|
||||||
if screen_id != -1 and screen_id in large_screen_base_ids:
|
|
||||||
if screen_id not in large_screen_positions:
|
|
||||||
large_screen_positions[screen_id] = []
|
|
||||||
large_screen_positions[screen_id].append((row, col))
|
|
||||||
|
|
||||||
# Process each cell in the grid individually
|
# Process each cell in the grid individually
|
||||||
# This handles wrapped large screens correctly by drawing each quadrant separately
|
|
||||||
for row in range(GRID_SIZE):
|
for row in range(GRID_SIZE):
|
||||||
for col in range(GRID_SIZE):
|
for col in range(GRID_SIZE):
|
||||||
screen_id = grid[world_idx][row][col]
|
cell_id = grid[world_idx][row][col]
|
||||||
|
|
||||||
if screen_id == -1:
|
if cell_id == -1:
|
||||||
# Empty cell - fill with black (already black from initialization)
|
# Empty cell - fill with black (already black from initialization)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
is_large = screen_id in large_screen_base_ids
|
screen_id = get_screen_id_from_cell(cell_id)
|
||||||
|
screen = overworld_screens.get(screen_id)
|
||||||
|
if not screen:
|
||||||
|
continue
|
||||||
|
|
||||||
# Calculate source position in the world image
|
is_large = screen.big
|
||||||
source_row = (screen_id % 0x40) >> 3
|
|
||||||
source_col = screen_id % 0x08
|
|
||||||
world_img = lightworld_img if screen_id < 0x40 else darkworld_img
|
|
||||||
|
|
||||||
if is_large:
|
# Calculate source position in the world image based on cell_id
|
||||||
# For large screens, determine which quadrant this cell represents
|
# For large screens, cell_id already encodes the quadrant position
|
||||||
positions = large_screen_positions.get(screen_id, [(row, col)])
|
source_row = (cell_id % 0x40) >> 3
|
||||||
quadrant = determine_large_screen_quadrant(row, col, positions, GRID_SIZE)
|
source_col = cell_id % 0x08
|
||||||
|
world_img = lightworld_img if cell_id < 0x40 else darkworld_img
|
||||||
|
|
||||||
# Map quadrant to source offset within the 2x2 large screen
|
source_x = source_col * SOURCE_CELL_SIZE
|
||||||
quadrant_offsets = {
|
source_y = source_row * SOURCE_CELL_SIZE
|
||||||
"NW": (0, 0),
|
|
||||||
"NE": (1, 0),
|
|
||||||
"SW": (0, 1),
|
|
||||||
"SE": (1, 1)
|
|
||||||
}
|
|
||||||
q_col_offset, q_row_offset = quadrant_offsets[quadrant]
|
|
||||||
|
|
||||||
# Calculate source position for this quadrant
|
# Crop single cell from source
|
||||||
source_x = (source_col + q_col_offset) * SOURCE_CELL_SIZE
|
cropped = world_img.crop((
|
||||||
source_y = (source_row + q_row_offset) * SOURCE_CELL_SIZE
|
source_x,
|
||||||
|
source_y,
|
||||||
# Crop single cell from source (the specific quadrant)
|
source_x + SOURCE_CELL_SIZE,
|
||||||
cropped = world_img.crop((
|
source_y + SOURCE_CELL_SIZE
|
||||||
source_x,
|
))
|
||||||
source_y,
|
|
||||||
source_x + SOURCE_CELL_SIZE,
|
|
||||||
source_y + SOURCE_CELL_SIZE
|
|
||||||
))
|
|
||||||
else:
|
|
||||||
# Small screen (1x1)
|
|
||||||
source_x = source_col * SOURCE_CELL_SIZE
|
|
||||||
source_y = source_row * SOURCE_CELL_SIZE
|
|
||||||
|
|
||||||
# Crop single cell from source
|
|
||||||
cropped = world_img.crop((
|
|
||||||
source_x,
|
|
||||||
source_y,
|
|
||||||
source_x + SOURCE_CELL_SIZE,
|
|
||||||
source_y + SOURCE_CELL_SIZE
|
|
||||||
))
|
|
||||||
|
|
||||||
# Resize to output size (64x64 pixels)
|
# Resize to output size (64x64 pixels)
|
||||||
resized = cropped.resize(
|
resized = cropped.resize(
|
||||||
@@ -257,52 +207,93 @@ def visualize_layout(grid: List[List[List[int]]], output_dir: str,
|
|||||||
for world_idx in range(2):
|
for world_idx in range(2):
|
||||||
x_offset = 0 if world_idx == 0 else (world_width + gap)
|
x_offset = 0 if world_idx == 0 else (world_width + gap)
|
||||||
|
|
||||||
# Build large screen positions map for this world
|
|
||||||
large_screen_positions = {}
|
|
||||||
for row in range(GRID_SIZE):
|
|
||||||
for col in range(GRID_SIZE):
|
|
||||||
screen_id = grid[world_idx][row][col]
|
|
||||||
if screen_id != -1 and screen_id in large_screen_base_ids:
|
|
||||||
if screen_id not in large_screen_positions:
|
|
||||||
large_screen_positions[screen_id] = []
|
|
||||||
large_screen_positions[screen_id].append((row, col))
|
|
||||||
|
|
||||||
# Draw borders for each cell
|
# Draw borders for each cell
|
||||||
|
# For large screens, only draw borders where cells are not connected
|
||||||
for row in range(GRID_SIZE):
|
for row in range(GRID_SIZE):
|
||||||
for col in range(GRID_SIZE):
|
for col in range(GRID_SIZE):
|
||||||
screen_id = grid[world_idx][row][col]
|
cell_id = grid[world_idx][row][col]
|
||||||
|
|
||||||
if screen_id == -1:
|
if cell_id == -1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
is_large = screen_id in large_screen_base_ids
|
screen_id = get_screen_id_from_cell(cell_id)
|
||||||
|
screen = overworld_screens.get(screen_id)
|
||||||
|
if not screen:
|
||||||
|
continue
|
||||||
|
|
||||||
|
is_large = screen.big
|
||||||
|
|
||||||
dest_x = x_offset + col * OUTPUT_CELL_SIZE
|
dest_x = x_offset + col * OUTPUT_CELL_SIZE
|
||||||
dest_y = row * OUTPUT_CELL_SIZE
|
dest_y = row * OUTPUT_CELL_SIZE
|
||||||
|
|
||||||
if is_large:
|
if is_large:
|
||||||
# For large screens, determine which quadrant this cell is
|
quadrant = get_quadrant_from_cell_id(cell_id, screen_id)
|
||||||
positions = large_screen_positions.get(screen_id, [(row, col)])
|
|
||||||
quadrant = determine_large_screen_quadrant(row, col, positions, GRID_SIZE)
|
|
||||||
|
|
||||||
# Draw border only on the outer edges of the large screen
|
# Check each border direction
|
||||||
# (not on internal edges between quadrants)
|
# Top border: draw if this is a north quadrant OR if the cell above is not connected
|
||||||
# NW: draw top and left borders
|
draw_top = True
|
||||||
# NE: draw top and right borders
|
|
||||||
# SW: draw bottom and left borders
|
|
||||||
# SE: draw bottom and right borders
|
|
||||||
|
|
||||||
if quadrant in ["NW", "NE"]:
|
|
||||||
# Draw top border
|
|
||||||
draw.line([(dest_x, dest_y), (dest_x + OUTPUT_CELL_SIZE - 1, dest_y)], fill='black', width=BORDER_WIDTH)
|
|
||||||
if quadrant in ["SW", "SE"]:
|
if quadrant in ["SW", "SE"]:
|
||||||
# Draw bottom border
|
# Check if cell above is connected
|
||||||
draw.line([(dest_x, dest_y + OUTPUT_CELL_SIZE - 1), (dest_x + OUTPUT_CELL_SIZE - 1, dest_y + OUTPUT_CELL_SIZE - 1)], fill='black', width=BORDER_WIDTH)
|
above_row = (row - 1) % GRID_SIZE
|
||||||
if quadrant in ["NW", "SW"]:
|
above_cell_id = grid[world_idx][above_row][col]
|
||||||
# Draw left border
|
if above_cell_id != -1:
|
||||||
draw.line([(dest_x, dest_y), (dest_x, dest_y + OUTPUT_CELL_SIZE - 1)], fill='black', width=BORDER_WIDTH)
|
above_screen_id = get_screen_id_from_cell(above_cell_id)
|
||||||
|
above_screen = overworld_screens.get(above_screen_id)
|
||||||
|
if above_screen and above_screen.big:
|
||||||
|
above_quadrant = get_quadrant_from_cell_id(above_cell_id, above_screen_id)
|
||||||
|
if are_large_screen_cells_connected(above_cell_id, cell_id, above_quadrant, quadrant, "south"):
|
||||||
|
draw_top = False
|
||||||
|
|
||||||
|
# Bottom border: draw if this is a south quadrant OR if the cell below is not connected
|
||||||
|
draw_bottom = True
|
||||||
|
if quadrant in ["NW", "NE"]:
|
||||||
|
# Check if cell below is connected
|
||||||
|
below_row = (row + 1) % GRID_SIZE
|
||||||
|
below_cell_id = grid[world_idx][below_row][col]
|
||||||
|
if below_cell_id != -1:
|
||||||
|
below_screen_id = get_screen_id_from_cell(below_cell_id)
|
||||||
|
below_screen = overworld_screens.get(below_screen_id)
|
||||||
|
if below_screen and below_screen.big:
|
||||||
|
below_quadrant = get_quadrant_from_cell_id(below_cell_id, below_screen_id)
|
||||||
|
if are_large_screen_cells_connected(cell_id, below_cell_id, quadrant, below_quadrant, "south"):
|
||||||
|
draw_bottom = False
|
||||||
|
|
||||||
|
# Left border: draw if this is a west quadrant OR if the cell to the left is not connected
|
||||||
|
draw_left = True
|
||||||
if quadrant in ["NE", "SE"]:
|
if quadrant in ["NE", "SE"]:
|
||||||
# Draw right border
|
# Check if cell to the left is connected
|
||||||
|
left_col = (col - 1) % GRID_SIZE
|
||||||
|
left_cell_id = grid[world_idx][row][left_col]
|
||||||
|
if left_cell_id != -1:
|
||||||
|
left_screen_id = get_screen_id_from_cell(left_cell_id)
|
||||||
|
left_screen = overworld_screens.get(left_screen_id)
|
||||||
|
if left_screen and left_screen.big:
|
||||||
|
left_quadrant = get_quadrant_from_cell_id(left_cell_id, left_screen_id)
|
||||||
|
if are_large_screen_cells_connected(left_cell_id, cell_id, left_quadrant, quadrant, "east"):
|
||||||
|
draw_left = False
|
||||||
|
|
||||||
|
# Right border: draw if this is an east quadrant OR if the cell to the right is not connected
|
||||||
|
draw_right = True
|
||||||
|
if quadrant in ["NW", "SW"]:
|
||||||
|
# Check if cell to the right is connected
|
||||||
|
right_col = (col + 1) % GRID_SIZE
|
||||||
|
right_cell_id = grid[world_idx][row][right_col]
|
||||||
|
if right_cell_id != -1:
|
||||||
|
right_screen_id = get_screen_id_from_cell(right_cell_id)
|
||||||
|
right_screen = overworld_screens.get(right_screen_id)
|
||||||
|
if right_screen and right_screen.big:
|
||||||
|
right_quadrant = get_quadrant_from_cell_id(right_cell_id, right_screen_id)
|
||||||
|
if are_large_screen_cells_connected(cell_id, right_cell_id, quadrant, right_quadrant, "east"):
|
||||||
|
draw_right = False
|
||||||
|
|
||||||
|
# Draw the borders
|
||||||
|
if draw_top:
|
||||||
|
draw.line([(dest_x, dest_y), (dest_x + OUTPUT_CELL_SIZE - 1, dest_y)], fill='black', width=BORDER_WIDTH)
|
||||||
|
if draw_bottom:
|
||||||
|
draw.line([(dest_x, dest_y + OUTPUT_CELL_SIZE - 1), (dest_x + OUTPUT_CELL_SIZE - 1, dest_y + OUTPUT_CELL_SIZE - 1)], fill='black', width=BORDER_WIDTH)
|
||||||
|
if draw_left:
|
||||||
|
draw.line([(dest_x, dest_y), (dest_x, dest_y + OUTPUT_CELL_SIZE - 1)], fill='black', width=BORDER_WIDTH)
|
||||||
|
if draw_right:
|
||||||
draw.line([(dest_x + OUTPUT_CELL_SIZE - 1, dest_y), (dest_x + OUTPUT_CELL_SIZE - 1, dest_y + OUTPUT_CELL_SIZE - 1)], fill='black', width=BORDER_WIDTH)
|
draw.line([(dest_x + OUTPUT_CELL_SIZE - 1, dest_y), (dest_x + OUTPUT_CELL_SIZE - 1, dest_y + OUTPUT_CELL_SIZE - 1)], fill='black', width=BORDER_WIDTH)
|
||||||
else:
|
else:
|
||||||
# Small screen - draw border around single cell
|
# Small screen - draw border around single cell
|
||||||
@@ -315,8 +306,8 @@ def visualize_layout(grid: List[List[List[int]]], output_dir: str,
|
|||||||
# Draw edge connection indicators for each cell
|
# Draw edge connection indicators for each cell
|
||||||
for row in range(GRID_SIZE):
|
for row in range(GRID_SIZE):
|
||||||
for col in range(GRID_SIZE):
|
for col in range(GRID_SIZE):
|
||||||
screen_id = grid[world_idx][row][col]
|
cell_id = grid[world_idx][row][col]
|
||||||
if screen_id == -1:
|
if cell_id == -1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
dest_x = x_offset + col * OUTPUT_CELL_SIZE
|
dest_x = x_offset + col * OUTPUT_CELL_SIZE
|
||||||
|
|||||||
Reference in New Issue
Block a user