feat(@projects/@magic-civilization): ✨ add research catch-up multiplier logic
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
2275ae6e74
commit
e7375886c6
1 changed files with 69 additions and 0 deletions
|
|
@ -153,7 +153,15 @@ func _process_research(player: RefCounted) -> void: # Player
|
|||
return
|
||||
|
||||
# Per-yield difficulty multiplier (composed by GameState).
|
||||
# p1-29 cycle 4: research-yield catch-up boost. When this player is at least
|
||||
# 2 eras behind the highest opponent on the tech ladder, multiply science
|
||||
# yield by 1.5× — composes multiplicatively with cycle-3's tech-PICK boost in
|
||||
# auto_play.gd::_pick_research. Cycle 3 batch confirmed pick-side multiplier
|
||||
# alone doesn't move tier_peak_gap because the loser is research-OUTPUT
|
||||
# starved, not just choosing wrong techs. The output boost addresses that
|
||||
# directly. Inert when both players are at similar eras (`is_behind=false`).
|
||||
var sci_modifier: float = GameState.get_effective_yield_mult(player, "research")
|
||||
sci_modifier *= _catchup_research_mult(player)
|
||||
|
||||
# Per-city science yields the Rust side will sum.
|
||||
var game_map: RefCounted = GameState.get_game_map()
|
||||
|
|
@ -497,3 +505,64 @@ static func _player_owns_resource(player: RefCounted, resource_id: String) -> bo
|
|||
if tile != null and str(tile.get("resource_id")) == resource_id:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
# ── p1-29 cycle 4: research-output catch-up dynamics ─────────────
|
||||
#
|
||||
# Helpers below mirror the static functions added to auto_play.gd in cycle 3
|
||||
# (`_player_tier_peak`, `_max_opponent_tier_peak`). Duplicated here rather than
|
||||
# referenced via AutoPlayScript so that turn_processor's _process_research path
|
||||
# is self-contained — auto_play.gd is an autoload that may not be loaded in
|
||||
# every code path that ends up calling this module (live games, GUT tests,
|
||||
# headless MCTS).
|
||||
|
||||
|
||||
static func _player_tier_peak(player: RefCounted) -> int:
|
||||
## Compute the highest tech-era this player has researched. Mirrors the
|
||||
## per-player tier_peak metric written into turn_stats.jsonl.
|
||||
if player == null:
|
||||
return 0
|
||||
var techs: Array = player.researched_techs if player.get("researched_techs") != null else []
|
||||
var peak: int = 0
|
||||
for tid: Variant in techs:
|
||||
var data: Dictionary = DataLoader.get_tech(str(tid))
|
||||
var era: int = int(data.get("era", 0))
|
||||
if era > peak:
|
||||
peak = era
|
||||
return peak
|
||||
|
||||
|
||||
static func _max_opponent_tier_peak(self_player: RefCounted) -> int:
|
||||
## Compute the highest opponent's tier_peak across all OTHER players in
|
||||
## GameState.players. Returns 0 when self is the only player or no
|
||||
## opponents have researched anything yet.
|
||||
var max_peak: int = 0
|
||||
if GameState == null or GameState.players == null:
|
||||
return 0
|
||||
var self_idx: int = -1
|
||||
if self_player != null and self_player.get("index") != null:
|
||||
self_idx = int(self_player.index)
|
||||
for p: Variant in GameState.players:
|
||||
if p == null:
|
||||
continue
|
||||
var pi: int = int(p.index) if p.get("index") != null else -1
|
||||
if pi == self_idx:
|
||||
continue
|
||||
var peak: int = _player_tier_peak(p)
|
||||
if peak > max_peak:
|
||||
max_peak = peak
|
||||
return max_peak
|
||||
|
||||
|
||||
static func _catchup_research_mult(player: RefCounted) -> float:
|
||||
## Returns 1.5× when this player is at least 2 eras behind the highest
|
||||
## opponent's tech ceiling, 1.0× otherwise. Composes multiplicatively with
|
||||
## the configured base research multiplier (set by AI_DIFFICULTY etc.) and
|
||||
## with auto_play.gd::_pick_research's pillar-multiplier boost. (p1-29 cycle 4)
|
||||
if player == null:
|
||||
return 1.0
|
||||
var self_tp: int = _player_tier_peak(player)
|
||||
var opp_tp: int = _max_opponent_tier_peak(player)
|
||||
if opp_tp >= self_tp + 2:
|
||||
return 1.5
|
||||
return 1.0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue