This commit is contained in:
team3
2026-09-16 13:21:45 +02:00
parent 8a188c5d5c
commit 49e8f2d95e
27 changed files with 1772 additions and 265 deletions

View File

@@ -5,9 +5,12 @@ extends RefCounted
var pref: Array[int] = []
var greed: float = 0.5 ## wie stark der Bot Gold hortet
var difficulty: int = Data.Difficulty.NORMAL
var opponent: PlayerState = null ## bekannter Gegner der Runde, für Konterwahl
func setup(rand: RandomNumberGenerator) -> void:
func setup(rand: RandomNumberGenerator, p_difficulty: int = Data.Difficulty.NORMAL) -> void:
difficulty = p_difficulty
var all: Array[int] = []
for e in Data.ELEMENT_COUNT:
all.append(e)
@@ -19,18 +22,23 @@ func setup(rand: RandomNumberGenerator) -> void:
all[i] = all[j]
all[j] = tmp
pref = [all[0], all[1], all[2]]
greed = rand.randf_range(0.3, 0.8)
var g: Array = Data.BOT_GREED[difficulty]
greed = rand.randf_range(g[0], g[1])
func take_turn(p: PlayerState, pool: Pool, rand: RandomNumberGenerator) -> void:
func take_turn(p: PlayerState, pool: Pool, rand: RandomNumberGenerator, opp: PlayerState = null) -> void:
opponent = opp
_do_upgrades(p, pool)
_do_buys(p, pool)
_do_placements(p)
_do_upgrades(p, pool)
var keep := int(lerpf(2.0, 18.0, greed))
# Wer kurz vor einem Upgrade steht, würfelt gezielt nach Futter.
var hunting := _closest_upgrade_gap(p) <= 3
# Leichte Bots jagen nicht, schwere immer.
var hunting := difficulty != Data.Difficulty.LEICHT and _closest_upgrade_gap(p) <= 3
var rolls := 3 if hunting else 1
if difficulty == Data.Difficulty.SCHWER:
rolls += 1
for i in rolls:
if p.gold > keep + Data.REROLL_COST and (hunting or rand.randf() < 0.6):
p.reroll(pool, rand)
@@ -71,8 +79,13 @@ func arrange(p: PlayerState, opp: PlayerState) -> void:
return _min_dist(a, enemy_tanks) > _min_dist(b, enemy_tanks))
units.sort_custom(func(a, b): return a.role == Data.Role.TANK and b.role != Data.Role.TANK)
for u in units:
var rows: Array = [0, 1, 2, 3] if u.role == Data.Role.TANK else [3, 2, 1, 0]
var cols: Array = tank_cols if u.role == Data.Role.TANK else far_cols
# Heiler direkt hinter die Tanks, sonst reicht ihre Heilung (2 Felder) nicht.
var rows: Array
match u.role:
Data.Role.TANK: rows = [0, 1, 2, 3]
Data.Role.HEILER: rows = [1, 2, 0, 3]
_: rows = [3, 2, 1, 0]
var cols: Array = tank_cols if u.role != Data.Role.DPS else far_cols
var placed := false
for r in rows:
for c in cols:
@@ -179,6 +192,13 @@ func _pick_bench_for_board(p: PlayerState) -> int:
func _pick_element(p: PlayerState) -> int:
var counts := p.trait_counts()
# Konter: schlägt eines meiner Lieblingselemente das häufigste Element des Gegners,
# nehme ich das. Schwere Bots kontern auch außerhalb ihrer Vorlieben.
var dominant := _dominant_element(opponent)
if dominant >= 0:
var counter := Data.beaten_by(dominant)
if pref.has(counter) or difficulty == Data.Difficulty.SCHWER:
return counter
var best := pref[0]
var best_c := -1
for e in pref:
@@ -189,6 +209,23 @@ func _pick_element(p: PlayerState) -> int:
return best
## Häufigstes Hauptelement auf dem Brett eines Spielers, -1 wenn leer.
func _dominant_element(p: PlayerState) -> int:
if p == null or p.board.is_empty():
return -1
var counts := {}
for u in p.board_units():
var e: int = u.primary_element()
counts[e] = counts.get(e, 0) + 1
var best := -1
var best_n := 1 # ab zwei Einheiten lohnt das Kontern
for e in counts:
if counts[e] > best_n:
best_n = counts[e]
best = e
return best
func _pick_hex(p: PlayerState, role: int) -> Vector2i:
var rows: Array
match role: