import { Agent } from "./agent.js";
import { NONE } from "./color.js";
/**
* Abstract base class for agent decorators (proxies).
*
* Wraps another agent and forwards all behaviour to it, with the exception of
* `onTurn` which is intentionally suppressed so that creature AI is disabled
* for the duration of any proxy effect (giving paralysis for free for
* non-player agents).
*
* Subclasses can override individual callbacks to add effect-specific behaviour.
* The wrapped agent is accessible as `this.agent`.
*
* Mirrors Java's `AgentProxy` abstract class.
*/
export class AgentProxy extends Agent {
/**
* @param {Agent} agent The agent being wrapped.
* @param {number} flags Additional flags added by this proxy.
*/
constructor(agent, flags) {
super(
agent?.name ?? "Unknown",
flags,
agent?.color ?? NONE,
agent?.symbol ?? null,
);
/** @type {Agent} */
this.agent = agent;
/**
* Marker used by Cell.setAgent / _clearAgent to detect proxy-wrapped
* players without creating a circular import to the AgentProxy class.
*/
this.isAgentProxy = true;
}
/**
* Returns true if either the proxy's own flags OR the wrapped agent has the
* given flag. This is critical so that `PLAYER` propagates through
* a `Paralyzed` wrapper.
*/
is(flag) {
return this.agent?.is(flag) || (this.flags & flag) === flag;
}
/** Returns true only if neither the proxy flags nor the wrapped agent has the given flag. */
not(flag) {
return this.agent?.not(flag) && (this.flags & flag) !== flag;
}
changeHealth(value) {
return this.agent.changeHealth(value);
}
canEnter(direction, from, to) {
return this.agent.canEnter(direction, from, to);
}
onDie(event, cell) {
this.agent.onDie(event, cell);
}
onHit(event, attackerCell, agentLoc, agent) {
this.agent.onHit(event, attackerCell, agentLoc, agent);
}
onHitBy(event, agentLoc, agent, dir) {
this.agent.onHitBy(event, agentLoc, agent, dir);
}
onHitByItem(event, itemLoc, item, dir) {
this.agent.onHitByItem(event, itemLoc, item, dir);
}
/** Delegates to the wrapped agent's onFrame if it defines one. */
onFrame(event, cell, frame) {
if (this.agent?.onFrame) {
this.agent.onFrame(event, cell, frame);
}
}
// onTurn is intentionally NOT delegated — suppresses creature AI while any
// proxy effect is active.
}