Hunters satchel
hunters-satchel · an adoption of Container, version 1
Use in your game
Opens the authoring tool with these answers and settings already filled in. You still add your game's own rules and tuning.
What is in the ZIP
The ZIP holds the adoption and its acceptance tests. In the authoring tool, choose Add contract and pick this ZIP. If you keep your design as files, put them in contracts/.
The contract behind it
A delivery is items arriving at a container, such as a bag or chest, that holds distinct items. This contract says when it is full and what happens when some items do not fit. It also says which items it accepts and which slot fills or empties first. It covers slots and size budgets. Version 1 excludes item footprints; counted amounts such as gold use the Ranged value contract.
Questions
The supplied answer is marked on each question. Pick other answers to see what changes. Nothing is saved here: the ZIP and the authoring tool use the supplied answers.
What makes this container full?
Why this is asked
Capacity changes what the container can hold and how it fills. This contract supports one size measure. Containers where items occupy a width-and-height footprint are outside version 1.
A delivery reaches the container, but not all the items fit. What goes in?
- Asked when
- Capacity limit is Slot count or Size budget or Slots and size.
Why this is asked
Two containers with the same free space can act differently. One accepts what fits; the other refuses the whole delivery.
What happens to the items that do not fit?
- Asked when
- Partial acceptance is Fill what fits.
Why this is asked
Items that stay outside still need a clear home. Otherwise one build may return them while another drops or destroys them.
Several slots could hold a new item. Which slot gets it?
- Asked when
- Capacity limit is Slot count or Slots and size or No limit.
Why this is asked
Two teams building the same spec can fill the same container differently. That changes what players see and what the game removes later. Rules that score slots, rotate between containers, or use a custom sequence stay in your game's prose.
The game needs an item for one of its own rules. Which matching slot does it take from?
Why this is asked
Automatic use needs a stable choice because it can change which stack remains for the player. A rotating choice over counted amounts belongs in the Ranged value contract.
Which kinds of item can this container hold?
Why this is asked
A clear item rule prevents silent differences between what the game accepts and what the designer intended. Rules built from another list or a code callback stay in your game's prose.
Numbers2 numbers
Each value is either a number set here or a reference to one of your tuning keys.
Slot count = 0
fixed as writtenslot-count
How many slots the container has. Use at least one when slots set capacity. Use zero when this container has no slot limit. If your game stores this number elsewhere, move it here so two copies cannot disagree.
Size budget = 35
fixed as writtensize-budget
The largest total size the container holds. Your game chooses the unit, such as kilograms or bulk. Every item uses the same unit. Use zero when size does not limit the container.
Rules2 rules
A rule is a check between the numbers. Validation reports a rule that fails.
slot-count >= 0size-budget >= 0
Lists1 list
Each list holds the rows this adoption supplies. A list can be empty.
Items
items
| Id | Slot rules declared in | Stack limit | Size | When forced out | Forced out order |
|---|---|---|---|---|---|
venison-cut | — | — | 1.5 | dropped-nearby | 1 |
deer-pelt | — | — | 3.5 | dropped-nearby | 2 |
iron-jaw-trap | — | — | 6 | dropped-nearby | 3 |
hunting-bow | — | — | 1.5 | dropped-nearby | 4 |
Test inputsscope and seeds
Some tests need a scope or seeds from the adoption before they can run.
capacity-holds
Capacity holds
- Scope
- sequences of packing, eating, dropping, and collecting venison cuts, pelts, traps, and the bow over a three-day hunt, including an exact-budget delivery, a partly fitting delivery, and an unlisted lantern refused intact, all measured in kilograms
- Seeds
["hunters-satchel-weight-a","hunters-satchel-weight-b"]
Acceptance tests8 tests apply
The contract comes with 14 tests. A test that runs once per row is counted once for each row. Tests that do not apply to these answers are still listed, with the reason.
delivery-that-fits
a delivery that fits is accepted whole
Applies to hunters-satchel.
A delivery hunters-satchel has room for is accepted whole: the container gains exactly what was offered, keeps everything it already held, and nothing is left over to account for. This is the ordinary case, written down so that every other test below reads as a departure from it.
Test steps and diagnostics
- Given
the
hunters-satchelcontainer with room for the whole of the delivery below- When
- a delivery offers n items of a type
hunters-satchelaccepts
- a delivery offers n items of a type
- Then
hunters-satchelholds exactly n more items of that type than it did- nothing already in
hunters-satchelis removed, destroyed, or changed into another type - nothing is handed back, dropped, or destroyed
- Diagnostics
hunters-satchel-contents-before-after
refuses-whole
a delivery that does not fit is refused whole
Does not apply to hunters-satchel: partial acceptance is fill what fits, not all or nothing.
takes-what-fits
a delivery that does not fit is split
Applies to hunters-satchel.
A delivery larger than the room available fills hunters-satchel as far as it goes and reports what it could not take. The part that did not fit is left outside hunters-satchel as a loose item where the delivery happened. Where that part ends up next, and who is responsible for it after that, is decided in this game's own prose.
Test steps and diagnostics
- Given
the
hunters-satchelcontainer with room for m items of a type it accepts, where m is more than zero and less than n- When
- a delivery offers n items of that type
- Then
hunters-satchelholds exactly m more items of that type- the remaining n minus m items are left outside
hunters-satchelas a loose item where the delivery happened - the delivery reports n minus m as the number it could not take
- Diagnostics
hunters-satchel-contents-before-afterhunters-satchel-delivery-report
slots-are-the-limit
the container is full when its slots are full
Does not apply to hunters-satchel: capacity limit is size budget, not slot count or slots and size.
size-is-the-limit
the container is full when its size budget is spent
Applies to hunters-satchel.
This container is full when the next item's size would take the total past the value at size-budget = 35. Sizes come from the item rows and the budget from that value; this test restates neither number.
Test steps and diagnostics
- Given
the
hunters-satchelcontainer holding items whose sizes add up to less thansize-budget = 35- When
- a delivery offers items whose sizes would take the total past
size-budget = 35
- a delivery offers items whose sizes would take the total past
- Then
- the sizes of the items
hunters-satchelholds never add up to more thansize-budget = 35 - each item's size is the size written on its own type's row, in the unit this game's prose names for the budget
- the sizes of the items
- Diagnostics
hunters-satchel-size-totalhunters-satchel-delivery-report
never-refuses
nothing is ever refused for want of room
Does not apply to hunters-satchel: capacity limit is size budget, not no limit.
fill-order-holds
an accepted item lands in the declared slot
Does not apply to hunters-satchel: fill order is not asked for hunters-satchel.
draw-order-by-position
the game takes from the declared slot
Does not apply to hunters-satchel: draw order is not applicable, not first in order or last in order.
draw-order-by-arrival
the game takes by when the stack arrived
Does not apply to hunters-satchel: draw order is not applicable, not newest first or oldest first.
stack-limit-holds
Row.id stacks no higher than its limit
Does not apply to hunters-satchel: capacity limit is size budget, not slot count or slots and size or no limit.
unlisted-type-refused
a type the list does not name is refused
Does not apply to hunters-satchel: type restriction is any item, not only these.
forced-out-holds · venison-cut
venison-cut leaves hunters-satchel in the declared way
Applies to the venison-cut row.
When hunters-satchel is made to give items up, venison-cut is left as a loose item where hunters-satchel is, for anyone to pick up, and it goes at position 1 in the declared order. When the container has slots and venison-cut sits in more than one slot, the last of those slots empties first — the row number orders the types, and that rule orders the slots inside one type. Of the five surveyed games that can force items out, three declare the switch that turns it on and none declares which item goes or where it lands — that gap is what this row closes.
Test steps and diagnostics
- Given
the
hunters-satchelcontainer holding more than onevenison-cutand, when it has slots and more than one slot is needed for that many, holding that type in more than one slot, together with any types carrying lower or higher forced-out order numbers- When
hunters-satchelis made to give items up without a take
- Then
venison-cutis left as a loose item wherehunters-satchelis, for anyone to pick upvenison-cutgoes at position1in the order: any type present with a lower number has gone before it, and any type present with a higher number goes after it- when the container has slots and
venison-cutsits in more than one slot, the last occupied slot of that type goes first and the container works back through its own order - no type that did not have to leave leaves
- Diagnostics
hunters-satchel-forced-removal-loghunters-satchel-contents-before-after
forced-out-holds · deer-pelt
deer-pelt leaves hunters-satchel in the declared way
Applies to the deer-pelt row.
When hunters-satchel is made to give items up, deer-pelt is left as a loose item where hunters-satchel is, for anyone to pick up, and it goes at position 2 in the declared order. When the container has slots and deer-pelt sits in more than one slot, the last of those slots empties first — the row number orders the types, and that rule orders the slots inside one type. Of the five surveyed games that can force items out, three declare the switch that turns it on and none declares which item goes or where it lands — that gap is what this row closes.
Test steps and diagnostics
- Given
the
hunters-satchelcontainer holding more than onedeer-peltand, when it has slots and more than one slot is needed for that many, holding that type in more than one slot, together with any types carrying lower or higher forced-out order numbers- When
hunters-satchelis made to give items up without a take
- Then
deer-peltis left as a loose item wherehunters-satchelis, for anyone to pick updeer-peltgoes at position2in the order: any type present with a lower number has gone before it, and any type present with a higher number goes after it- when the container has slots and
deer-peltsits in more than one slot, the last occupied slot of that type goes first and the container works back through its own order - no type that did not have to leave leaves
- Diagnostics
hunters-satchel-forced-removal-loghunters-satchel-contents-before-after
forced-out-holds · iron-jaw-trap
iron-jaw-trap leaves hunters-satchel in the declared way
Applies to the iron-jaw-trap row.
When hunters-satchel is made to give items up, iron-jaw-trap is left as a loose item where hunters-satchel is, for anyone to pick up, and it goes at position 3 in the declared order. When the container has slots and iron-jaw-trap sits in more than one slot, the last of those slots empties first — the row number orders the types, and that rule orders the slots inside one type. Of the five surveyed games that can force items out, three declare the switch that turns it on and none declares which item goes or where it lands — that gap is what this row closes.
Test steps and diagnostics
- Given
the
hunters-satchelcontainer holding more than oneiron-jaw-trapand, when it has slots and more than one slot is needed for that many, holding that type in more than one slot, together with any types carrying lower or higher forced-out order numbers- When
hunters-satchelis made to give items up without a take
- Then
iron-jaw-trapis left as a loose item wherehunters-satchelis, for anyone to pick upiron-jaw-trapgoes at position3in the order: any type present with a lower number has gone before it, and any type present with a higher number goes after it- when the container has slots and
iron-jaw-trapsits in more than one slot, the last occupied slot of that type goes first and the container works back through its own order - no type that did not have to leave leaves
- Diagnostics
hunters-satchel-forced-removal-loghunters-satchel-contents-before-after
forced-out-holds · hunting-bow
hunting-bow leaves hunters-satchel in the declared way
Applies to the hunting-bow row.
When hunters-satchel is made to give items up, hunting-bow is left as a loose item where hunters-satchel is, for anyone to pick up, and it goes at position 4 in the declared order. When the container has slots and hunting-bow sits in more than one slot, the last of those slots empties first — the row number orders the types, and that rule orders the slots inside one type. Of the five surveyed games that can force items out, three declare the switch that turns it on and none declares which item goes or where it lands — that gap is what this row closes.
Test steps and diagnostics
- Given
the
hunters-satchelcontainer holding more than onehunting-bowand, when it has slots and more than one slot is needed for that many, holding that type in more than one slot, together with any types carrying lower or higher forced-out order numbers- When
hunters-satchelis made to give items up without a take
- Then
hunting-bowis left as a loose item wherehunters-satchelis, for anyone to pick uphunting-bowgoes at position4in the order: any type present with a lower number has gone before it, and any type present with a higher number goes after it- when the container has slots and
hunting-bowsits in more than one slot, the last occupied slot of that type goes first and the container works back through its own order - no type that did not have to leave leaves
- Diagnostics
hunters-satchel-forced-removal-loghunters-satchel-contents-before-after
never-forced-out
Row.id is never given up by hunters-satchel itself
Does not apply to hunters-satchel: no row in items matches when-forced-out never.
capacity-holds
the limit holds after every delivery and take
Applies to hunters-satchel.
For every delivery and take in this adoption's verification scope — sequences of packing, eating, dropping, and collecting venison cuts, pelts, traps, and the bow over a three-day hunt, including an exact-budget delivery, a partly fitting delivery, and an unlisted lantern refused intact, all measured in kilograms — the sizes of the items held never add up to more than the container's declared size budget. The scope and seeds are supplied by this adoption through its verification inputs; the rule being checked is the one this container's own capacity answer entitles it to assert.
Test steps and diagnostics
- Diagnostics
hunters-satchel-contents-trace- first-violating-delivery-or-take
- Holds
after every delivery and every take, the sizes of the items held never add up to more than the container's declared size budget
- Seeds
["hunters-satchel-weight-a","hunters-satchel-weight-b"]- Scope
sequences of packing, eating, dropping, and collecting venison cuts, pelts, traps, and the bow over a three-day hunt, including an exact-budget delivery, a partly fitting delivery, and an unlisted lantern refused intact, all measured in kilograms
JSONthe adoption as one file
The adoption file as supplied. Answers you try on this page are not written into it; to change an adoption, open it in the authoring tool.
{
"contract": "container",
"version": 1,
"origin": "https://opengdd.org/contracts/container-1",
"summary": "A delivery is items arriving at a container, such as a bag or chest, that holds distinct items. This contract says when it is full and what happens when some items do not fit. It also says which items it accepts and which slot fills or empties first. It covers slots and size budgets. Version 1 excludes item footprints; counted amounts such as gold use the Ranged value contract.",
"mechanism": [
"One container holds items. Two items of one type are interchangeable; items differing within a type — wear, charges — are separate types here, or this game's prose. A slot holds one stack: items of one type together.",
"The container's own order is the order the game's material numbers or lists its slots; first and last below mean first and last in it. A container with no slots has none. Containers where an item occupies a width-and-height footprint, including attaché cases and grid inventories, are outside version 1.",
"A put offers a type and an amount — a delivery. A take asks for a type and an amount; one larger than the holdings yields what is held and reports the shortfall.",
"A delivery that fits is accepted whole; one that does not is settled by partial-acceptance, and anything left over by leftover-destination.",
"A stack never holds more than the stack limit on its type's row. Past it, an amount starts a new stack in a free slot, or counts as not fitting if there is none. Under type-restriction any-item, where slots alone set the limit, a type with no row stacks one item per slot and is unmovable in a forced removal, as though when-forced-out were never; under a size budget an unlisted type has no size, so it is refused intact until a row names its size.",
"A forced removal is an item leaving without a take: the container shrank, its rules changed, or its owner is gone. Each item row says what becomes of its type and when its turn comes. In a container with slots, the last occupied slot within one type goes first.",
"One adoption file describes one container; two are two files with their own rows. Moving an item between them is a take then a delivery, and nothing binds them. Rearranging by hand is input. In a container with slots, a sort re-delivers the contents in the order the sort names; each delivery then lands by the fill-order answer. A slotless container's sort changes nothing observable.",
"The same delivery from the same contents lands the same way; the same take comes from the same slot."
],
"questions": {
"capacity-limit": {
"asks": "What makes this container full?",
"rationale": "Capacity changes what the container can hold and how it fills. This contract supports one size measure. Containers where items occupy a width-and-height footprint are outside version 1.",
"options": {
"slot-count": {
"meaning": "A fixed number of slots makes it full. A shop's twenty stock slots refuse a new kind of item when all twenty hold stacks. A matching stack with room can still accept it."
},
"size-budget": {
"meaning": "A size-budget container has no slots. A card deck with a thirty-point build budget may spend those points across cards of different costs."
},
"slots-and-size": {
"meaning": "A slot limit and a size budget both apply. A bag with three free slots can still refuse an anvil when its weight budget is full."
},
"no-limit": {
"meaning": "It never fills. A new item always has room, so nothing is refused because the container ran out of space.",
"rationale": "Use this when room can never run out. It avoids a fake large limit that readers may mistake for a real cap."
}
}
},
"partial-acceptance": {
"asks": "A delivery reaches the container, but not all the items fit. What goes in?",
"rationale": "Two containers with the same free space can act differently. One accepts what fits; the other refuses the whole delivery.",
"when": {
"flag": {
"capacity-limit": [
"slot-count",
"size-budget",
"slots-and-size"
]
}
},
"options": {
"all-or-nothing": {
"meaning": "The whole delivery is refused. A ten-arrow pickup adds no arrows when the container has room for only five. Each offered type and amount is one delivery. A craft with several outputs makes several deliveries, so some outputs may enter before another is refused. The refused items stay with whatever offered them, and what that action does next is the game's own rule."
},
"fill-what-fits": {
"meaning": "Everything that fits goes in. A ten-arrow pickup adds five when only five fit; the other five remain outside."
}
}
},
"leftover-destination": {
"asks": "What happens to the items that do not fit?",
"rationale": "Items that stay outside still need a clear home. Otherwise one build may return them while another drops or destroys them.",
"when": {
"flag": {
"partial-acceptance": [
"fill-what-fits"
]
}
},
"options": {
"back-to-the-sender": {
"meaning": "The leftover goes back to its source. Arrows that do not fit return to the chest or pickup that offered them."
},
"left-where-it-is": {
"meaning": "The leftover stays where the delivery arrived. Arrows that do not fit become a loose pickup beside the bag."
},
"another-store": {
"meaning": "The leftover moves to another store named by your game. Arrows that do not fit may go to a stash."
},
"destroyed": {
"meaning": "The leftover is destroyed. Arrows that do not fit disappear instead of returning, dropping, or moving elsewhere."
}
}
},
"fill-order": {
"asks": "Several slots could hold a new item. Which slot gets it?",
"rationale": "Two teams building the same spec can fill the same container differently. That changes what players see and what the game removes later. Rules that score slots, rotate between containers, or use a custom sequence stay in your game's prose.",
"when": {
"flag": {
"capacity-limit": [
"slot-count",
"slots-and-size",
"no-limit"
]
}
},
"options": {
"top-up-then-first-empty": {
"meaning": "Matching stacks fill before empty slots open. A potion tops up the first potion stack with room, then uses the first empty slot."
},
"first-slot-that-fits": {
"meaning": "The first slot that can hold the item gets it. An empty first hotbar slot wins over a later matching stack with room."
},
"append": {
"meaning": "New items go after everything already held. An empty slot in the middle stays unused until the items after it are gone. A bag with a slot limit can count as full while that gap remains."
},
"not-applicable": {
"meaning": "Choose this only when each item has one reserved slot. If slots are unlimited, choose Append instead."
}
}
},
"draw-order": {
"asks": "The game needs an item for one of its own rules. Which matching slot does it take from?",
"rationale": "Automatic use needs a stable choice because it can change which stack remains for the player. A rotating choice over counted amounts belongs in the Ranged value contract.",
"options": {
"first-in-order": {
"meaning": "The first matching slot supplies the item. Crafting uses the earliest stack in the bag before later stacks."
},
"last-in-order": {
"meaning": "The last matching slot supplies the item. Crafting empties the last matching stack before earlier stacks."
},
"newest-first": {
"meaning": "The stack that received items most recently supplies them first. Topping up an older potion stack makes it the newest again."
},
"oldest-first": {
"meaning": "The stack that began first supplies items first. Topping up an old potion stack does not make it newer.",
"rationale": "Use this when the longest-held stack must leave first, such as a magazine or queue."
},
"not-applicable": {
"meaning": "The game never has to choose between matching slots. The player chooses a slot, only one can match, or the container has no slots."
}
}
},
"type-restriction": {
"asks": "Which kinds of item can this container hold?",
"rationale": "A clear item rule prevents silent differences between what the game accepts and what the designer intended. Rules built from another list or a code callback stay in your game's prose.",
"options": {
"only-these": {
"meaning": "Only listed item types can enter. A potion bag says no to a sword. The sword stays where it was; nothing is destroyed. An empty list means the container accepts nothing."
},
"any-item": {
"meaning": "Every item type may enter once the contract knows how much room it needs. Where slots alone set the limit, an unlisted type — a quest letter no row names — uses one slot per item and cannot be forced out. Under a size budget, it is refused intact until a row names its size."
},
"by-slot": {
"meaning": "Each slot has its own item rule. An armour slot accepts a helmet but refuses a potion without destroying it. List every kind that needs a stacking or forced-out rule.",
"semantics": "Each item row's slot-rules-declared-in citation is binding. It points to prose that lists every slot and every item kind that slot accepts; an item not accepted there is refused intact."
}
}
}
},
"declares": {
"values": {
"slot-count": {
"description": "How many slots the container has. Use at least one when slots set capacity. Use zero when this container has no slot limit. If your game stores this number elsewhere, move it here so two copies cannot disagree."
},
"size-budget": {
"description": "The largest total size the container holds. Your game chooses the unit, such as kilograms or bulk. Every item uses the same unit. Use zero when size does not limit the container."
}
},
"rows": {
"items": {
"description": "The item types whose rules this contract records. Use one row for each type. For a restricted container, the rows are also the allowed list. An empty list means no listed types. For any-item, the rows plus the unlisted-type defaults fully decide entry, stacking, and forced removal for every type. The validator checks each row's fields; a reviewer checks that the game's own prose does not give unlisted types a rule different from the defaults.",
"record": {
"id": {
"type": "string",
"required": true,
"pattern": "kebab-case",
"unique": true,
"description": "The item type's name, written as your game names it."
},
"slot-rules-declared-in": {
"type": "citation",
"when": {
"flag": {
"type-restriction": [
"by-slot"
]
}
},
"description": "The place in this game's prose that lists every slot and every item kind it accepts. This citation is the binding rule for the slots. Use the same citation on every row when one section holds the whole list."
},
"stack-limit": {
"type": "integer",
"when": {
"flag": {
"capacity-limit": [
"slot-count",
"slots-and-size",
"no-limit"
]
}
},
"description": "How many items of this type fit in one slot. It is required whenever the container has slots, including when it never fills. Use one for an item that does not stack, or another positive whole number."
},
"size": {
"type": "number",
"when": {
"flag": {
"capacity-limit": [
"size-budget",
"slots-and-size"
]
}
},
"description": "How much of the size budget one item uses. Use the same unit as the container's budget. Use zero or more."
},
"when-forced-out": {
"type": "string",
"required": true,
"options": [
"never",
"dropped-nearby",
"moved-to-another-store",
"destroyed"
],
"description": "What happens to this item when the container must give items up. It may stay, drop nearby, move to another store, or be destroyed. An item marked to stay is skipped. The container tries other types in their chosen order. It refuses the forced removal if too few items can leave. If destroying an item could make the game impossible to finish, say so and test it in your own rules."
},
"forced-out-order": {
"type": "integer",
"unique": true,
"when": {
"row": {
"when-forced-out": [
"dropped-nearby",
"moved-to-another-store",
"destroyed"
]
}
},
"description": "The order in which item types leave, lowest number first. Give each movable type a different number. Items of one type leave from its last occupied slot first. The size of the gaps between numbers does not matter."
}
}
}
}
},
"pack": "sha256:8f40a54e650b683136852e7a5b47976ebe709f810057f847424d6d8ab3b41b20",
"rules": {
"slot-count-not-negative": "slot-count >= 0",
"size-budget-not-negative": "size-budget >= 0"
},
"answers": {
"capacity-limit": "size-budget",
"partial-acceptance": "fill-what-fits",
"leftover-destination": "left-where-it-is",
"draw-order": "not-applicable",
"type-restriction": "any-item"
},
"values": {
"slot-count": 0,
"size-budget": 35
},
"rows": {
"items": [
{
"id": "venison-cut",
"size": 1.5,
"when-forced-out": "dropped-nearby",
"forced-out-order": 1
},
{
"id": "deer-pelt",
"size": 3.5,
"when-forced-out": "dropped-nearby",
"forced-out-order": 2
},
{
"id": "iron-jaw-trap",
"size": 6,
"when-forced-out": "dropped-nearby",
"forced-out-order": 3
},
{
"id": "hunting-bow",
"size": 1.5,
"when-forced-out": "dropped-nearby",
"forced-out-order": 4
}
]
},
"verification": {
"capacity-holds": {
"scope": "sequences of packing, eating, dropping, and collecting venison cuts, pelts, traps, and the bow over a three-day hunt, including an exact-budget delivery, a partly fitting delivery, and an unlisted lantern refused intact, all measured in kilograms",
"seeds": [
"hunters-satchel-weight-a",
"hunters-satchel-weight-b"
]
}
}
}