diff --git a/src/game/engine/src/autoloads/biome_registry.gd b/src/game/engine/src/autoloads/biome_registry.gd index 6a038975..e1e3ed9f 100644 --- a/src/game/engine/src/autoloads/biome_registry.gd +++ b/src/game/engine/src/autoloads/biome_registry.gd @@ -39,6 +39,27 @@ func rebuild_from_data() -> void: _reverse_cache[tag] = [] as Array[String] _reverse_cache[tag].append(biome_id) + # Fold in legacy water terrains from terrain.json (ocean, coast, lake, + # inland_sea) that may not have matching entries in biomes.json. Without + # this, map generation code that queries BiomeRegistry for "is_water" + # treats water tiles as land and mis-classifies whole maps. + for terrain: Dictionary in DataLoader.get_all_terrains(): + var terrain_id: String = terrain.get("id", "") + if terrain_id.is_empty() or _tag_cache.has(terrain_id): + continue + var flags: Array = terrain.get("flags", []) + var derived: Array[String] = [] + if "water" in flags: + derived.append("is_water") + if derived.is_empty(): + continue + _tag_cache[terrain_id] = derived + for tag: String in derived: + if not _reverse_cache.has(tag): + _reverse_cache[tag] = [] as Array[String] + if terrain_id not in _reverse_cache[tag]: + _reverse_cache[tag].append(terrain_id) + _loaded = true diff --git a/src/game/engine/src/generation/map_generator.gd b/src/game/engine/src/generation/map_generator.gd index bd9304a3..96ad24eb 100644 --- a/src/game/engine/src/generation/map_generator.gd +++ b/src/game/engine/src/generation/map_generator.gd @@ -38,9 +38,6 @@ var _settings: Dictionary = {} func generate(settings: Dictionary) -> RefCounted: - print("[mapgen] generate() called with map_type=%s map_size=%s" % [ - settings.get("map_type", "?"), settings.get("map_size", "?"), - ]) ## Generate a complete map from settings. ## ## Settings keys: @@ -179,28 +176,11 @@ func _generate_terrain(game_map: RefCounted, type_data: Dictionary) -> void: # Stage 7b: Derive substrate_id from elevation + geology _derive_substrates(game_map) - var _dbg_land_before_patches: int = 0 - for axial: Vector2i in game_map.tiles: - if not BiomeRegistry.has_tag(game_map.tiles[axial].biome_id, "is_water"): - _dbg_land_before_patches += 1 - print("[mapgen] before_patches land=%d" % _dbg_land_before_patches) - # Stage 8: Terrain patch expansion TerrainRefinerScript.assign_terrain_patches( game_map, type_data, _elevation, _moisture, _temperature, _rng ) - var _dbg_land_after_patches: int = 0 - var _dbg_biomes: Dictionary = {} - for axial: Vector2i in game_map.tiles: - var bid: String = game_map.tiles[axial].biome_id - _dbg_biomes[bid] = _dbg_biomes.get(bid, 0) + 1 - if not BiomeRegistry.has_tag(bid, "is_water"): - _dbg_land_after_patches += 1 - print("[mapgen] after_patches land=%d biomes=%s" % [ - _dbg_land_after_patches, str(_dbg_biomes), - ]) - # Stage 9: Wind map (full 3-cell atmospheric model) + quality WindCalculatorScript.compute_wind_map(game_map) TerrainRefinerScript.assign_quality(game_map) @@ -346,27 +326,13 @@ func _assign_sea_level( roundi(ocean_target * all_elevs.size()), 0, all_elevs.size() - 1 ) var sea_level: float = all_elevs[idx] - print("[mapgen] sea_level=%.3f ocean_target=%.3f total=%d elev_min=%.3f elev_max=%.3f" % [ - sea_level, ocean_target, all_elevs.size(), - all_elevs[0], all_elevs[all_elevs.size() - 1], - ]) - var _dbg_land_pre: int = 0 for axial: Vector2i in game_map.tiles: - var is_land_pre: bool = _elevation.get(axial, 0.0) >= sea_level - if is_land_pre: - _dbg_land_pre += 1 game_map.tiles[axial].biome_id = ( "ocean" if _elevation.get(axial, 0.0) < sea_level else "land" ) - print("[mapgen] pre-smooth land=%d/%d" % [_dbg_land_pre, game_map.tiles.size()]) TerrainRefinerScript.smooth_coastlines(game_map, gen_params) - var _dbg_land_post: int = 0 - for axial: Vector2i in game_map.tiles: - if game_map.tiles[axial].biome_id != "ocean": - _dbg_land_post += 1 - print("[mapgen] post-smooth land=%d/%d" % [_dbg_land_post, game_map.tiles.size()]) TerrainRefinerScript.assign_coast_tiles(game_map) diff --git a/src/game/engine/src/generation/map_placer.gd b/src/game/engine/src/generation/map_placer.gd index 4607eb55..48b16707 100644 --- a/src/game/engine/src/generation/map_placer.gd +++ b/src/game/engine/src/generation/map_placer.gd @@ -28,10 +28,8 @@ func place_all( game_map: RefCounted, settings: Dictionary, num_players: int, wonder_count: int, type_data: Dictionary, ) -> void: - print("[placer] place_all start tiles=%d" % game_map.tiles.size()) ## Run the full placement pipeline on a terrain-generated map. place_natural_wonders(game_map, wonder_count) - print("[placer] after_wonders") var resource_mult: float = _get_density_multiplier( settings.get("resource_density", "standard"), "resources" @@ -39,14 +37,6 @@ func place_all( place_resources(game_map, resource_mult) var start_strategy: String = settings.get("start_strategy", "") - var _dbg_biomes: Dictionary = {} - var _dbg_is_land: int = 0 - for _axial: Vector2i in game_map.tiles: - var _bid: String = game_map.tiles[_axial].biome_id - _dbg_biomes[_bid] = _dbg_biomes.get(_bid, 0) + 1 - if game_map.tiles[_axial].is_land(): - _dbg_is_land += 1 - print("[placer] biomes=%s is_land_count=%d" % [str(_dbg_biomes), _dbg_is_land]) var start_positions: Array[Vector2i] = _start_position.select_start_positions( game_map, num_players, type_data, start_strategy ) diff --git a/src/game/engine/src/generation/start_position.gd b/src/game/engine/src/generation/start_position.gd index b1c39b52..66f7e7b8 100644 --- a/src/game/engine/src/generation/start_position.gd +++ b/src/game/engine/src/generation/start_position.gd @@ -21,27 +21,19 @@ func select_start_positions( var prefer_coast: bool = gen_params.get( "start_position_prefer_coast", true ) - print("[start] dispatch strategy='%s' type_id='%s' num_players=%d min_dist=%d" % [ - start_strategy, type_data.get("id", ""), num_players, - gen_params.get("start_position_min_distance", 10), - ]) # Dispatch to specialised strategy if provided - var result: Array[Vector2i] match start_strategy: "quadrant": - result = _select_starts_quadrant(game_map, num_players, prefer_coast) + return _select_starts_quadrant(game_map, num_players, prefer_coast) "per_continent": - result = _select_starts_per_continent(game_map, num_players, prefer_coast) + return _select_starts_per_continent(game_map, num_players, prefer_coast) "arm_tips": var type_id: String = type_data.get("id", "") - result = _select_starts_arm_tips(game_map, num_players, prefer_coast, type_id) - _: - result = _select_starts_greedy(game_map, num_players, gen_params, prefer_coast) - print("[start] result size=%d positions=%s" % [result.size(), str(result)]) - if result.size() == 2: - print("[start] pair_dist=%d" % HexUtilsScript.hex_distance(result[0], result[1])) - return result + return _select_starts_arm_tips(game_map, num_players, prefer_coast, type_id) + + # Default: greedy score-based with min-distance constraint + return _select_starts_greedy(game_map, num_players, gen_params, prefer_coast) func _select_starts_greedy( @@ -85,13 +77,6 @@ func _select_starts_greedy( if far_enough: selected.append(pos) - # DEBUG: report selected positions and pair distance for arena investigation - if selected.size() == 2: - print("[start] greedy min_distance=%d scored_count=%d selected=%s pair_dist=%d" % [ - min_distance, scored_tiles.size(), str(selected), - HexUtilsScript.hex_distance(selected[0], selected[1]), - ]) - return selected @@ -287,34 +272,20 @@ func _score_all_start_candidates( ) -> Array[Dictionary]: ## Score all eligible start tiles and return sorted descending by score. var scored: Array[Dictionary] = [] - var _dbg_total: int = 0 - var _dbg_non_land: int = 0 - var _dbg_nw: int = 0 - var _dbg_tag: int = 0 - var _dbg_zero: int = 0 for axial: Vector2i in game_map.tiles: - _dbg_total += 1 var tile: Variant = game_map.tiles[axial] if not tile.is_land(): - _dbg_non_land += 1 continue if tile.is_natural_wonder(): - _dbg_nw += 1 continue if ( BiomeRegistry.has_tag(tile.biome_id, "is_elevated") or BiomeRegistry.has_tag(tile.biome_id, "is_water") ): - _dbg_tag += 1 continue var score: float = _score_start_position(game_map, axial, prefer_coast) if score > 0: scored.append({"position": axial, "score": score}) - else: - _dbg_zero += 1 - print("[start] candidates total=%d non_land=%d nw=%d tag=%d zero=%d qualifying=%d" % [ - _dbg_total, _dbg_non_land, _dbg_nw, _dbg_tag, _dbg_zero, scored.size() - ]) scored.sort_custom( func(a: Dictionary, b: Dictionary) -> bool: return a["score"] > b["score"]