Files
aetherbound-guild/runtime/p9_7/battle_state.gd
T

134 lines
3.8 KiB
GDScript

class_name P97BattleState
extends RefCounted
var revision := 0
var route_id := ""
var seed := 0
var tick := 0
var terminal := false
var outcome := ""
var outcome_cause := ""
var member_ids: Array[String] = []
var member_professions: Dictionary = {}
var member_hp: Dictionary = {}
var member_max_hp: Dictionary = {}
var member_positions: Dictionary = {}
var member_next_action: Dictionary = {}
var member_action_counts: Dictionary = {}
var member_last_targets: Dictionary = {}
var member_flags: Dictionary = {}
var enemy_ids: Array[String] = []
var enemy_hp: Dictionary = {}
var enemy_max_hp: Dictionary = {}
var enemy_positions: Dictionary = {}
var enemy_next_action: Dictionary = {}
var enemy_action_counts: Dictionary = {}
var enemy_flags: Dictionary = {}
var event_log: Array[Dictionary] = []
func reset() -> void:
revision = 0
route_id = ""
seed = 0
tick = 0
terminal = false
outcome = ""
outcome_cause = ""
member_ids.clear()
member_professions.clear()
member_hp.clear()
member_max_hp.clear()
member_positions.clear()
member_next_action.clear()
member_action_counts.clear()
member_last_targets.clear()
member_flags.clear()
enemy_ids.clear()
enemy_hp.clear()
enemy_max_hp.clear()
enemy_positions.clear()
enemy_next_action.clear()
enemy_action_counts.clear()
enemy_flags.clear()
event_log.clear()
func living_member_ids() -> Array[String]:
var result: Array[String] = []
for member_id in member_ids:
if int(member_hp.get(member_id, 0)) > 0:
result.append(member_id)
return result
func living_enemy_ids() -> Array[String]:
var result: Array[String] = []
for enemy_id in enemy_ids:
if int(enemy_hp.get(enemy_id, 0)) > 0:
result.append(enemy_id)
return result
func snapshot() -> Dictionary:
return {
"revision": revision,
"route_id": route_id,
"seed": seed,
"tick": tick,
"terminal": terminal,
"outcome": outcome,
"outcome_cause": outcome_cause,
"member_ids": member_ids.duplicate(),
"member_professions": member_professions.duplicate(true),
"member_hp": member_hp.duplicate(true),
"member_max_hp": member_max_hp.duplicate(true),
"member_positions": member_positions.duplicate(true),
"member_next_action": member_next_action.duplicate(true),
"member_action_counts": member_action_counts.duplicate(true),
"member_last_targets": member_last_targets.duplicate(true),
"member_flags": member_flags.duplicate(true),
"enemy_ids": enemy_ids.duplicate(),
"enemy_hp": enemy_hp.duplicate(true),
"enemy_max_hp": enemy_max_hp.duplicate(true),
"enemy_positions": enemy_positions.duplicate(true),
"enemy_next_action": enemy_next_action.duplicate(true),
"enemy_action_counts": enemy_action_counts.duplicate(true),
"enemy_flags": enemy_flags.duplicate(true),
"event_log": event_log.duplicate(true),
}.duplicate(true)
func invariants_hold() -> bool:
if revision < 0 or tick < 0 or route_id.is_empty():
return false
if outcome not in ["", "victory", "defeat", "timeout"] or terminal != (not outcome.is_empty()):
return false
if member_ids.is_empty() or enemy_ids.is_empty() or not _unique(member_ids) or not _unique(enemy_ids):
return false
for member_id in member_ids:
if not member_professions.has(member_id) or not member_max_hp.has(member_id):
return false
var hp := int(member_hp.get(member_id, -1))
if hp < 0 or hp > int(member_max_hp[member_id]):
return false
for enemy_id in enemy_ids:
if not enemy_max_hp.has(enemy_id):
return false
var hp := int(enemy_hp.get(enemy_id, -1))
if hp < 0 or hp > int(enemy_max_hp[enemy_id]):
return false
for index in event_log.size():
if not event_log[index] is Dictionary or int(event_log[index].get("index", -1)) != index:
return false
return true
func _unique(values: Array) -> bool:
var seen := {}
for value in values:
if seen.has(value):
return false
seen[value] = true
return true