pub trait RuleBindings<P: EffectProvider + ?Sized>: 'static {
Show 16 methods
// Required methods
fn apply_boost(
&self,
b: &mut BattlerState<P>,
stat_index: usize,
stages: i8,
) -> bool;
fn set_status(&self, b: &mut BattlerState<P>, status_index: usize) -> bool;
fn has_type(&self, b: &BattlerState<P>, type_index: usize) -> bool;
// Provided methods
fn set_status_with_amount(
&self,
b: &mut BattlerState<P>,
status_index: usize,
_amount: u16,
) -> bool { ... }
fn make_volatile(
&self,
_name: &str,
_amount: u16,
) -> Option<P::EffectStateKind> { ... }
fn type_chart_mult(
&self,
_ctx: &BattleCtx<'_, P>,
_move_type_index: usize,
_defender: BattlerRef,
) -> (u32, u32) { ... }
fn current_stat_index(&self, _ctx: &BattleCtx<'_, P>) -> Option<usize> { ... }
fn has_volatile(
&self,
_ctx: &BattleCtx<'_, P>,
_who: BattlerRef,
_name: &str,
) -> bool { ... }
fn redirect_hp_loss(
&self,
_ctx: &mut BattleCtx<'_, P>,
_who: BattlerRef,
_source: BattlerRef,
_amount: u16,
) -> bool { ... }
fn move_type_is_defender_type(
&self,
ctx: &BattleCtx<'_, P>,
move_type_index: usize,
who: BattlerRef,
) -> bool { ... }
fn has_status(&self, _b: &BattlerState<P>, _status_index: usize) -> bool { ... }
fn has_any_status(&self, _b: &BattlerState<P>) -> bool { ... }
fn battler_level(&self, _b: &BattlerState<P>) -> u16 { ... }
fn resource_id(&self, resource_index: usize) -> u16 { ... }
fn can_pay_resource(
&self,
b: &BattlerState<P>,
resource_index: usize,
amount: u16,
) -> bool { ... }
fn pay_resource(
&self,
b: &mut BattlerState<P>,
resource_index: usize,
amount: u16,
) { ... }
}Expand description
Resolves interned data-layer indices to concrete P::Stat/P::Status and
supplies the type-chart fold + defender-type membership, all pure.
A game implements this once for its provider; the loader carries it so the
zero-capture interpret bridge can reach it. The trait is
generic over P: EffectProvider, so the engine learns nothing.
Required Methods§
Sourcefn apply_boost(
&self,
b: &mut BattlerState<P>,
stat_index: usize,
stages: i8,
) -> bool
fn apply_boost( &self, b: &mut BattlerState<P>, stat_index: usize, stages: i8, ) -> bool
Apply a signed stat-stage delta to who for the interned stat_index.
Returns false if the index is unknown (a no-op; the loader validates
names at compile, so this is defense-in-depth). Phase 1 applies directly;
the nested-TryBoost veto is driver orchestration (doc 11 §3).
Sourcefn set_status(&self, b: &mut BattlerState<P>, status_index: usize) -> bool
fn set_status(&self, b: &mut BattlerState<P>, status_index: usize) -> bool
Set who’s non-volatile status for the interned status_index. Returns
false if the index is unknown.
Sourcefn has_type(&self, b: &BattlerState<P>, type_index: usize) -> bool
fn has_type(&self, b: &BattlerState<P>, type_index: usize) -> bool
Whether who has the type with interned chart type_index (the HasType
predicate, doc 11 §1.1). Pure read.
Provided Methods§
Sourcefn set_status_with_amount(
&self,
b: &mut BattlerState<P>,
status_index: usize,
_amount: u16,
) -> bool
fn set_status_with_amount( &self, b: &mut BattlerState<P>, status_index: usize, _amount: u16, ) -> bool
Set who’s non-volatile status carrying a game-interpreted numeric
amount (e.g. Gen-1 sleep turns). The engine resolves amount from the
op’s AmountSpec — drawing its OWN rng — and hands
the pure number here. Defaulted to delegate to
set_status and ignore the amount, so a game whose
statuses carry no duration is unaffected. Pure; no entropy.
Sourcefn make_volatile(&self, _name: &str, _amount: u16) -> Option<P::EffectStateKind>
fn make_volatile(&self, _name: &str, _amount: u16) -> Option<P::EffectStateKind>
Build the game’s OPAQUE P::EffectStateKind volatile for the vocabulary
name + already-resolved amount (the InflictVolatile
op). The engine installs whatever is returned generically (fresh arena
id) and never learns what the volatile means — only the game does.
Defaulted to None ⇒ a game with no volatiles (or that doesn’t
recognise name) makes the op inert. Pure — the engine already drew any
rng needed for amount.
Sourcefn type_chart_mult(
&self,
_ctx: &BattleCtx<'_, P>,
_move_type_index: usize,
_defender: BattlerRef,
) -> (u32, u32)
fn type_chart_mult( &self, _ctx: &BattleCtx<'_, P>, _move_type_index: usize, _defender: BattlerRef, ) -> (u32, u32)
The chart fold for the in-flight move_type_index against defender’s
type(s), as ONE pre-combined integer rational (num, den) (doc 12 §3.2,
§5.3 — one rational ⇒ exactly one scale, avoiding per-step truncation).
Default (1, 1) ⇒ inert (no chart). Pure / RNG-free.
Sourcefn current_stat_index(&self, _ctx: &BattleCtx<'_, P>) -> Option<usize>
fn current_stat_index(&self, _ctx: &BattleCtx<'_, P>) -> Option<usize>
The in-flight folded stat index, if the driver stashed one for a
StatIs predicate (the Sandstorm WeatherModifyStat case, doc 11 §1).
Default None ⇒ StatIs never matches. Pure.
Sourcefn has_volatile(
&self,
_ctx: &BattleCtx<'_, P>,
_who: BattlerRef,
_name: &str,
) -> bool
fn has_volatile( &self, _ctx: &BattleCtx<'_, P>, _who: BattlerRef, _name: &str, ) -> bool
Whether who currently has the live volatile named by name (the
HasVolatile predicate, blueprint 15 §2/§3 — the Substitute block on
side-status). The game inspects its own ctx.effects arena (the engine
treats EffectStateKind opaquely, so only the game can tell which arena
entry IS “Substitute”). Defaulted to false so a game with no volatiles
(every game built so far) is unaffected and the predicate never matches.
Pure read; no entropy.
Sourcefn redirect_hp_loss(
&self,
_ctx: &mut BattleCtx<'_, P>,
_who: BattlerRef,
_source: BattlerRef,
_amount: u16,
) -> bool
fn redirect_hp_loss( &self, _ctx: &mut BattleCtx<'_, P>, _who: BattlerRef, _source: BattlerRef, _amount: u16, ) -> bool
Damage-redirection seam for the DIRECT-MUTATE ops (SetHp / DamageFraction
/ DamageCurrentHpFraction / RepeatHits) that apply HP OUTSIDE the driver’s
Event::Damage fold. Before such an op subtracts amount HP from who
(attributed to source), the interpreter asks the game whether a damage sink
on who should swallow it instead — a monster Substitute doll, a cross-game
shield/ward/decoy. Returning true means the game HANDLED the loss (it mutated
its own sink via ctx); the interpreter then SKIPS the direct HP write. Returning
false (the default) leaves the op to apply HP exactly as before.
This is the ONLY binding permitted to MUTATE through ctx (every other is a pure
read) — it is the redirect analogue of the TryBoost/Event::Damage interception
the driver already fires for formula damage, extended to the ops the driver never
routes. Defaulted to false so every existing game (and every op) is
byte-identical: the loss applies unredirected, no ctx mutation, no entropy.
source lets a game exempt self-inflicted loss (recoil / self-KO) from its own
sink. Draws NO randomness.
Sourcefn move_type_is_defender_type(
&self,
ctx: &BattleCtx<'_, P>,
move_type_index: usize,
who: BattlerRef,
) -> bool
fn move_type_is_defender_type( &self, ctx: &BattleCtx<'_, P>, move_type_index: usize, who: BattlerRef, ) -> bool
Whether the in-flight move’s type (move_type_index, recovered from the
record’s type:) equals one of who’s types (the MoveTypeIsDefenderType
predicate — Gen-1 burn/freeze/paralyze self-type-immunity quirk #23,
blueprint 15 §2/§3). Defaulted to false ⇒ the quirk never fires for a
game that does not implement it. Pure read; no entropy. The default body
delegates to has_type so a game whose has_type already
answers chart membership gets the quirk for free by overriding nothing — but
the engine has no move_type_index for a generic predicate, so the loader
passes it through and the binding decides.
Sourcefn has_status(&self, _b: &BattlerState<P>, _status_index: usize) -> bool
fn has_status(&self, _b: &BattlerState<P>, _status_index: usize) -> bool
Whether who currently has the non-volatile status at interned
status_index (the TargetHasStatus predicate — the Dream Eater sleep
gate, blueprint 15 §2). The status index is the game’s vocabulary (the same
indices set_status consumes). Defaulted to false ⇒ a game that does
not implement it never matches. Pure read; no entropy.
Sourcefn has_any_status(&self, _b: &BattlerState<P>) -> bool
fn has_any_status(&self, _b: &BattlerState<P>) -> bool
Whether b has ANY non-volatile status (the TargetHasAnyStatus
predicate — the Toxic “already-statused ⇒ fail” guard). The engine knows
no concrete status, so the game answers. Defaulted to false ⇒ a game
that doesn’t implement it never matches. Pure read; no entropy.
Sourcefn battler_level(&self, _b: &BattlerState<P>) -> u16
fn battler_level(&self, _b: &BattlerState<P>) -> u16
The level of battler b (the LevelGE predicate’s gate + the level-based
SetDamage sources — Seismic Toss / Night Shade /
Psywave; blueprint 15 §2/§3). BattlerState<P>
carries no level field (the engine is level-agnostic), so the game answers
it here. Defaulted to 0 ⇒ a game that authors no level-gated op is
unaffected (it never calls this) and LevelGE is 0 >= 0 == true. Pure
read; no entropy. Game-agnostic: “a number the binding supplies per battler”.
Sourcefn resource_id(&self, resource_index: usize) -> u16
fn resource_id(&self, resource_index: usize) -> u16
Map an interned resource index (the ruleset’s resources: order) to the
engine’s opaque resource id used in ResourcePool
/ BattleProvider::move_cost
(the MP/SP/mana cost gate, doc 13 §4). Defaulted so games with no
resources need not implement it — they never reference a resource, so it is
never called. Default: identity (index as u16). Pure.
Sourcefn can_pay_resource(
&self,
b: &BattlerState<P>,
resource_index: usize,
amount: u16,
) -> bool
fn can_pay_resource( &self, b: &BattlerState<P>, resource_index: usize, amount: u16, ) -> bool
Whether b can pay amount of the resource at interned resource_index
(the PayResource op’s gate, doc 13 §4). Pure read. The default delegates
to the engine’s ResourcePool via
resource_id — a game that stores its pool on
BattlerState.resources (the engine default) gets correct behavior for free.
Sourcefn pay_resource(
&self,
b: &mut BattlerState<P>,
resource_index: usize,
amount: u16,
)
fn pay_resource( &self, b: &mut BattlerState<P>, resource_index: usize, amount: u16, )
Deduct amount of the resource at interned resource_index from b (the
PayResource op’s deduction). Pure arithmetic — no rng. Default
delegates to the engine ResourcePool.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".