update
This commit is contained in:
@@ -27,7 +27,11 @@ var human_recap: Dictionary = {} ## Rückblick auf den letzten eigenen Kampf
|
||||
var human_last_result: int = 0 ## 1 Sieg, -1 Niederlage, 0 unentschieden/keine
|
||||
|
||||
|
||||
func start(seed_value: int = 0) -> void:
|
||||
var difficulty: int = Data.Difficulty.NORMAL
|
||||
|
||||
|
||||
func start(seed_value: int = 0, p_difficulty: int = Data.Difficulty.NORMAL) -> void:
|
||||
difficulty = p_difficulty
|
||||
rand.seed = seed_value if seed_value != 0 else randi()
|
||||
pool = Pool.new()
|
||||
players.clear()
|
||||
@@ -37,7 +41,7 @@ func start(seed_value: int = 0) -> void:
|
||||
var b := PlayerState.new(i + 1, BOT_NAMES[i], true)
|
||||
players.append(b)
|
||||
var ai := BotAI.new()
|
||||
ai.setup(rand)
|
||||
ai.setup(rand, difficulty)
|
||||
bots[b.pid] = ai
|
||||
round_no = 1
|
||||
for p in players:
|
||||
@@ -61,8 +65,9 @@ func alive_players() -> Array:
|
||||
func _run_bot_turns() -> void:
|
||||
for p in players:
|
||||
if p.is_bot and p.alive:
|
||||
bots[p.pid].take_turn(p, pool, rand)
|
||||
bots[p.pid].arrange(p, opponent_of(p))
|
||||
var opp := opponent_of(p)
|
||||
bots[p.pid].take_turn(p, pool, rand, opp)
|
||||
bots[p.pid].arrange(p, opp)
|
||||
|
||||
|
||||
## Planungsuhr. Läuft sie ab, startet der Kampf von selbst.
|
||||
@@ -85,7 +90,7 @@ func start_combat() -> void:
|
||||
return
|
||||
# Abbilder erst jetzt kopieren, damit sie den aktuellen Stand zeigen.
|
||||
for pr in pairings:
|
||||
if pr["ghost"]:
|
||||
if pr["ghost"] and pr["ghost_src"] != null:
|
||||
pr["b"] = _make_ghost(pr["ghost_src"])
|
||||
pending.clear()
|
||||
player_combat = null
|
||||
@@ -117,10 +122,28 @@ func skip_combat() -> void:
|
||||
resolve_round()
|
||||
|
||||
|
||||
func is_pve_round() -> bool:
|
||||
return round_no <= Data.PVE_ROUNDS
|
||||
|
||||
|
||||
## Wildnis-Gegner: klein, ohne Leben, jeder Spieler bekommt seinen eigenen.
|
||||
func _make_creeps() -> PlayerState:
|
||||
var c := PlayerState.new(-2, "Wildnis", true)
|
||||
c.level = 9
|
||||
c.board[Vector2i(3, 0)] = Avatar.new(Data.Role.TANK, [Data.Element.ERDE] as Array[int], 1)
|
||||
if round_no >= 2:
|
||||
c.board[Vector2i(2, 1)] = Avatar.new(Data.Role.DPS, [Data.Element.WIND] as Array[int], 1)
|
||||
return c
|
||||
|
||||
|
||||
func _make_pairings() -> Array:
|
||||
var alive := alive_players()
|
||||
alive.shuffle()
|
||||
var out := []
|
||||
if is_pve_round():
|
||||
for p in alive:
|
||||
out.append({"a": p, "b": _make_creeps(), "ghost": true, "ghost_src": null})
|
||||
return out
|
||||
alive.shuffle()
|
||||
var i := 0
|
||||
while i + 1 < alive.size():
|
||||
out.append({"a": alive[i], "b": alive[i + 1], "ghost": false})
|
||||
@@ -207,7 +230,9 @@ func _next_round() -> void:
|
||||
for p in players:
|
||||
if not p.alive:
|
||||
continue
|
||||
p.gold += p.round_income()
|
||||
var income: int = p.round_income()
|
||||
p.gold += income
|
||||
p.stats["gold_earned"] += income
|
||||
p.gain_xp(Data.XP_PER_ROUND)
|
||||
p.new_round_shop(pool, rand)
|
||||
pairings = _make_pairings()
|
||||
@@ -216,13 +241,96 @@ func _next_round() -> void:
|
||||
phase = Phase.PLANNING
|
||||
|
||||
|
||||
# --- Speichern -------------------------------------------------------------
|
||||
|
||||
func to_dict() -> Dictionary:
|
||||
var ps := []
|
||||
for p in players:
|
||||
ps.append(p.to_dict())
|
||||
var ai := {}
|
||||
for pid in bots:
|
||||
ai[str(pid)] = {"pref": Array(bots[pid].pref), "greed": bots[pid].greed}
|
||||
return {
|
||||
"version": 1, "round": round_no, "difficulty": difficulty, "rng_state": str(rand.state),
|
||||
"pool": Array(pool.element_left), "players": ps, "bots": ai,
|
||||
"human_recap": human_recap, "log": last_round_log,
|
||||
}
|
||||
|
||||
|
||||
func from_dict(d: Dictionary) -> void:
|
||||
difficulty = int(d["difficulty"])
|
||||
rand.state = int(str(d["rng_state"]))
|
||||
pool = Pool.new()
|
||||
for i in mini(pool.element_left.size(), d["pool"].size()):
|
||||
pool.element_left[i] = int(d["pool"][i])
|
||||
players.clear()
|
||||
bots.clear()
|
||||
for pd in d["players"]:
|
||||
var p := PlayerState.from_dict(pd)
|
||||
players.append(p)
|
||||
if not p.is_bot:
|
||||
human = p
|
||||
else:
|
||||
var ai := BotAI.new()
|
||||
ai.setup(rand, difficulty)
|
||||
var bd: Dictionary = d["bots"].get(str(p.pid), {})
|
||||
if bd.has("pref"):
|
||||
ai.pref.clear()
|
||||
for e in bd["pref"]:
|
||||
ai.pref.append(int(e))
|
||||
ai.greed = float(bd["greed"])
|
||||
bots[p.pid] = ai
|
||||
round_no = int(d["round"])
|
||||
human_recap = d.get("human_recap", {})
|
||||
last_round_log = d.get("log", [])
|
||||
pairings = _make_pairings()
|
||||
for p in players:
|
||||
if p.is_bot and p.alive:
|
||||
bots[p.pid].arrange(p, opponent_of(p))
|
||||
plan_left = Data.PLAN_SECONDS
|
||||
phase = Phase.PLANNING
|
||||
|
||||
|
||||
func save(path: String = Data.SAVE_PATH) -> bool:
|
||||
if phase != Phase.PLANNING:
|
||||
return false
|
||||
var f := FileAccess.open(path, FileAccess.WRITE)
|
||||
if f == null:
|
||||
return false
|
||||
f.store_string(JSON.stringify(to_dict()))
|
||||
return true
|
||||
|
||||
|
||||
static func has_save(path: String = Data.SAVE_PATH) -> bool:
|
||||
return FileAccess.file_exists(path)
|
||||
|
||||
|
||||
static func delete_save(path: String = Data.SAVE_PATH) -> void:
|
||||
if FileAccess.file_exists(path):
|
||||
DirAccess.remove_absolute(ProjectSettings.globalize_path(path))
|
||||
|
||||
|
||||
static func load_from(path: String = Data.SAVE_PATH) -> Game:
|
||||
if not FileAccess.file_exists(path):
|
||||
return null
|
||||
var f := FileAccess.open(path, FileAccess.READ)
|
||||
if f == null:
|
||||
return null
|
||||
var parsed = JSON.parse_string(f.get_as_text())
|
||||
if not (parsed is Dictionary):
|
||||
return null
|
||||
var g := Game.new()
|
||||
g.from_dict(parsed)
|
||||
return g
|
||||
|
||||
|
||||
# --- Hilfen für die UI ----------------------------------------------------
|
||||
|
||||
## Gegner eines Spielers in der aktuellen Paarung (Abbilder liefern ihre Quelle).
|
||||
func opponent_of(p: PlayerState) -> PlayerState:
|
||||
for pr in pairings:
|
||||
if pr["a"] == p:
|
||||
return pr["ghost_src"] if pr["ghost"] else pr["b"]
|
||||
return pr["ghost_src"] if (pr["ghost"] and pr["ghost_src"] != null) else pr["b"]
|
||||
if pr["b"] == p:
|
||||
return pr["a"]
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user