669. Lesson identity
670. Learning objective
After this lesson, you can define a small inventory contract that stores fungible quantities by item-definition ID, enforces an explicit per-definition possession cap, validates mutations, reports their results, and separates possession from item interpretation.
671. Why this matters
Equipment, crafting, rewards, shops, and save data may all depend on inventory state. If each system changes that state according to different assumptions, quantities can become negative, caps can be exceeded, and callers may report success when possession did not change.
A narrow inventory authority provides one answer to what the player possesses and one path for changing it. It does not make the inventory responsible for equipment effects, recipes, prices, progression, or narrative meaning.
672. Identity: definition IDs and instance IDs
This lesson distinguishes two forms of identity:
- An item-definition ID identifies a reusable item type, such as
bandageorscrap_metal. Multiple interchangeable units can share this ID. - An item-instance ID identifies one particular object when it has individual state, such as durability, generated properties, ownership history, or another per-instance value.
The small contract in this lesson supports only fungible quantities keyed by item-definition ID:
quantityByDefinitionId[definitionId] = quantity
It does not store item-instance IDs, stack records, or slot placement. Therefore, it cannot represent two separate stacks of the same definition or two individually different copies. A game that needs those distinctions requires a different or extended storage model.
673. Inventory authority and boundaries
The inventory is authoritative for:
- whether a positive quantity of an item-definition ID is possessed;
- the stored quantity for that definition ID;
- whether an addition or removal satisfies the inventory contract;
- applying or rejecting the mutation;
- reporting a caller-visible result.
Other systems remain authoritative for:
- whether an item can be equipped and what effect it has;
- whether an item is a valid crafting ingredient;
- shop prices and economic interpretation;
- progression or unlock decisions;
- narrative meaning;
- item-definition data such as display information and the configured possession cap.
Other systems may read possession and request a mutation, but they should not rewrite the quantity map directly.
674. Supported storage and capacity model
For this lesson, each item definition has one aggregate quantity and an optional per-definition possession cap:
stored state: definition ID → aggregate quantity
valid quantity: 0 through possessionCap, inclusive
The cap limits the total quantity held under that definition ID. It is not a stack limit, slot limit, weight limit, or total inventory limit.
Examples:
bandage quantity: 3 possession cap: 5
scrap_metal quantity: 4 possession cap: 10
key_fold quantity: 1 possession cap: 1
The item-definition data owns the configured cap. The inventory reads that value when validating possession changes. A quantity of zero may be omitted from storage, provided the contract states that a missing entry means zero.
675. Mutation contract
Use this sequence:
REQUEST → VALIDATE → MUTATE OR REJECT → REPORT RESULT
A minimal request identifies:
- the operation:
addorremove; - the item-definition ID;
- a positive requested quantity.
Validation rules for this model:
- The definition ID must resolve to a known definition.
- The requested quantity must be greater than zero.
- Addition is valid only when
current + requested <= possessionCap. - Removal is valid only when
current >= requested. - Rejection leaves stored state unchanged.
A caller-visible result should include at least:
accepted: true or false
reason: accepted, unknown_definition, invalid_quantity, cap_exceeded, or insufficient_quantity
resultingQuantity: authoritative quantity after the request
Reporting the authoritative resulting quantity prevents the caller from guessing whether state changed.
676. Concrete example
Initial state and definitions:
bandage quantity: 3 possession cap: 5
scrap_metal quantity: 4 possession cap: 10
key_fold quantity: 1 possession cap: 1
| Request | Result | Stored state afterward |
|---|---|---|
Add 2 bandage |
Accepted | bandage = 5 |
Add 3 bandage from quantity 3 |
Rejected: cap_exceeded |
bandage = 3 |
Remove 2 scrap_metal |
Accepted | scrap_metal = 2 |
Remove 2 key_fold |
Rejected: insufficient_quantity |
key_fold = 1 |
Equip key_fold |
Not an inventory mutation by itself | Possession is unchanged |
The rejected bandage addition is not split into multiple stacks because this model has no stack records. Supporting separate stacks would require stack identity and an appropriate container structure.
677. Responsibility table
| Fact or decision | Owning system |
|---|---|
bandage definition exists |
Item-definition system |
bandage possession cap is 5 |
Item-definition system |
Player currently possesses 3 bandage |
Inventory |
| Add 3 would exceed the cap | Inventory validation |
bandage restores health |
Item-use or health system |
scrap_metal is a valid recipe ingredient |
Crafting system |
key_fold opens a particular door |
Interaction or narrative system |
The inventory can supply possession evidence without becoming the authority for those interpretations.
678. Common mistakes
Calling an aggregate cap a stack limit
A stack limit applies to a stack record. This lesson stores no stack records, so its rule is a per-definition possession cap.
Treating a definition ID as an instance ID
bandage identifies a type shared by interchangeable units. It does not distinguish one bandage from another. Individual durability or generated properties require instance records.
Leaving capacity unspecified
The word “capacity” is ambiguous unless the contract identifies whether it means slots, weight, stacks, total items, or a per-definition quantity. This contract supports only the last of those.
Allowing direct writes
Callers that edit the quantity map can bypass validation. Additions and removals should use explicit operations.
679. Guided practice
Create a contract and decision table for these definitions:
ration possession cap: 4
copper_wire possession cap: 10
access_token possession cap: 1
Use this template:
Supported identity model:
Stored state:
Meaning of a missing entry:
Cap ownership and meaning:
Add validation:
Remove validation:
Rejected-request behavior:
Caller-visible result:
Unsupported storage features:
Responsibilities outside inventory:
Resolve these cases:
- Add 4
rationto quantity 0. - Add 1 more
rationafter case 1. - Remove 2
access_tokenwhen quantity is 1. - Decide whether
copper_wireis a valid crafting ingredient. - Explain what must change in the storage model if two
rationunits need different durability values.
For each mutation, record the accepted flag, reason, resulting quantity, and whether stored state changed.
680. Validation and evidence
Submit the contract and result table through the attached practical assessment. Check that:
- definition IDs and optional instance IDs are explicitly distinguished;
- the supported model is limited to fungible aggregate quantities;
- the cap is defined as a per-definition possession cap;
- no answer relies on stack splitting, slots, or weight;
- additions and removals validate before mutation;
- rejected requests leave state unchanged;
- caller-visible results include acceptance, reason, and resulting quantity;
- crafting or another interpretation is assigned outside inventory;
- the need for instance records is recognized when units have individual state.
681. Key takeaways
- This inventory stores aggregate fungible quantities keyed by item-definition ID.
- An item-definition ID identifies a type; an item-instance ID would identify one particular object.
- This model uses a per-definition possession cap, not stacks, slots, or weight.
- Inventory owns possession and validated possession changes, not every interpretation of an item.
- Every mutation must validate first and return an explicit result.
682. Next lesson
2.5 L2 — Equipment changes capability through a contract keeps inventory authoritative for possession while equipment owns equipped state and effect interpretation.
683. Knowledge check
Answer these items for yourself before reading the answers.
Which fact should the inventory own?
Show answer and feedback
Answer: Whether the player possesses an item definition and in what quantity
Why: Inventory owns possession and quantity. Price, combat effects, and narrative meaning belong to other systems.
What should happen before an inventory mutation is applied?
Show answer and feedback
Answer: The request must be validated against the inventory contract
Why: Validation before mutation prevents invalid quantities and ensures rejected requests leave state unchanged.
Which identity does bandage represent when several interchangeable units share that value?
Show answer and feedback
Answer: An item-definition ID
Why: A definition ID identifies a shared item type. Distinguishing individual units would require instance IDs and instance records.
In the lesson's aggregate model, what does a possession cap of 5 for bandage mean?
Show answer and feedback
Answer: The total aggregate quantity stored under that definition ID cannot exceed 5
Why: The supported model stores one aggregate quantity per definition ID. It does not represent stacks, slots, or weight.
An inventory stores ration → 4, and the ration definition has a possession cap of 4. A caller requests add ration, 2. Which diagnosis and result are consistent with the contract?
Show answer and feedback
Answer: ration is a definition ID; reject with cap_exceeded, report resulting quantity 4, and leave state unchanged
Why: The stored key is a definition ID, and adding 2 would exceed its aggregate possession cap. Rejection must preserve quantity 4 and report that authoritative result.