osrlib.core.items
Equipment, inventories, magic items, identification, and curses.
The equipment catalog — weapons, armour, gear, and ammunition — compiles from the OSE
SRD's equipment pages and loads as frozen templates via
load_equipment. The magic item catalog — enchanted
arms, potions, scrolls, rings, rods, staves, wands, and sentient swords — compiles the
same way and loads via load_magic_items. Play never
mutates either catalog: it spawns owned instances from the frozen templates —
ItemInstance for mundane equipment,
MagicItemInstance for magic items — and
carries them in an Inventory.
A magic item instance starts unidentified, and even once identified may still hide a
curse: a revealed cursed item pins to its bearer until remove curse.
equip and unequip, and
their validate_* counterparts, enforce what a class may wear or wield: armour and
weapon policies, a two-ring cap, and the conflict between a two-handed weapon and a
shield.
Torch, holy water, and burning oil appear on both the SRD's weapon table and its gear list. osrlib adopts the reading that each is one physical item, not two: they compile as gear carrying an embedded combat facet, the weapons list holds the 19 pure weapons, and no item has two ids. Class weapon policies govern the weapons list only — gear combat facets are exempt, so a cleric may use holy water and a magic-user may throw oil or swing a torch, as a documented adaptation (see the adaptations register).
All weights are in coins (ten coins to the pound); coins themselves weigh 1 each. The maximum load rule always applies, not only under detailed encumbrance: tracked weight above 1,600 coins means the character cannot move, under both tracking modes. Inventory itself is never capped.
AnyInstance
module-attribute
AnyInstance = Annotated[ItemInstance | MagicItemInstance, Field(discriminator='instance_type')]
Any owned instance — mundane or magic — discriminated by instance_type.
BASE_MOVEMENT_FEET
module-attribute
The default movement rate, feet per exploration turn: 120' (40').
COIN_VALUES_CP
module-attribute
Coin values in copper pieces, from the SRD's Wealth conversion table.
ItemTemplate
module-attribute
ItemTemplate = Annotated[
WeaponTemplate | ArmourTemplate | GearTemplate | AmmunitionTemplate, Field(discriminator="item_type")
]
Any equipment template, discriminated by item_type.
MAX_LOAD_COINS
module-attribute
The maximum load any character can carry; above it, movement is 0.
MAX_RINGS_WORN
module-attribute
RAW's ring cap: one on each hand — a third is rejected (more than two = none function).
MISC_GEAR_WEIGHT_COINS
module-attribute
Detailed encumbrance's flat weight for carrying any miscellaneous gear.
AmmunitionTemplate
Bases: BaseModel
An ammunition row.
Ammunition weight is always 0: the SRD's missile weapon weights already include
the ammunition and its container, and the ammunition table has no weight column.
Sling stones' printed cost of Free compiles to cost 0 with a purchase lot size
of 1.
ArmourCategory
Bases: StrEnum
Basic-encumbrance armour categories; unarmoured is the absence of worn armour.
ArmourTemplate
ArmourTypeRow
CoinPurse
Bases: BaseModel
Coins by denomination. Each coin weighs 1, whatever its metal.
Payment consumes denominations smallest-first (cp, sp, ep, gp, pp) until the cost is covered; change for any overpayment returns in the fewest coins, largest denominations first. Purse contents after a purchase are always deterministic and value-preserving.
can_afford
Whether the purse's total value covers a cost in gold pieces.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cost_gp
|
int
|
The cost in whole gold pieces. Non-negative. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the purse's value in cp is at least the cost's. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
spend
spend(cost_gp: int) -> None
Pay a cost in gold pieces, spending smallest denominations first and making change largest-first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cost_gp
|
int
|
The cost in whole gold pieces. Non-negative. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Coins
Bases: BaseModel
A frozen coin bundle: generated treasure, cache contents, dropped piles.
CombatFacet
EquipmentCatalog
Bases: BaseModel
The loaded equipment lists, with id lookup across all four.
get
get(item_id: str) -> WeaponTemplate | ArmourTemplate | GearTemplate | AmmunitionTemplate
Return the template with item_id from any of the four lists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_id
|
str
|
An equipment id from
|
required |
Returns:
| Type | Description |
|---|---|
WeaponTemplate | ArmourTemplate | GearTemplate | AmmunitionTemplate
|
The template. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no item has that id. |
GearTemplate
Bases: BaseModel
An adventuring gear item.
lot_size sizes the purchase lot bought at cost_gp — see
purchase for exactly what a lot buys.
capacity_coins is container capacity where the SRD gives one (backpack, sacks);
combat is the embedded combat facet for the three dual-listed items. params
carries structured exploration mechanics from the SRD's gear table (a torch's
burn_turns and light_radius_feet, the tinder box's light_chance_in_six),
consumed by the crawl procedures.
GeneratedTreasure
Inventory
Bases: BaseModel
A character's carried items, coins, valuables, and equipped state.
The item list (items) is ordered (a defined order everywhere, per the
determinism contract). Equipping moves an instance out of items into its slot,
so each instance lives in exactly one place. Carried coins are the purse
(CoinPurse); magic items join the item list and
the equipped slots as union members; rings are the two worn-ring slots (RAW:
one on each hand — the cap is enforced at equip validation); valuables are
carried gems and jewellery.
all_instances
all_instances() -> list[ItemInstance | MagicItemInstance]
Return every carried instance — the item list plus the equipped slots.
equipped_instances
equipped_instances() -> list[ItemInstance | MagicItemInstance]
Return every equipped instance, slots first then wielded then rings.
magic_item
magic_item(instance_id: str) -> MagicItemInstance | None
Return the carried magic item with instance_id, or None.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
instance_id
|
str
|
The instance id, e.g. |
required |
Returns:
| Type | Description |
|---|---|
MagicItemInstance | None
|
The instance, wherever it is carried or equipped. |
ItemInstance
Bases: BaseModel
A mutable owned item spawned from a frozen template.
quantity counts individual units: buying one lot of torches yields one instance
with quantity 6.
MagicArmourTypeTable
Bases: BaseModel
The Magic Armour Type d8 table: what a generated Armour +N is made of.
base_for_roll
Return the base armour id a d8 roll selects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
roll
|
int
|
The d8 result, 1–8. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The mundane armour template id. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the roll is outside 1–8. |
MagicItemCatalog
Bases: BaseModel
The loaded magic item catalog: templates, sub-tables, and the sword tables.
get
get(item_id: str) -> MagicItemTemplate
Return the magic item template with item_id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_id
|
str
|
A magic item id from
|
required |
Returns:
| Type | Description |
|---|---|
MagicItemTemplate
|
The template. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no item has that id. |
sub_table
sub_table(category: MagicItemType) -> MagicSubTable
Return the generation sub-table for a master-table type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
category
|
MagicItemType
|
The master-table type. |
required |
Returns:
| Type | Description |
|---|---|
MagicSubTable
|
The sub-table. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no sub-table covers that type. |
MagicItemCategory
Bases: StrEnum
The magic item catalog's categories — the master table's types, devices split.
The master Magic Item Type table's rod_staff_wand type covers three catalog
categories; every other type maps to one.
MagicItemEffect
Bases: BaseModel
The structured mechanics of a magic item the kernel automates.
kind names the kernel behavior that executes it (worn_modifiers, potion,
damage_area, condition_area, healing, save_or_die, on_hit_drain,
striking, ward, regeneration, light); every other item in the catalog
carries manual-tagged prose instead. Fields are the union the behaviors read —
dice, element, save, shape and dimensions, duration — with params carrying
per-item scalars.
MagicItemInstance
Bases: BaseModel
A mutable owned magic item spawned from a frozen template.
template_id is the item id from
load_magic_items — see
the magic item id index. charges_remaining is referee-only
(RAW: undiscoverable) and None for uncharged items; quantity counts
ammunition; identified gates the player view's masking; base_item_id is the
generated base for generic armour outcomes (the Magic Armour Type d8) and the
template's own base otherwise; state is per-item memory (the energy-drain
sword's remaining drains, the staff of healing's per-target days, a multi-spell
scroll's remaining spells).
instance_type
class-attribute
instance-attribute
instance_type: Literal['magic_item'] = 'magic_item'
MagicItemTemplate
Bases: BaseModel
A magic item, compiled from the generation tables and per-item pages.
Frozen SRD data: play spawns mutable
MagicItemInstances. id is this
template's own id, listed in load_magic_items's
catalog — see the magic item id index. base_item_id is the
mundane equipment id (from load_equipment; see
the equipment id index) an enchanted arm overlays (sword,
dagger, chainmail, shield, arrows); generic armour outcomes leave it None — the
Magic Armour Type d8 sets the instance's base at generation. Bonuses are
negative for cursed items; the cursed AC 9 [10] forms carry ac_set /
ac_set_ascending instead. charges_dice rolls at generation (referee-only
forever after); quantity_dice sizes ammunition (sub-table rows may override
per printed band). weight_coins is the base item's weight — enchanted armour
at half per RAW, potions/scrolls/devices from the TreasureWeight rows.
hoard_recipe is a treasure map's compiled hoard; curses is the cursed
scroll's example-curse table.
params
class-attribute
instance-attribute
MagicSubTable
Bases: BaseModel
One category's generation sub-table: the sparse B column and the full X column.
row_for_basic
row_for_basic(roll: int) -> MagicSubTableRow
Return the row a Basic-tier small-die roll selects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
roll
|
int
|
The small-die result, 1 through |
required |
Returns:
| Type | Description |
|---|---|
MagicSubTableRow
|
The selected row. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no row carries that face. |
row_for_expert
row_for_expert(roll: int) -> MagicSubTableRow
Return the row an Expert-tier d% roll selects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
roll
|
int
|
The d% result, 1–100. |
required |
Returns:
| Type | Description |
|---|---|
MagicSubTableRow
|
The selected row. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the roll is outside 1–100. |
MagicSubTableRow
Bases: BaseModel
One outcome row of a category generation sub-table.
basic_value is the sparse small-die B column face (None when the printed
cell is blank — B and X are independent index spaces over the same outcome
list); expert_min/expert_max are the full d% X band (00 reads as 100).
item_ids is usually one id; the armour-with-shield rows are two-item bundles.
params carries per-band generation data (the ring wish-count dice, the arrow
and bolt quantity dice) that overrides the template's own fields.
Material
Bases: StrEnum
Weapon material — silver matters to the damage pipeline's immunity gate. Extensible.
MissileRanges
RangeBand
ScrollCurse
Bases: BaseModel
One of the cursed scroll's six example curses, compiled as a data row.
wired=True marks the two the kernel resolves (energy drain through
drain_levels with the curse's own halfway XP policy, slow healing through the
slowed-healing hooks); the rest are manual prose carried on the event.
ScrollSpellLevelRow
Bases: BaseModel
One row of the Random Scroll Spell Level table.
The B column here is d6 bands (1–3), not sparse faces — None bounds mark
the Expert-only rows.
ScrollSpellLevelTable
Bases: BaseModel
The Random Scroll Spell Level table, with its arcane and divine columns.
level_for_basic
Return the spell level a Basic-tier d6 roll selects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
roll
|
int
|
The d6 result, 1–6. |
required |
divine
|
bool
|
True for the divine column. |
required |
Returns:
| Type | Description |
|---|---|
int
|
The spell level. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no band covers the roll. |
level_for_expert
Return the spell level an Expert-tier d% roll selects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
roll
|
int
|
The d% result, 1–100. |
required |
divine
|
bool
|
True for the divine column. |
required |
Returns:
| Type | Description |
|---|---|
int
|
The spell level. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the roll is outside 1–100. |
SentientSwordTables
Bases: BaseModel
The sentient-sword generation tables, compiled as data.
Generation follows the SRD's own procedure: the special-purpose 1-in-20 roll first (a special sword is always sentient at INT 12/Ego 12), otherwise the 30% sentience roll, then INT 1d6+6, communication, languages, alignment, powers, and Ego 1d12, in the printed order.
power
power(power_id: str) -> SwordPower
Return the power with power_id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
power_id
|
str
|
The power id, e.g. |
required |
Returns:
| Type | Description |
|---|---|
SwordPower
|
The power. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no power has that id. |
SwordCommunicationRow
SwordControlResult
SwordPower
Bases: BaseModel
One sentient-sword power: manual-tagged prose data (automation is out of 1.0).
SwordPowersRow
SwordSentience
SwordTableBand
Bases: BaseModel
One die band of a sentient-sword roll table; result is a slug or directive.
Directives: roll_twice (languages and both power tables), roll_thrice
(extraordinary 00), roll_extraordinary (sensory 96–99).
TreasureWeight
UsableBy
Bases: BaseModel
Who may use a magic item.
all is the default ("All characters (unless noted)"); caster restricts to
spell casters of caster kind (arcane for wands, per staff page otherwise);
classes restricts to the named class ids. Swords, weapons, and armour stay
all — "per normal class restrictions" resolves through the base item's
equip policies, not here.
ValuableInstance
Bases: BaseModel
A gem or piece of jewellery, its value rolled at generation and fixed.
Appraisal is always instantaneous and exact: B/X prices treasure for the XP
economy, and a haggling or appraisal minigame is a game's own feature to add, not
part of osrlib. weight_coins comes from the TreasureWeight rows at generation.
VersusBonus
Bases: BaseModel
A +2 vs Lycanthropes clause: the printed label and its resolved targets.
bonus is the alternate attack-and-damage bonus that replaces the item's base
bonus against a matching target. Targets resolve structurally, never by
string-matching prose: categories name monster category tags (undead,
enchanted) and template_ids name compiled monster ids (the lycanthrope set,
the ability-derived spell-user and regenerating sets, the dagger's
orcs/goblins/kobolds). A clause matches a target whose template carries any
listed category or id; characters carry no monster template, so a clause never
matches one.
WeaponQuality
WeaponTemplate
encounter_movement_rate
equip
equip(inventory: Inventory, definition: ClassDefinition, instance: ItemInstance | MagicItemInstance) -> None
Equip an item from the inventory's item list.
Body armour goes to the worn-armour slot and the shield to the shield slot — a previous occupant returns to the item list. Weapons, combat-facet gear, devices, and miscellaneous magic items join the wielded list; rings join the ring slots. Equipping a two-handed weapon with a shield equipped (or the shield while a two-handed weapon is wielded) rejects — the conflict is enforced at equip time, not silently ignored at resolution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
Inventory
|
The inventory; mutated. |
required |
definition
|
ClassDefinition
|
The character's class definition. |
required |
instance
|
ItemInstance | MagicItemInstance
|
The instance to equip; must be in the item list. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the instance is not in the item list, or equipping it fails
|
equipment_weight_coins
Return detailed-encumbrance equipment weight: weapons, armour, and the gear flat.
Weapons and armour weigh their listed weights; ammunition always weighs 0 — its weight is already folded into the missile weapon's listed weight, and the ammunition table has no weight column of its own. Miscellaneous gear counts as a flat 80 coins when any is carried, since the SRD gives gear no per-item weights. Enchanted weapons and armour weigh as equipment beside their mundane bases — base weight, armour halved per RAW.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
Inventory
|
The inventory to weigh. |
required |
Returns:
| Type | Description |
|---|---|
int
|
The equipment weight in coins. |
equipped_item_modifiers
equipped_item_modifiers(inventory: Inventory) -> list[ModifierSpec]
Return the stat modifiers granted by equipped always-active magic items.
Item bonuses are computed from equipped inventory at query time rather than
stored as ActiveEffect stat modifiers: they combine freely with spell
modifiers and are always exempt from the cumulative largest-bonus-plus-largest-
penalty cap that modifier_total applies
to spell-sourced modifiers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
Inventory
|
The inventory to scan. |
required |
Returns:
| Type | Description |
|---|---|
list[ModifierSpec]
|
The modifiers, in equipped order (slots, wielded, rings). |
magic_item_template
magic_item_template(instance: MagicItemInstance) -> MagicItemTemplate
Return a magic item instance's template from load_magic_items's catalog.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
instance
|
MagicItemInstance
|
The instance whose template to look up. |
required |
Returns:
| Type | Description |
|---|---|
MagicItemTemplate
|
The frozen template. |
movement_rate_feet
Return the movement rate in feet per exploration turn.
Per the Ruleset encumbrance flag:
none: always 120; nothing is tracked and no load cap applies.basic: rate by worn-armour category (unarmoured/light/heavy) and thecarrying_treasurejudgment — significant treasure is a referee call in RAW, so it stays one: the game sets the flag, no invented threshold. Treasure weight (coins included) is still tracked against the 1,600-coin maximum load.detailed: rate by total tracked weight; the SRD's thresholds are inclusive ("up to").
In both tracking modes, tracked weight above the 1,600-coin maximum load means the character cannot move (movement 0).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
Inventory
|
The inventory to weigh. |
required |
ruleset
|
Ruleset
|
The ruleset whose encumbrance flag governs. |
required |
carrying_treasure
|
bool
|
Basic mode's referee judgment: is the character carrying a significant amount of treasure? |
False
|
Returns:
| Type | Description |
|---|---|
int
|
The movement rate in feet per turn: 120, 90, 60, 30, or 0. |
purchase
purchase(inventory: Inventory, template: ItemTemplate, lots: int = 1) -> ItemInstance
Buy lots purchase lots of an item, paying from the purse.
A purchase lot is the quantity one purchase at the template's listed cost_gp
delivers: gear and ammunition arrive in lot_size-sized lots (buying one lot of
torches costs 1 gp and yields quantity 6), while weapons and armour carry no
lot_size field, so one lot is a single unit. lots scales both the total cost
and the delivered quantity: buying 2 lots of torches costs 2 gp and yields
quantity 12. The new instance is appended to the item list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
Inventory
|
The buyer's inventory; mutated. |
required |
template
|
ItemTemplate
|
The item to buy. |
required |
lots
|
int
|
How many purchase lots. Positive. |
1
|
Returns:
| Type | Description |
|---|---|
ItemInstance
|
The purchased instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the purchase fails
|
sword_control_check
sword_control_check(character: Any, sword: MagicItemInstance, *, stream: RngStream) -> SwordControlResult
Resolve a sentient sword control check, à la carte.
RAW arithmetic: the sword's Will is INT + Ego, +1 per extraordinary power, +1d10 when the sword's and wielder's alignments differ; the wielder's Will is STR + WIS, −1d4 below full hit points, −2d4 below half. The sword controls when its Will is strictly higher. The crawl framework never auto-invokes this check; games narrate control through referee commands.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Any
|
The wielder: a |
required |
sword
|
MagicItemInstance
|
The sentient sword instance. |
required |
stream
|
RngStream
|
The RNG stream for the situational dice; à la carte callers choose. |
required |
Returns:
| Type | Description |
|---|---|
SwordControlResult
|
The plain result — no events, crawl-neutral. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the sword is not sentient. |
tracked_weight_coins
tracked_weight_coins(inventory: Inventory, mode: EncumbranceMode) -> int
Return the weight the given encumbrance mode tracks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
Inventory
|
The inventory to weigh. |
required |
mode
|
EncumbranceMode
|
The encumbrance mode in play. |
required |
Returns:
| Type | Description |
|---|---|
int
|
0 under |
int
|
treasure plus equipment weight under |
treasure_weight_coins
Return the weight of carried treasure in coins.
Purse coins weigh 1 each; valuables weigh their TreasureWeight figures; magic
items in the categories those rows price (potion, scroll, rod, staff, wand) weigh
as treasure. Rings and miscellaneous items weigh zero absent a page figure (the
Bag of Holding's printed loaded weight rides its params, counted while it holds
anything); enchanted weapons and armour always weigh as equipment beside their
mundane bases, not as treasure, so basic encumbrance's treasure tracking stays
honest.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
Inventory
|
The inventory to weigh. |
required |
Returns:
| Type | Description |
|---|---|
int
|
The treasure weight in coins. |
unequip
unequip(inventory: Inventory, instance: ItemInstance | MagicItemInstance) -> None
Return an equipped instance to the item list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
Inventory
|
The inventory; mutated. |
required |
instance
|
ItemInstance | MagicItemInstance
|
The equipped instance. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the instance is not equipped, or a revealed curse pins it
(validate with |
usable_by_class
usable_by_class(template: MagicItemTemplate, definition: ClassDefinition) -> bool
Return whether a class may use a magic item per its usable_by.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
template
|
MagicItemTemplate
|
The magic item template. |
required |
definition
|
ClassDefinition
|
The class definition. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True when the item's usability admits the class. |
validate_equip
validate_equip(
definition: ClassDefinition, instance: ItemInstance | MagicItemInstance, inventory: Inventory | None = None
) -> list[Rejection]
Validate equipping an item against the class's armour and weapon policies.
Weapon policies govern the weapons list only: gear carrying a combat facet (torch,
holy water, burning oil) is exempt and always equippable, as a documented
adaptation (see the adaptations register) that also lets a magic-user throw oil
or swing a torch. Gear without a facet, and ammunition, is not equippable at all.
Magic items resolve through their base item's policies (enchanted arms), the ring
cap, or their own usable_by (devices, miscellaneous items).
Wielding a two-handed weapon with a shield equipped — or equipping the second of
the pair — always rejects with items.equip.two_handed_with_shield: the conflict
is enforced at equip time rather than silently ignored at resolution. The check
needs the current equipped state, so pass inventory when one exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
definition
|
ClassDefinition
|
The character's class definition. |
required |
instance
|
ItemInstance | MagicItemInstance
|
The instance to equip. |
required |
inventory
|
Inventory | None
|
The inventory whose equipped state the two-handed-versus-shield conflict is checked against. |
None
|
Returns:
| Type | Description |
|---|---|
list[Rejection]
|
Structured rejections; empty when equipping is legal. |
validate_purchase
validate_purchase(purse: CoinPurse, template: ItemTemplate, lots: int = 1) -> list[Rejection]
Validate buying lots purchase lots of an item.
See purchase for exactly what a purchase lot buys.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
purse
|
CoinPurse
|
The buyer's purse. |
required |
template
|
ItemTemplate
|
The item to buy. |
required |
lots
|
int
|
How many purchase lots. Positive. |
1
|
Returns:
| Type | Description |
|---|---|
list[Rejection]
|
Structured rejections; empty when the purchase is legal. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
validate_unequip
validate_unequip(inventory: Inventory, instance: ItemInstance | MagicItemInstance) -> list[Rejection]
Validate returning an equipped instance to the item list.
A revealed cursed item pins to its bearer: it rejects with items.curse.stuck
until remove curse (each cursed category's page carries the same
cannot-discard clause).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
Inventory
|
The inventory holding the instance. |
required |
instance
|
ItemInstance | MagicItemInstance
|
The equipped instance. |
required |
Returns:
| Type | Description |
|---|---|
list[Rejection]
|
Structured rejections; empty when unequipping is legal. |