131 lines
3.4 KiB
GDScript
131 lines
3.4 KiB
GDScript
extends SceneTree
|
|
|
|
var failures: Array[String] = []
|
|
var died_events := 0
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("_run")
|
|
|
|
|
|
func _run() -> void:
|
|
var manager := _create_manager()
|
|
manager.player_died.connect(_on_player_died)
|
|
|
|
var state: PlayerStateRecord = manager.get_player_state()
|
|
_check(
|
|
(
|
|
state != null
|
|
and is_equal_approx(state.get_hunger(), 40.0)
|
|
and is_equal_approx(state.get_energy(), 100.0)
|
|
and not state.is_dead()
|
|
),
|
|
"A fresh player should start with embodied needs and no death state",
|
|
)
|
|
|
|
for _tick in 3:
|
|
manager.simulate_tick()
|
|
_check(
|
|
(
|
|
is_equal_approx(state.get_hunger(), 40.375)
|
|
and is_equal_approx(state.get_energy(), 99.8125)
|
|
),
|
|
"Simulation ticks should advance the player's hunger and drain energy",
|
|
)
|
|
|
|
state.data["hunger"] = 80.0
|
|
var hunger_before_eat: float = state.get_hunger()
|
|
var eaten: float = manager.player_eat(10.0)
|
|
_check(
|
|
(
|
|
is_equal_approx(eaten, 10.0)
|
|
and state.get_hunger() < hunger_before_eat
|
|
and state.get_energy() > 80.0
|
|
),
|
|
"Eating should reduce the player's own hunger and restore energy",
|
|
)
|
|
|
|
var initial_standing: float = manager.get_player_standing().get_standing()
|
|
manager.get_player_standing().grant_standing(20.0, 1)
|
|
var standing_after_help: float = manager.get_player_standing().get_standing()
|
|
state.data["hunger"] = PlayerStateRecord.STACK_THRESHOLD
|
|
state.data["starvation_ticks"] = (int(state.data["starvation_death_threshold"]) - 1)
|
|
manager.simulate_tick()
|
|
_check(
|
|
(
|
|
died_events == 1
|
|
and state.is_dead()
|
|
and is_equal_approx(
|
|
manager.get_player_standing().get_standing(),
|
|
standing_after_help * PlayerStateRecord.DEATH_STANDING_PENALTY
|
|
)
|
|
),
|
|
"Starvation death should emit a death event and cut standing as a consequence",
|
|
)
|
|
|
|
var saved_json: String = manager.serialize_state()
|
|
var restored := _create_manager(902)
|
|
_check(
|
|
restored.restore_state_from_json(saved_json),
|
|
"The dead player state should restore through the current schema"
|
|
)
|
|
_check(
|
|
(
|
|
restored.get_state_checksum() == manager.get_state_checksum()
|
|
and restored.get_player_state().is_dead()
|
|
and restored.get_player_state().get_deaths() == 1
|
|
),
|
|
"Restore should preserve the embodied death state and checksum",
|
|
)
|
|
|
|
_check(manager.respawn_player(), "A dead player should be able to respawn")
|
|
_check(
|
|
(
|
|
not state.is_dead()
|
|
and is_equal_approx(state.get_hunger(), PlayerStateRecord.RESET_HUNGER)
|
|
and is_equal_approx(state.get_energy(), PlayerStateRecord.RESET_ENERGY)
|
|
),
|
|
"Respawn should reset needs to the documented baseline",
|
|
)
|
|
|
|
manager.free()
|
|
restored.free()
|
|
_finish()
|
|
|
|
|
|
func _create_manager(seed_value: int = 901) -> Node:
|
|
var manager: Node = load("res://simulation/SimulationManager.gd").new()
|
|
manager.simulation_seed = seed_value
|
|
manager.debug_logs = false
|
|
var home_positions: Array[Vector3] = [
|
|
Vector3(0.0, 0.0, 0.0),
|
|
Vector3(2.0, 0.0, 0.0),
|
|
Vector3(10.0, 0.0, 0.0),
|
|
Vector3(12.0, 0.0, 0.0),
|
|
Vector3(30.0, 0.0, 30.0),
|
|
Vector3(40.0, 0.0, 40.0),
|
|
]
|
|
manager.home_positions = home_positions
|
|
root.add_child(manager)
|
|
manager.set_process(false)
|
|
return manager
|
|
|
|
|
|
func _on_player_died(_state: PlayerStateRecord) -> void:
|
|
died_events += 1
|
|
|
|
|
|
func _check(condition: bool, message: String) -> void:
|
|
if not condition:
|
|
failures.append(message)
|
|
|
|
|
|
func _finish() -> void:
|
|
if failures.is_empty():
|
|
print("[TEST] Embodied player needs passed")
|
|
quit(0)
|
|
return
|
|
for failure in failures:
|
|
push_error("[TEST] " + failure)
|
|
quit(1)
|