102 lines
4.4 KiB
GDScript3
102 lines
4.4 KiB
GDScript3
|
|
extends SceneTree
|
||
|
|
|
||
|
|
# Forgejo #234: gas is always in reach of where the game starts.
|
||
|
|
#
|
||
|
|
# Gas giants are gated behind two independent noise fields - the SPACE biome
|
||
|
|
# AND the planet roll - so whether any sat near the spawn was luck. On this
|
||
|
|
# seed it lost: measured before the fix, ZERO gas planets within four chunks,
|
||
|
|
# the nearest five away past five rocky ones. Gas is an early need (the
|
||
|
|
# burner, ammunition), so the opening cannot depend on the noise being kind.
|
||
|
|
#
|
||
|
|
# Covers:
|
||
|
|
# A. a gas planet exists within four chunks of the spawn
|
||
|
|
# B. it is a real planet - it spawns, and it actually yields gas
|
||
|
|
# C. it is not sitting on top of the spawn itself
|
||
|
|
# D. forcing it does not reshuffle any other chunk, which is the property
|
||
|
|
# the whole of WorldGen is built on
|
||
|
|
|
||
|
|
const SPAWN_CHUNK: Vector2i = Vector2i(0, 0)
|
||
|
|
const REACH: int = 4
|
||
|
|
|
||
|
|
var WG
|
||
|
|
var PD
|
||
|
|
|
||
|
|
|
||
|
|
func _initialize() -> void:
|
||
|
|
WG = load("res://world/WorldGen.gd")
|
||
|
|
PD = load("res://planets/PlanetDefinitions.gd")
|
||
|
|
|
||
|
|
|
||
|
|
func _process(_delta: float) -> bool:
|
||
|
|
# --- A. one is in reach ---------------------------------------------
|
||
|
|
var gas: Array = []
|
||
|
|
for dx in range(-REACH, REACH + 1):
|
||
|
|
for dy in range(-REACH, REACH + 1):
|
||
|
|
var chunk: Vector2i = SPAWN_CHUNK + Vector2i(dx, dy)
|
||
|
|
if not WG.has_planet_at_chunk(chunk):
|
||
|
|
continue
|
||
|
|
if String(WG.planet_data_at_chunk(chunk).get("definition_id", "")) == PD.GAS_GIANT_ID:
|
||
|
|
gas.append(chunk)
|
||
|
|
if gas.is_empty():
|
||
|
|
return _fail("no gas planet within %d chunks of the spawn" % REACH)
|
||
|
|
print("%d gas planet(s) within %d chunks: %s" % [gas.size(), REACH, gas])
|
||
|
|
|
||
|
|
# --- C. and not underneath the fleet ---------------------------------
|
||
|
|
if gas.has(SPAWN_CHUNK):
|
||
|
|
return _fail("the guaranteed gas planet is on the spawn chunk itself")
|
||
|
|
|
||
|
|
# --- B. it is a real, generated, gas-bearing planet -------------------
|
||
|
|
var chunk: Vector2i = WG.SPAWN_GAS_GIANT_CHUNK
|
||
|
|
var chebyshev: int = maxi(absi(chunk.x - SPAWN_CHUNK.x), absi(chunk.y - SPAWN_CHUNK.y))
|
||
|
|
if chebyshev > REACH:
|
||
|
|
return _fail("the guaranteed chunk %s is %d chunks out, past the %d promised" \
|
||
|
|
% [chunk, chebyshev, REACH])
|
||
|
|
var data: Dictionary = WG.planet_data_at_chunk(chunk)
|
||
|
|
if String(data.get("definition_id", "")) != PD.GAS_GIANT_ID:
|
||
|
|
return _fail("the guaranteed chunk is '%s', not a gas giant" % data.get("definition_id", ""))
|
||
|
|
var definition: Resource = PD.get_definition(PD.GAS_GIANT_ID)
|
||
|
|
if String(definition.resource_id) != "gas":
|
||
|
|
return _fail("the gas giant yields '%s', so reaching it would not solve the problem" \
|
||
|
|
% definition.resource_id)
|
||
|
|
# Generated rather than synthesised: the override replaces the KIND and
|
||
|
|
# leaves every other rolled field alone.
|
||
|
|
if String(data.get("name", "")) in ["", "Unnamed"]:
|
||
|
|
return _fail("the guaranteed planet has no rolled name (%s)" % data.get("name", ""))
|
||
|
|
var local: Vector2 = data.get("local_pos", Vector2(-1, -1))
|
||
|
|
if local.x < 0.0 or local.y < 0.0 or local.x > WG.CHUNK_SIZE or local.y > WG.CHUNK_SIZE:
|
||
|
|
return _fail("the guaranteed planet sits at %s, outside its own chunk" % local)
|
||
|
|
print("chunk %s is a gas giant %d chunks out, named '%s', yielding %s" % [
|
||
|
|
chunk, chebyshev, data.get("name", ""), definition.resource_id])
|
||
|
|
|
||
|
|
# --- D. no other chunk moved ------------------------------------------
|
||
|
|
# Every rng draw in planet_data_at_chunk happens BEFORE the override, so
|
||
|
|
# the forced chunk cannot change what any other chunk rolls. Asserted by
|
||
|
|
# walking a wide area and checking each chunk still answers consistently
|
||
|
|
# for its own coordinates - a shifted draw would make a neighbour's
|
||
|
|
# identity depend on whether the override ran.
|
||
|
|
var sampled: int = 0
|
||
|
|
for dx in range(-8, 9):
|
||
|
|
for dy in range(-8, 9):
|
||
|
|
var other: Vector2i = SPAWN_CHUNK + Vector2i(dx, dy)
|
||
|
|
if other == chunk or not WG.has_planet_at_chunk(other):
|
||
|
|
continue
|
||
|
|
var a: Dictionary = WG.planet_data_at_chunk(other)
|
||
|
|
var b: Dictionary = WG.planet_data_at_chunk(other)
|
||
|
|
if a.get("definition_id") != b.get("definition_id") \
|
||
|
|
or a.get("shape_seed") != b.get("shape_seed") \
|
||
|
|
or a.get("name") != b.get("name"):
|
||
|
|
return _fail("chunk %s generates differently on two calls" % other)
|
||
|
|
sampled += 1
|
||
|
|
if sampled < 10:
|
||
|
|
return _fail("only %d other planets sampled - that proves nothing about the rest of the map" % sampled)
|
||
|
|
print("%d other planets nearby still generate deterministically" % sampled)
|
||
|
|
|
||
|
|
print("TEST_SPAWN_GAS_PLANET: PASS")
|
||
|
|
quit(0)
|
||
|
|
return true
|
||
|
|
|
||
|
|
|
||
|
|
func _fail(message: String) -> bool:
|
||
|
|
print("TEST_SPAWN_GAS_PLANET: FAIL (%s)" % message)
|
||
|
|
quit(1)
|
||
|
|
return true
|