DiscordPHP-NHA Documentation

LoopStrategyStateTrait

{@see \NHA\StateStore} slice: the autoplay loop's strategic memory — the forced-objective rotation and its cooldown (armed when {@see \NHA\Brain\AutoPlayer::detectLoop()} catches the agent looping), the persisted {@see \NHA\Brain\Stance}, and the inventor-points trend that tells the fallback whether research is still paying.

Relies on the host's array $data and save().

Tags
since
3.1.32

Table of Contents

Constants

OBJECTIVE_ROTATION  : mixed = ['explore', 'wealth', 'build', 'research']
Objectives cycled through, in order, each time the agent is caught looping.
FORCED_OBJECTIVE_TTL_TICKS  : mixed = 45
A forced objective sticks for this many world ticks after a loop break.
LOOP_BREAK_COOLDOWN_TICKS  : mixed = 24
After a loop break, do not break again for this many ticks — let it play out.
RESEARCH_PAYING_WINDOW  : mixed = 900
Research counts as "paying" for this long after the last inventor-point gain.

Methods

bumpForcedObjective()  : string
Advances the agent's forced-objective cursor one step through {@see self::OBJECTIVE_ROTATION} and returns the new objective. Called by {@see \NHA\Brain\AutoPlayer} when it detects the agent is stuck in a loop, so each successive loop break tries a *different* kind of goal.
getForcedObjective()  : string|null
The objective forced by the most recent loop break, or `null` once it has aged out ({@see self::FORCED_OBJECTIVE_TTL_TICKS} ticks) — after which the agent is back on the normal ladder.
getStance()  : array{stance: string, tick: int}
The agent's persisted strategic stance and the tick it last changed (`{stance, tick}`). Defaults to `homestead` at tick 0.
loopBreakCooldownActive()  : bool
Whether a loop break happened too recently to break again — the forced objective (and the brain turns after it) need a few ticks to actually change the situation before the loop detector is allowed to fire once more.
noteInventorPoints()  : bool
Records the agent's current lifetime `inventor_points` and reports whether research is paying *right now* — the score rose this turn, or rose within the last {@see self::RESEARCH_PAYING_WINDOW} seconds.
peekNextForcedObjective()  : string
The objective {@see bumpForcedObjective()} WOULD return next, without advancing the cursor or arming the cooldown — so the loop guard can name the objective in the brain prompt and only commit it once the turn actually applies it.
setStance()  : void
Records the agent's stance. `$tick` is only stamped when the stance actually changes, so it marks the last *switch* for the dwell timer.

Constants

OBJECTIVE_ROTATION

Objectives cycled through, in order, each time the agent is caught looping.

public mixed OBJECTIVE_ROTATION = ['explore', 'wealth', 'build', 'research']

FORCED_OBJECTIVE_TTL_TICKS

A forced objective sticks for this many world ticks after a loop break.

private mixed FORCED_OBJECTIVE_TTL_TICKS = 45

LOOP_BREAK_COOLDOWN_TICKS

After a loop break, do not break again for this many ticks — let it play out.

private mixed LOOP_BREAK_COOLDOWN_TICKS = 24

RESEARCH_PAYING_WINDOW

Research counts as "paying" for this long after the last inventor-point gain.

private mixed RESEARCH_PAYING_WINDOW = 900

Methods

bumpForcedObjective()

Advances the agent's forced-objective cursor one step through {@see self::OBJECTIVE_ROTATION} and returns the new objective. Called by {@see \NHA\Brain\AutoPlayer} when it detects the agent is stuck in a loop, so each successive loop break tries a *different* kind of goal.

public bumpForcedObjective(int $agent_id, int $tick) : string
Parameters
$agent_id : int
$tick : int
Tags
since
3.1.12
Return values
string

getForcedObjective()

The objective forced by the most recent loop break, or `null` once it has aged out ({@see self::FORCED_OBJECTIVE_TTL_TICKS} ticks) — after which the agent is back on the normal ladder.

public getForcedObjective(int $agent_id, int $tick) : string|null
Parameters
$agent_id : int
$tick : int
Tags
since
3.1.12
Return values
string|null

getStance()

The agent's persisted strategic stance and the tick it last changed (`{stance, tick}`). Defaults to `homestead` at tick 0.

public getStance(int $agent_id) : array{stance: string, tick: int}
Parameters
$agent_id : int
Tags
since
3.1.23
Return values
array{stance: string, tick: int}

loopBreakCooldownActive()

Whether a loop break happened too recently to break again — the forced objective (and the brain turns after it) need a few ticks to actually change the situation before the loop detector is allowed to fire once more.

public loopBreakCooldownActive(int $agent_id, int $tick) : bool

Without this the loop-break moves themselves keep the "no productive action" window full and it thrashes every turn.

Parameters
$agent_id : int
$tick : int
Tags
since
3.1.14
Return values
bool

noteInventorPoints()

Records the agent's current lifetime `inventor_points` and reports whether research is paying *right now* — the score rose this turn, or rose within the last {@see self::RESEARCH_PAYING_WINDOW} seconds.

public noteInventorPoints(int $agent_id, int $points) : bool

Inventor points never drop (a rejected invention only refunds ingredients), so an absolute > 0 test stays true forever once an agent has invented anything. The autoplay fallback needs the recent trend instead: keep speculating while discoveries are still landing, fall to infrastructure once they dry up. The first sighting only sets the baseline and returns false (no trend yet).

Parameters
$agent_id : int
$points : int
Tags
since
3.1.9
Return values
bool

peekNextForcedObjective()

The objective {@see bumpForcedObjective()} WOULD return next, without advancing the cursor or arming the cooldown — so the loop guard can name the objective in the brain prompt and only commit it once the turn actually applies it.

public peekNextForcedObjective(int $agent_id) : string
Parameters
$agent_id : int
Tags
since
3.1.21
Return values
string

setStance()

Records the agent's stance. `$tick` is only stamped when the stance actually changes, so it marks the last *switch* for the dwell timer.

public setStance(int $agent_id, string $stance, int $tick) : void
Parameters
$agent_id : int
$stance : string
$tick : int
Tags
since
3.1.23
On this page

Search results