134 lines
3.8 KiB
GDScript
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
|