# The Bag as a UI Facade

Lecture ID: lecture_w17_d02
Week 17, Day 2

## Objectives
- Identify the FireRed files, structs, functions, constants, data tables, and state variables that implement each major game system.
- Connect week 17 material to the overall course plan.

## Transcript
All right, let’s pick up exactly where yesterday’s lecture left us. We already treated items as data and state: item records in the item table, quantities in the saved bag pockets, and helper routines that answer questions like “what pocket does this item belong to?” or “can I add three more of these?” Today I want to raise the level of abstraction one step. The bag is not just an inventory array, and it is not just a menu. Architecturally, it is a facade: a UI-facing surface that lets multiple gameplay contexts display, select, confirm, sell, toss, and use items without forcing every caller to understand window allocation, list rendering, money boxes, yes-no menus, pocket layout, or encrypted quantities.

So, on the board, I’m going to write the phrase “canonical inventory versus bag facade.” Under canonical inventory, put gBagPockets, item slots, quantities, pocket capacities, item metadata, AddBagItem, RemoveBagItem, CheckBagHasItem, and CheckBagHasSpace. Under facade, put InitBagWindows, ShowBagWindow, HideBagWindow, OpenBagWindow, CloseBagWindow, GetBagWindow, BagPrintTextOnWindow, BagCreateYesNoMenuBottomRight, BagCreateYesNoMenuTopRight, BagPrintMoneyAmount, and BagDrawTextBoxOnWindow. That second group is not me making up a design pattern vocabulary; those functions are exactly the exported bag interface in pokefirered/include/bag.h, chunk_8f2c0bdfc3224a33. Notice what is absent from that header: it does not expose the save block arrays directly, it does not expose the item table directly, and it does not ask callers to manually calculate tilemap coordinates for every bag-related prompt. It gives menu code a controlled vocabulary for bag UI operations.

Now, before we go further, let’s connect this to the course arc. In earlier weeks, when we traced trainer data into battle setup and battle results back into the overworld, we kept using the same mental chain: data table, runtime globals, callback or task, visible behavior. We are not going to re-teach trainer tables or battle result routing today. The important transfer is the shape of the reasoning. Inventory follows the same architecture, but its visible behavior is much more UI-heavy. The item table tells us what a Potion is. The save block tells us how many Potions the player owns. The bag facade tells us how to show the player the Potion, ask whether they want to use it, display its description, possibly show money, and then route the selection back into item-use logic.

Let’s make that concrete. Suppose the player receives a Potion from an NPC. At the data level, Potion is an item ID, and the item table gives the name, price, description, pocket, use callbacks, and battle usage information. In pokefirered/src/item.c, chunk_1b104a09a7f41ad7, the item system pulls in the item descriptions and data through the included item data table, and it defines the central bag pocket state as EWRAM_DATA struct BagPocket gBagPockets[NUM_BAG_POCKETS]. That is the runtime directory of pockets. It is not itself the saved array of items. Instead, SetBagPocketsPointers connects each pocket entry to the corresponding arrays in gSaveBlock1Ptr: normal items, key items, Poke Balls, TM/HM, and berries. That indirection is a small but important architectural move. The UI and item helper code can talk to gBagPockets uniformly, while the actual persisted storage remains in the save block.

Pause on that, because it is easy to underestimate. If you were designing your lab inventory model this week, and you put one giant array called inventory, you might get something working. But FireRed has different pocket capacities, different presentation rules, and different special cases. The normal item pocket is not the TM case. The berry pouch is not just another row in a flat list. The facade only works because below it there is a structured inventory model with pocket-specific storage and capacity. So in your lab, when you create pockets, stack limits, add and remove operations, and then a UI facade that only exposes display and selection commands, you are mirroring this separation. You are not cloning every FireRed detail, but you are cloning the boundary.

Now look at quantities. FireRed does not simply read slot.quantity as a plain number in the bag path. In pokefirered/src/item.c, chunk_1b104a09a7f41ad7, GetBagItemQuantity returns the stored quantity XORed with gSaveBlock2Ptr->encryptionKey, and SetBagItemQuantity writes the quantity back through the same key. That means code that mutates inventory must pass through the helper routines if it wants to preserve the save representation. This is one of those advanced-level details where architecture and data integrity touch. The UI facade should not know this. A yes-no menu should not know this. A text window that says “Toss how many?” should not know this. The mutation layer knows it.

Check for understanding: if I ask, “Where should the encryption key logic live, in the bag window function or in AddBagItem?” the answer should be immediate. It belongs in the inventory state helper layer, not the facade. The facade displays and gathers intent. The item system validates and mutates state.

Let’s keep following the Potion example. AddBagItem first asks what pocket the item belongs to. The source anchor here is pokefirered/src/item.c, chunk_296b886a4f0b7cc8, where the lookup and mutation flow uses ItemId_GetPocket, scans the selected pocket for an existing slot, checks the current quantity, enforces the stack limit of 999, and either increases the stack or finds an empty slot. That is not merely a convenience routine. It is the inventory invariant enforcer. It decides whether this operation is legal. It decides whether the player can receive the item. It prevents overflowing the stack. It also handles FireRed-specific special cases, such as adding the TM Case key item when the player receives something that belongs in the TM Case pocket and adding the Berry Pouch key item when the player receives berries without already having the pouch.

That last behavior is worth saying slowly. The player-facing fiction is, “I received a berry,” or “I received a TM.” The inventory mutation logic may also need to ensure that the corresponding container key item exists. That is not a pure array append. It is game-rule mutation. This is why the bag should not be treated as a passive data structure. It is a gameplay system with rules, save-state representation, and UI integration.

Now, if I draw the flow on the board, it looks like this: item ID enters from script, pickup, shop, battle reward, or some other game context. Then item lookup determines metadata, especially pocket. Then inventory mutation validates capacity and stack limit. Then, if successful, UI feedback can say the item was obtained or show the updated bag. The facade sits on the visible side of that line. It does not decide whether a Potion can stack to 1002. The mutation function decides that.

The same pattern appears when removing an item. In pokefirered/src/item.c, chunk_296b886a4f0b7cc8, RemoveBagItem rejects invalid item IDs and ITEM_NONE, finds the item in the correct pocket, reads the decrypted quantity, subtracts the requested count only if enough exists, writes the new encrypted quantity, and clears the item ID when the quantity reaches zero. This is the opposite path of AddBagItem, but notice the invariant symmetry. Add does not just draw a new row; Remove does not just hide a row. They both preserve the pocket model.

Now let me ask a quick check question. Imagine a student implementation where the UI list has its own quantities and, when the player tosses an item, the UI decrements the visible number first and later tries to synchronize with the inventory model. What bug class have they introduced? Yes, a duplicated source of truth. The player could see a number that the saved model does not actually contain. Or the item could vanish visually but remain in the save block. FireRed’s architecture pushes against that by making item quantities part of the canonical bag state and making UI code ask through accessors like BagGetQuantityByPocketPosition or BagGetQuantityByItemId, which are part of the continuation of item support in pokefirered/src/item.c, chunk_352eff45b08b4413.

Let’s talk about the item table side for a moment, because it matters to the facade. The bag can show a name and description because the item system exposes item lookup functions. In pokefirered/src/item.c, chunk_352eff45b08b4413, you see a clean family of accessors: ItemId_GetName, ItemId_GetPrice, ItemId_GetHoldEffect, ItemId_GetHoldEffectParam, ItemId_GetDescription, ItemId_GetImportance, ItemId_GetPocket, ItemId_GetType, ItemId_GetFieldFunc, ItemId_GetBattleUsage, ItemId_GetBattleFunc, and ItemId_GetSecondaryId. That tells you the table is not merely a list of display strings. It is the policy source for how the item participates in field use, battle use, holding, shop value, and pocket placement.

This is where the bag facade becomes more than a pretty menu. Suppose the player highlights an Escape Rope. The UI needs a name, an icon or row text, and a description. But when the player presses A, the next behavior depends on item type and field-use callback. The bag does not need to hardcode “Escape Rope warps the player out of a cave” in its window drawing logic. It can ask the item metadata what kind of item it is and which function should run. This is the same data-driven pattern we have used all semester. Battle AI had script pointers and predicates. Trainer battles had trainer records and battle setup. Items have item records and use callbacks.

And, just to show that this is not isolated to one file, the research packet gives us several cross-module inclusions. pokefirered/src/pokemon_summary_screen.c, chunk_e8e17a42bbf17d46, includes item.h and constants/items.h, because held items and party inspection need item data. pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, includes item.h and constants/items.h, because battle logic cares about items and hold effects. pokefirered/src/battle_setup.c, chunk_494d132a59422c85, also includes item.h in the larger battle-entry context. I am not asking you to dive into those modules today; I’m pointing out the architectural reach. Once item data exists, many systems depend on it. That is exactly why the item table and inventory helpers must be stable, and why the bag facade should be narrow.

Now, let’s move to the word “facade” more formally. A facade is not just any wrapper. A useful facade offers a simplified interface over a more complex subsystem while preserving the subsystem’s invariants. In FireRed’s case, the bag-facing UI code has to manage windows, text, yes-no prompts, money display, list rows, and pocket switching. The exported bag header in pokefirered/include/bag.h, chunk_8f2c0bdfc3224a33, gives a compact surface for those operations. InitBagWindows sets up the bag windows. BagPrintTextOnWindow centralizes text rendering with font, position, spacing, speed, and color parameters. ShowBagWindow, HideBagWindow, OpenBagWindow, CloseBagWindow, and GetBagWindow abstract the lifecycle and identity of bag windows. BagCreateYesNoMenuBottomRight and BagCreateYesNoMenuTopRight abstract common confirmation prompts. BagPrintMoneyAmount exists because selling, buying, and money feedback are common enough in bag workflows to deserve a named operation. BagDrawTextBoxOnWindow abstracts the standard text box framing.

What does that buy the rest of the game? It means a sell workflow does not need to become a low-level tutorial in the windowing system. It can ask the bag facade to show a window, print the relevant text, ask for confirmation, and show money. The inventory mutation remains in item.c; the visual affordance remains behind bag.h. This is modularity, but not the abstract, hand-wavy version. It is modularity where you can point to the actual exported functions.

Here’s a concrete example. The player selects a Nugget in the bag while in a shop sell context. The item table says Nugget has a price. The sell flow can use ItemId_GetPrice from pokefirered/src/item.c, chunk_352eff45b08b4413, compute the sale value according to shop rules, display a money amount through the bag UI surface, ask a yes-no question through the bag facade in pokefirered/include/bag.h, chunk_8f2c0bdfc3224a33, and then, if the player confirms, call RemoveBagItem from pokefirered/src/item.c, chunk_296b886a4f0b7cc8. The UI action and the inventory mutation are linked by the selected item ID, but they are not collapsed into one giant function that does everything.

That separation is what I want you to carry into the workshop. Your facade should not expose “array slot 17 has quantity 4; please draw it at x equals 112.” That is too leaky. It should expose operations like “show pocket,” “show item detail,” “prompt confirmation,” “select item,” or “display currency.” Under that, your model can enforce stack limits, pocket rules, and legal add/remove behavior.

Let’s do another check for understanding. If a key item has importance metadata and cannot be tossed, where should the decision come from: the text box function, the selected row renderer, or the item metadata plus context menu policy? Right, metadata plus menu policy. The text box prints. The row renderer draws. The item record and context rules determine whether “Toss” is even a valid action. When you mix those, you create fragile UI code that knows too much about game rules.

Now, advanced point: FireRed has a single-stack assumption in several bag helpers. In pokefirered/src/item.c, chunk_296b886a4f0b7cc8, CheckBagHasItem, CheckBagHasSpace, and AddBagItem scan for an item and then reason about that one stack. The comments in the source note that Ruby, Sapphire, and Emerald check across stacks in certain cases, while FireRed and LeafGreen assume one stack of the item. That assumption is an invariant supported by AddBagItem’s behavior: if an item already exists, it tries to add to that stack rather than creating another duplicate stack. Why do we care? Because a facade can only remain simple when the model underneath is disciplined. If duplicates were allowed, the UI would need a policy for displaying duplicate rows, merging quantities, selling partial quantities from multiple stacks, and so on. FireRed avoids that complexity by enforcing a simpler inventory shape.

You can see a similar cleanup idea in the support functions. BagPocketCompaction, SortAndCompactBagPocket, and SortPocketAndPlaceHMsFirst appear in pokefirered/src/item.c, chunk_352eff45b08b4413. These are not player-facing verbs. The player does not think, “I am compacting my pocket array.” But the user experience depends on those operations. Empty slots should not create strange holes in the list. TM and HM ordering has special presentation expectations. Again, the facade’s apparent simplicity depends on maintenance routines below it.

Let me recap the first half of today’s argument before we push further. The item table answers “what is this item?” The saved bag pockets answer “what does the player own?” The item mutation functions answer “can this operation legally change ownership, and how?” The bag facade answers “how do bag-related screens display information and collect choices?” The player experiences all of that as one seamless bag menu, but the architecture is layered.

And this is why week 17 sits where it does in the course. We have already seen overworld state, scripts, battle transitions, party data, and battle internals. Inventory is where those threads start crossing through UI constantly. Items can be found in the overworld, bought in shops, used in battle, held by party members, displayed in summaries, checked by scripts, and saved persistently. If you design inventory poorly, every one of those systems becomes harder. If you design inventory with a clean data model and a narrow UI facade, those systems can cooperate without becoming one tangled menu file.

All right, hold that model in your head: canonical item state below, bag facade above, item ID as the narrow bridge between them. In the next stretch, we’ll trace the actual selection flow more closely: how a highlighted row becomes a context menu, how context depends on location, and how the bag avoids owning the final behavior of every item it displays.

Good. Let’s pick that apart slowly, because this is the place where people who have built a few menu systems tend to over-generalize. A highlighted row is not an item behavior. A highlighted row is a view coordinate. It is a pocket plus a visible row plus a scroll offset. Only after the bag translates that coordinate through the inventory model do we get an item ID. And only after we combine that item ID with the current bag location do we get a meaningful set of actions.

So, on the board, I’m going to write the chain this way: row, pocket, item slot, item ID, context, command. That is the facade pipeline. The player thinks, “I selected Potion.” The engine thinks, “The cursor is at row two in the current pocket, the pocket state says this corresponds to slot index N, the slot contains item ID X, and because the current location is field rather than battle or shop, the context menu should include this set of commands.” That distinction is exactly why the bag can stay reusable.

Now tie this back to the source. In pokefirered/src/item.c, especially the item system chunk labeled chunk_1b104a09a7f41ad7, the canonical layer is built around gItems, struct Item, struct BagPocket, and gBagPockets. The item record has data fields like name, price, holdEffect, description, importance, registrability, pocket, type, fieldUseFunc, battleUsage, battleUseFunc, and secondaryId. That means the item table does not merely store text. It stores routing hints. It says, in data, “I belong in this pocket,” “I can be used in this mode,” “here is the function pointer for field use,” and “here is the function pointer for battle use.” That is much more sophisticated than a beginner inventory table that contains only name and count.

Then, in pokefirered/src/item.c chunk_296b886a4f0b7cc8, the mutation and lookup flow keeps the bag honest. AddBagItem, RemoveBagItem, CheckBagHasItem, CheckBagHasSpace, GetPocketByItemId, and the quantity helpers are not decorative wrappers. They are the rules of ownership. If the UI wants to display how many Potions you have, it should not rummage through raw save memory and interpret quantity bytes by itself. It should go through the item layer, because the item layer knows about pockets, stack limits, empty slots, and the quantity encoding used by the save system.

Let me pause there. If you remember only one thing from this portion, remember this: the facade is allowed to ask, display, and route. It is not allowed to become the authority on what the inventory means. In a clone project, the moment your bag screen contains its own independent “add item” logic, its own “is pocket full” logic, and its own “what kind of item is this” logic, you have duplicated the model. That duplication will work for the first three items and then betray you when you add held items, key items, battle-only items, or shop selling.

Concrete example. Suppose the player opens the bag from the field and highlights a Potion. The visible menu does not need to know how a Potion heals. First, the UI finds the selected slot. Then it asks the item layer for the item ID by pocket position. FireRed exposes that style of access with BagGetItemIdByPocketPosition and BagGetQuantityByPocketPosition in the item support continuation, pokefirered/src/item.c chunk_352eff45b08b4413. Once the item ID is known, the bag can ask the item table what kind of item this is. ItemId_GetPocket tells us where it belongs. ItemId_GetDescription gives the text for the description panel. ItemId_GetFieldFunc gives the field-use callback. ItemId_GetBattleUsage and ItemId_GetBattleFunc become relevant if we opened the bag from battle.

Notice the phrase “if we opened the bag from battle.” That is the context half of the pipeline. The same item ID can appear in different worlds of possibility depending on where the bag was invoked. We have already seen this pattern in earlier weeks with main callbacks and task dispatch, so I will not re-teach that whole shell. Just connect the ideas. The bag is not a free-floating screen. It is entered from the start menu, from battle, from the PC, from a shop, from party give-item flow, and from a few special tutorial or scripted contexts. Each entry path gives the bag a return callback and a location mode. That is why the bag can answer, “When the player presses B, where do I return?” and “Which actions should I show for this item?”

Now, slide your eyes to the header boundary. pokefirered/include/bag.h chunk_8f2c0bdfc3224a33 is very revealing because it does not expose “heal Pokémon,” “throw ball,” “teach TM,” or “register bike.” It exposes UI operations: InitBagWindows, BagPrintTextOnWindow, ShowBagWindow, HideBagWindow, OpenBagWindow, CloseBagWindow, GetBagWindow, BagCreateYesNoMenuBottomRight, BagCreateYesNoMenuTopRight, BagPrintMoneyAmount, and BagDrawTextBoxOnWindow. That header is a facade contract in the plainest possible sense. It says, “Here are the bag’s window and prompt services.” It does not say, “Here is the entire inventory game.”

That is a strong architectural signal. Headers are contracts, and this one is narrow. It is about the bag as a screen and as a set of menu affordances. The item model contract, by contrast, lives around item.h and item.c: item records, pockets, stack checks, add and remove, and item metadata accessors. A good advanced reading of the codebase is not just, “Where is the function?” It is, “Which file is allowed to know which fact?” Bag UI can know there is a window. Item logic can know that quantities are encrypted against the save key. Battle logic can know whether a battle item is legal in the current battle. Party logic can know whether a selected creature is a valid target. Those responsibilities should not collapse into one giant switch statement just because the player experiences them through one menu.

Let’s do a check for understanding. If the player highlights a Potion in the Items pocket, and the bag wants to print “Potion x3,” where should the quantity come from? Not from the rendered row text. Not from a cached string. Not by reading a raw quantity field and assuming it is plain. It should come from the inventory access path, such as BagGetQuantityByPocketPosition or the equivalent model query, because the model owns the stack quantity. Good. Second check: if the player chooses Use, should the bag screen itself subtract one Potion immediately? Usually no. It should route to the item’s use flow, and the successful item effect should trigger mutation at the appropriate point. If you remove the item before target validation, you create bugs like consuming a Potion when the player backs out of the party menu, or consuming a Poké Ball when the battle rejects the action.

This is why “Use” is not one behavior. “Use” is a command word in the facade. The meaning is supplied by item data and context. A Potion in the field tends to route toward party selection. A Poké Ball in battle routes toward battle item behavior. A Bicycle in the field routes toward an overworld field-use function. A key item may be registrable, may be usable, may only show descriptive behavior, or may be blocked depending on map state. The bag menu presents a tiny verb, but that verb is late-bound through item metadata.

And this is where FireRed’s item table design pays off. ItemId_GetFieldFunc and ItemId_GetBattleFunc, in pokefirered/src/item.c chunk_352eff45b08b4413, make item behavior table-driven at the lookup boundary. The bag does not need a special “if item is Bicycle, then call Bicycle code” branch for every object in the game. The item record already points to the field-use function. That does not mean there are no special cases anywhere; commercial RPG code always has some. But the common path is data to lookup to callback, which is the course thesis showing up again in inventory form.

Now, let’s compare two calls that look similar but mean different things: CheckBagHasSpace and AddBagItem. CheckBagHasSpace is a question. It should be used before a script promises the player an item, before a shop confirms a purchase, or before a pickup flow commits. AddBagItem is a mutation. It actually changes the saved inventory state. In pokefirered/src/item.c chunk_296b886a4f0b7cc8, AddBagItem first asks which pocket the item belongs to through ItemId_GetPocket, then checks whether the item already exists in that pocket, then applies the stack limit, and otherwise finds an empty slot. That is the central rule: pocket assignment is not chosen by the caller. It is read from the item data. If your clone has code like “add Potion to the healing pocket” in shop code, and “add Potion to the item pocket” in field pickup code, you have already created two authorities. FireRed avoids that by making item ID the key and item data the source of pocket membership.

There is also a nice FireRed-specific wrinkle here. Adding TMs or berries can cause the associated container key item, like the TM Case or Berry Pouch, to appear if needed. That behavior is still inside AddBagItem’s flow rather than scattered across every acquisition path. Architecturally, that means acquisition sites can say, “Add this item,” and the inventory model can preserve invariants about companion containers and flags. We will care about that in the lab, because if you implement a Berry-like pocket in your own model, you should ask whether “unlock the pocket container” belongs to the item addition rule or to each script that grants a berry. In almost every design, centralizing it is cleaner.

Let’s bring in the save side for a moment, but only as much as we need. gBagPockets is not itself the entire saved inventory. It is an EWRAM array of BagPocket descriptors pointing at the actual save block arrays for Items, Key Items, Poké Balls, TM/HM, and Berries. SetBagPocketsPointers, in pokefirered/src/item.c chunk_1b104a09a7f41ad7, wires each pocket descriptor to the correct save block storage and capacity. That is a subtle but important pattern. The runtime code wants a uniform “array of pockets” interface. The save layout wants fixed arrays with fixed capacities. gBagPockets bridges those two needs.

So on the board I’ll draw this as two columns. Left column: save storage, fixed arrays, bagPocket_Items, bagPocket_KeyItems, bagPocket_PokeBalls, bagPocket_TMHM, bagPocket_Berries. Right column: runtime pocket interface, gBagPockets indexed by pocket constants. The arrow between them is SetBagPocketsPointers. That arrow is not glamorous, but without it the rest of the inventory code would be full of repeated switch statements. A uniform pointer-plus-capacity descriptor lets CheckBagHasItem and AddBagItem loop generically.

Now think about the UI facade again. The bag screen does not need to know that the Items pocket has one capacity and the Poké Ball pocket has another. It can ask the pocket interface for what it needs to display. It can count non-empty slots, build list rows, and remember cursor state per pocket. The display layer can then say, “I have N rows plus a Cancel row,” which is a UI fact, not a save fact. The model says which slots exist and what they contain. The facade turns that into list menu rows.

Here is a concrete walk-through. Player opens the bag from the start menu. The bag initializes its windows through the bag window API described in pokefirered/include/bag.h chunk_8f2c0bdfc3224a33. It displays the current pocket name, the item list, a description window, and probably an icon area. The cursor is on Potion. The player presses A. The input task converts the current row into an item ID, using the pocket and row position. The UI stores or passes the selected item ID so the next state can inspect it. Then context selection happens: field location, Items pocket, ordinary item, not key item. The context menu can offer commands like Use, Give, Toss, and Cancel. If the player chooses Use, the bag should not know the healing formula. It asks the item metadata for the field-use function, and that function can move the player into a party-selection flow or display “can’t use that here” as needed.

Now replay the same highlighted-row pattern in battle. The player opens the bag from the battle controller. I am deliberately not re-teaching battle result storage or battle controller flow; we covered that in the previous module. But the connection is important: battle enters the bag with a different return path and different legality rules. Now when the player highlights a Poké Ball, the context is battle, so ItemId_GetBattleUsage and ItemId_GetBattleFunc matter. If the player highlights an Escape Rope, the field-use callback may exist, but the battle context should not treat that as usable just because “Use” exists somewhere in the data. Location constrains action.

That location constraint is a major design lesson for your own architecture. Do not attach a single universal “onUse” callback to every item unless your callback receives enough context to reject invalid use cleanly. FireRed separates field and battle function pointers in the item record, which is one way to encode context at the data level. Another valid design is a command registry keyed by item ID and usage context. But the principle is the same: the bag facade asks, “What can I offer here?” before it says, “What happens now?”

Let me ask a diagnostic question. Suppose your clone has a Rare Candy item. The player opens the bag in the field and selects it. The bag shows Use. The player selects a fainted creature, or a creature at max level, or cancels. Where should those checks live? Not in the row selection code. Not in the generic window code. The bag facade can route to party targeting, but the item effect system or party item-use logic must decide whether the target is legal and whether the item is consumed. This is the same boundary we saw with battle AI predicates last week: the caller can request a decision, but the domain module owns the predicate. Party-aware checks belong near party/item behavior, not in the screen that happened to launch them.

Now, money is another clue that bag.h is a facade. BagPrintMoneyAmount appears in pokefirered/include/bag.h chunk_8f2c0bdfc3224a33, and it matters because the bag is reused in shop contexts. But printing money is not the same as owning the economy. The shop system owns price decisions and purchase or sale flow; the item table gives ItemId_GetPrice; the bag facade can show a money window when the current location calls for it. Again, display and selection on top, canonical rules below.

This gives us a nice recap point. The data table says what an item is. The save-backed pocket arrays say what the player owns. The item.c mutation functions enforce how ownership changes. The bag header exposes window and prompt operations. The menu state tracks where the bag is, which pocket is open, and where the cursor is. The context flow turns a highlighted row into a command list, but the final item behavior belongs to item-use, party, battle, overworld, shop, or script systems depending on context. That is why the lecture title calls the bag a UI facade rather than “the inventory system.”

And I want you to notice how this ties to the larger course arc. In week 1, when we discussed AgbMain, SetMainCallback2, and RunTasks, the point was that the game is a set of cooperating state machines. In week 17, the bag is one of those state machines, but it is also a facade over persistent item state. In the battle weeks, we traced data records through runtime globals and callbacks into player-visible behavior. Here, the same trace is: gItems and pocket constants, to gBagPockets and save block item slots, to bag menu state and window commands, to item-use callback or mutation function, to visible feedback. Same architectural grammar, different subsystem.

One more check before we move forward. If I ask you, “Where is the single best place to enforce the 999 item stack limit?” your answer should not be “the shop” or “the pickup script” or “the bag display.” It should be the model mutation path, the same family of logic as CheckBagHasSpace and AddBagItem in pokefirered/src/item.c chunk_296b886a4f0b7cc8. The callers can preflight, but the mutation function must still defend the invariant. Advanced engineering means you do not trust every caller to remember every rule.

So, synthesis for this stretch: the highlighted row is only the beginning of the story. FireRed’s bag works because it translates UI coordinates into item IDs, then lets item data and current location decide what commands are meaningful. Its facade API, shown by pokefirered/include/bag.h chunk_8f2c0bdfc3224a33, is intentionally about windows, text, yes-no prompts, and money display. Its inventory authority, shown by pokefirered/src/item.c chunks chunk_1b104a09a7f41ad7, chunk_296b886a4f0b7cc8, and chunk_352eff45b08b4413, is about item records, pockets, quantities, stack rules, sorting, and lookup. That separation is the reason the same bag can serve field use, battle use, selling, giving, PC interaction, and scripted special cases without every subsystem becoming the bag.

All right, keep the row-to-command pipeline on the board. Next we’ll zoom in on the mutation rules themselves, especially the difference between checking, adding, removing, compacting, and sorting, because that is where many inventory bugs hide even when the UI looks correct.

So, let’s put the mutation pipeline underneath the row-to-command pipeline we already have on the board. I’m going to write five verbs in a row: check, add, remove, compact, sort. Those sound like ordinary inventory verbs, but in a cartridge RPG they are not interchangeable. They are separate because each one protects a different invariant.

A check answers a question without changing the save data. Do I have this item? Do I have enough quantity? Is there space for this new item? An add changes item slots, but only after the system knows the operation can succeed. A remove changes quantities and may erase a slot. Compacting repairs the physical pocket array so the UI does not see holes between valid entries. Sorting imposes pocket-specific order, especially where the player expects a canonical order rather than acquisition order. That distinction is central to the item support code in pokefirered/src/item.c, especially the lookup and mutation flow described in chunk_296b886a4f0b7cc8 and the continuation in chunk_352eff45b08b4413.

Now, pause on that word invariant. In the battle lectures we talked about state being resolved back into the world, and we did not re-run the whole battle every time we wanted to know the outcome. We trusted the battle result storage and the callback path back to overworld. Same architectural discipline here. The bag UI should not “kind of” remove a potion by changing a visible row. The item system must mutate the real pocket slot. The bag UI can ask, display, and route the player, but the authoritative inventory state belongs to the item layer.

Let me give you a concrete example. Suppose the player has one Potion in the items pocket and opens the bag from the field. The list row says Potion, quantity one. The cursor position is not the item itself. It is a UI coordinate. The bag facade translates that coordinate into an item ID. Once we have the item ID, item data tells us what kind of thing it is, which pocket it belongs to, whether it has a field-use function, what text to show, and what price or effect values are associated with it. Those item record lookups are part of the item system in pokefirered/src/item.c chunk_1b104a09a7f41ad7, where item data records and accessor-style behavior are the real foundation.

Then the field-use command tries to use the item. If the potion successfully heals a party member, only then should removal happen. Not when the item row is highlighted. Not when the menu opens. Not when the yes-no prompt appears. Successful effect first, inventory mutation after. That is one of the simplest ways to avoid duplication bugs. If a player cancels from the party menu, the item should still be there. If the selected Pokémon is already full HP and the command fails, the item should still be there. The UI may show messages, but the item count changes only when the game rule says the item was consumed.

Now look at the board. I’m drawing the item pocket as an array of slots. Each slot has an item ID and a quantity. Slot zero, Potion, quantity one. Slot one, Antidote, quantity three. Slot two, empty. The bag list that the player sees is derived from that structure. It is not the structure. That difference matters because the bag may also include a Cancel row, may preserve scroll position, may draw icons, may display descriptions, and may temporarily hide or refresh entries. The facade in pokefirered/include/bag.h chunk_8f2c0bdfc3224a33 exposes exactly those kinds of operations: bag text, windows, prompts, money display, selection handling, and visual support. That header is a cross-module contract for presentation behavior, not a license for every caller to hand-edit pocket arrays.

Check for understanding here. If the cursor is on row two, do we know the item ID yet? Not safely. We know a UI row. We must translate through the current pocket’s list state. And if the player changes pockets, row two may refer to an entirely different item, or to no item at all. Good. That is why “selected row” is facade state, while “item ID and quantity in a pocket slot” is inventory state.

Now let’s separate add from check. Imagine the player receives five Poké Balls from an NPC. The script wants to give the item, but the bag may be full. A careless implementation says, “Find the first partial stack, fill it, then if there is no empty slot, stop.” That is dangerous, because now the operation may partially succeed. Maybe two balls were added and three were not. Sometimes that is intended, but in a scripted reward flow it usually is not. The cleaner pattern is to ask first: is there enough space for all five? That is the conceptual role of a space check in the mutation flow. Once it returns yes, the add operation can confidently modify slots.

And the check must understand stack limits. It cannot merely ask, “Is there an empty slot?” If the player already has a stack of ten and the max stack is higher, the new items can fit without a new slot. Conversely, if the player has many full stacks and no empty slots, the item cannot be added even though the item ID is already present. So the check walks the pocket using the same pocket and stack rules that the add operation will use. That pairing is what keeps the user-visible bag from lying.

This is where many student clones fail in the week 17 lab. They implement pockets, and they implement a screen, but they make “add item” a UI operation. Then, when they later add shops or battle rewards, they copy the same logic into three places. FireRed avoids that by making inventory mutation a lower-level service. The shop, the field script, the battle reward, and the PC withdrawal flow can all converge on item functions, while the bag facade remains responsible for display and selection.

Now removal has its own pitfalls. If I remove one Potion from a quantity-one slot, I do not want a visible row with Potion quantity zero. Zero is not a small amount of Potion; zero means the slot should stop representing Potion. So removal usually has two phases. First, reduce the quantity or clear the slot. Second, repair the pocket so later UI traversal sees a clean list. That repair is compaction.

Let’s work it explicitly. Slot zero Potion one. Slot one Antidote three. Slot two Escape Rope one. Use the Potion. Slot zero becomes empty. If we leave it like that, the list code has to decide whether to skip empty slot zero, and every cursor calculation becomes more complicated. Instead, compaction moves Antidote and Escape Rope forward, then leaves the empty slot at the end. So after compaction: slot zero Antidote three, slot one Escape Rope one, slot two empty. The player experiences this as “Potion disappeared and the list closed up.” The source-level reality is that the pocket array has been normalized.

Sorting is a different operation from compaction. Compaction only removes holes. Sorting decides order. Some pockets should preserve the player’s acquired order, because the player expects the bag to feel personal or chronological. Other pockets, such as technical machines or berries, often benefit from canonical ordering by item ID or category because the player is searching a known series. The important point is not that every pocket sorts identically. The important point is that sorting is a rule of the inventory model, not a visual afterthought. The item support continuation in pokefirered/src/item.c chunk_352eff45b08b4413 is relevant here because it keeps these support behaviors near the item and pocket logic instead of burying them in the window drawing code.

Now, connect that to constants. Item IDs are constants. Pocket IDs are constants. Quantities and capacities are constrained by constants and structs. The bag does not store “a thing called Potion” as a string. It stores an item ID. The display layer can use that ID to fetch the item name and description. The mutation layer can use that ID to find the correct pocket. The battle and field systems can use that ID to decide what commands are legal. That is the same data-table-to-runtime-behavior path we have used since the early architecture weeks, just now in inventory form.

I’ll point to two cross-system signs that the architecture is not isolated. The Pokémon summary screen includes item-related headers and constants in pokefirered/src/pokemon_summary_screen.c chunk_e8e17a42bbf17d46, because held items and item display cross from inventory into party UI. Battle utility code includes item infrastructure and item constants in pokefirered/src/battle_util.c chunk_9335e5727aa0657d, because item effects matter in battle without the battle engine becoming the bag menu. And daycare code, in pokefirered/src/daycare.c chunk_119931105f546346, includes constants/items.h among many menu and Pokémon-related headers, which is a useful reminder that item identity is a shared vocabulary across systems. Shared vocabulary, not shared ownership. That distinction is subtle but very important.

Let’s do a quick verbal trace. A player opens the bag from the start menu. The main callback and task machinery, which we covered earlier in the course, is responsible for getting into the menu and running per-frame input. The bag facade owns the windows, printed text, icons, arrows, yes-no prompts, and current selection behavior, as represented by pokefirered/include/bag.h chunk_8f2c0bdfc3224a33. The selected row becomes an item ID. The item ID is looked up through item data in pokefirered/src/item.c chunk_1b104a09a7f41ad7. A command is chosen. If that command changes inventory, the mutation functions in item.c, especially the flow represented by chunk_296b886a4f0b7cc8, check and update the real pocket slots. After mutation, the bag view refreshes from state. The direction of dependency is the key: state first, view derived.

Here is a good exam-level question. Why should the bag facade expose money display helpers if money is not an item pocket? Think for a second. The answer is that the bag participates in shop-like flows where the player sees item quantities, prices, sell prompts, and current money. The facade can provide a consistent money window without making money an item. That is a UI composition concern. Selling still has to remove an item through inventory mutation rules, and money still has to update through the money state rules. The shared screen does not imply shared storage.

This is also why yes-no prompts belong in the facade. “Toss this item?” “Use this item?” “Give this item?” The prompt is presentation and control flow. But the yes branch must call into the appropriate game rule. If we toss five Antidotes, the prompt collects intent and quantity; the item system validates and removes. If the item is a key item that cannot be tossed, item data and command rules should prevent or reject that operation. The window is not the law. The window is the clerk at the counter.

Now check your understanding with a failure case. Suppose your clone updates the visible quantity label from three to two when the player uses an item, but forgets to update the underlying pocket array. What happens next? The immediate screen may look correct, but the next time the list is rebuilt, the quantity goes back to three. Or worse, a save writes the old quantity. That is a facade-only mutation bug. Now suppose the reverse: you update the pocket array correctly but forget to refresh the list buffer. The save data is correct, but the current screen lies until the player changes pockets or reopens the menu. That is a stale-view bug. Both bugs come from confusing derived UI state with authoritative inventory state.

We can make this more advanced. The bag is not merely a list of items; it is a mode-sensitive command surface. Opening the bag in the field is different from opening it in battle. Opening it from a shop is different from opening it from the party menu. The same item ID may have different legal commands depending on context. A Potion in the field may offer Use, Give, Toss, or Cancel depending on rules. In battle, it may offer battle use if the battle-use field says it is legal. In a shop, it may participate in sell flow and money display. The item data and current entry mode together determine the command set. That is why treating the bag as “an inventory screen” is too narrow. It is a facade over item identity, pocket state, command routing, and UI mode.

Write this sentence in your notes if you are keeping design principles: a facade is allowed to simplify access, but it must not become the owner of every rule it touches. FireRed’s bag facade simplifies text, windows, prompts, pocket visuals, selection, and money presentation. It does not replace item records. It does not replace pocket mutation. It does not replace battle item effects. It does not replace party held-item rules. It coordinates.

Now, let’s connect to the lab. Your inventory model needs pockets, stack limits, add and remove operations, and a bag UI facade that exposes display and selection commands. At the advanced level, I expect your check operation to be side-effect-free. I expect your add operation either to be atomic for the requested quantity or to document partial-add behavior explicitly. I expect remove to handle zero quantities by clearing and compacting. I expect the UI list to be rebuilt or patched after mutation. And I expect your command layer to receive an item ID, not a row label string.

One more concrete example before we move on. Suppose a player has a registered key item. If that item is removed by some special flow, the registration state cannot keep pointing to a nonexistent item. This is a broader invariant: inventory mutation can have secondary state consequences. We saw similar patterns in battle result routing, where one result variable is not the entire world transition but influences the transition path. Here, removing an item may require checking whether any UI shortcut, held reference, or special state still points at it. You do not want SELECT to try to use an item the player no longer owns.

So the sophisticated view is this: item.c is not just a bag backend; it is an inventory authority. bag.h is not just a header full of menu utilities; it is the public shape of a facade. Other systems include item constants and item helpers because item identity matters everywhere, but that does not mean every system should know how to compact a pocket. That is the architectural boundary we are studying today.

All right, local recap before the next segment. Row selection becomes item ID. Item ID connects to item data. Item data and bag mode determine commands. Commands call game rules. Successful rules call inventory mutation. Mutation checks, adds, removes, compacts, and sorts according to pocket rules. The facade then refreshes the player’s view. Keep that chain on the board, because next we are going to use it to analyze the difference between using an item, giving an item, and selling an item, and those three cases are where the facade boundary becomes especially visible.

So, let’s take those three cases one at a time, and I want you to listen for a repeated pattern. The Bag is not “the place where item behavior lives.” The Bag is the place where item behavior is presented, selected, confirmed, and visually refreshed. That distinction sounds almost semantic until you trace one of these flows carefully.

First case: using an item. When the player highlights a Potion and chooses Use, the Bag facade has enough information to know that the highlighted row corresponds to an item ID and that this command is currently permitted. It does not need to contain the whole healing algorithm. The deeper rule is attached to item identity and to the context in which the item is being used. In FireRed, that relationship is visible in the item support code centered in pokefirered/src/item.c, especially the item lookup and mutation flow in chunk_296b886a4f0b7cc8 and the continuation in chunk_352eff45b08b4413. The item system gives other systems ways to ask, “What is this item? What pocket does it belong to? What behavior should it dispatch to? Can the bag accept or remove this quantity?” The Bag facade then wraps those questions in list selection, message boxes, yes-no prompts, and callback routing.

Now, put this on the board as a small flow. I’ll write: highlighted row, item ID, item metadata, command menu, target selection, effect function, consume or do not consume, refresh. That is the use-item path in architectural language. Notice that consumption is not the first thing that happens. That is important. A novice implementation often removes the item as soon as the player selects Use. That is wrong for a real RPG architecture, because the use can fail, be canceled, require a target, or produce no effect. If the player chooses Potion, then backs out of the party menu, the Potion should not disappear. If the player chooses an item that cannot be used here, the UI should explain that and preserve state. If a battle item is attempted outside battle, the context check should block it before mutation. So the facade asks and routes; the rule system decides; the mutation helpers perform the actual add or remove only after the rule succeeds.

That should sound familiar from battle outcomes last week. We did not let the battle transition screen decide whether a trainer was defeated. The battle result state told the overworld script machinery how to continue. Same architectural principle. Visual surface is not the owner of the rule. The Bag is a surface. Item mutation is a rule service. The player experiences it as one seamless menu, but the code is divided so that the same item identity can matter in the overworld, in battle, in party screens, in shops, and in scripts.

Second case: giving an item. Giving looks deceptively similar to using. The player selects an item, chooses a command, maybe chooses a party member, and something changes. But the semantic target is different. Using a Potion targets a creature’s HP and usually consumes the item after a successful effect. Giving an Oran Berry or held item targets the creature’s held-item slot. The operation is not “apply item effect now.” It is “transfer item ownership from bag stack to party data,” possibly with a swap if the creature is already holding something.

That means the Bag facade must cross into the party UI, but it should not become the party model. This is why includes tell us a lot about architecture. In pokefirered/src/pokemon_summary_screen.c, chunk_e8e17a42bbf17d46, the summary screen includes item.h, constants/items.h, party_menu.h, and related UI and data headers. That does not mean the summary screen owns the bag. It means the party-facing UI needs item identity and item display rules because held items are visible and interactive there. Conversely, the Bag needs to route toward party selection when an item command requires a creature target. These modules meet through item IDs and helper APIs, not by merging into one giant inventory-party object.

Let me make that concrete. Suppose the player highlights a held item in the Bag, chooses Give, and selects the second party member. The facade’s responsibilities are: preserve the selected item ID and quantity context, launch or coordinate the party selection screen, display the relevant messages, and return to the correct menu state afterward. The game-rule responsibilities are: check whether the item is holdable in this context, check whether the selected creature can receive it, update that creature’s held item field, and decrement or swap the bag quantity correctly. If the creature already has a held item, the resulting flow may need a prompt. “Switch items?” That yes-no prompt is facade work. The actual swap is model mutation.

Check for understanding here: if I ask you, “Where should the code live that draws the yes-no prompt for replacing a held item?” you should say, the Bag or menu facade layer, or a closely related UI helper, not the item rule table itself. If I ask, “Where should the code live that decides whether the selected item leaves the bag and becomes the creature’s held item?” you should say, the inventory and party mutation path, not the text printer. This is exactly the boundary made visible by pokefirered/include/bag.h, chunk_8f2c0bdfc3224a33, because that header exposes bag text, windows, yes-no, and money interface concepts. It is a contract for interaction, not a dumping ground for every item effect.

Third case: selling an item. Selling is especially useful because it proves that item data is reused in a totally different context. In a shop, the player is not using the item and not giving it to a party member. The player is converting some quantity of a bag stack into money. So the relevant item properties are pocket, quantity, and price. The relevant UI surfaces are the sell list, quantity selector, confirmation prompt, and money display. Again, the Bag facade helps present and select, but the economic rule is separate from row drawing.

On the board, I’ll add a second column beside Use. For Sell, the chain is: highlighted row, item ID, price lookup, quantity selection, confirmation, remove quantity, add money, refresh list and money window. The important comparison is that both Use and Sell begin with highlighted row to item ID, and both end with mutation plus refresh. But the middle is different. Use dispatches to an effect. Sell dispatches to an economy operation. Give dispatches to party ownership transfer. The facade’s power is that it gives these flows the same navigational language without pretending they are the same rule.

You can see the need for that shared language in the bag header focus, pokefirered/include/bag.h, chunk_8f2c0bdfc3224a33. The presence of bag windows, text helpers, yes-no interaction, and money interface in that contract tells us the Bag menu is not just an array viewer. It is a UI coordinator. It owns the little rituals: print the message, draw the box, ask the question, show the amount, return to the list. But when we trace into pokefirered/src/item.c, chunk_1b104a09a7f41ad7, chunk_296b886a4f0b7cc8, and chunk_352eff45b08b4413, the center of gravity shifts toward item records, bag pockets, quantities, lookup helpers, and mutation rules.

Now, a subtle point for advanced students. The facade boundary does not mean zero coupling. FireRed is a C codebase on the Game Boy Advance, not a dependency-injected enterprise service mesh. You will see includes across systems. You will see global save data. You will see callback state. You will see menu modules directly aware of item constants. The architecture is not “pure.” The question is whether responsibilities are still legible. And here they are. Item identity is represented by constants. Item properties live in data records and helpers. Bag storage is pocketed and quantity-based. UI operations are exposed through menu and bag-window helpers. Other systems include item headers because items are a shared domain concept, not because every system should implement pocket compaction.

This is the mature way to read this codebase. Do not ask, “Is it perfectly separated?” Ask, “What kinds of decisions are localized?” Pocket capacity decisions are localized around inventory helpers. Display decisions are localized around menu and bag helpers. Item effect dispatch is localized around item metadata and use context. Party-held-item mutation touches party state. Money display and money mutation touch the shop and wallet path. That is a real architecture, even if it is built in C with globals and callbacks.

Let’s connect this to your week 17 lab, because this is exactly where I expect your designs to become more precise. The lab asks you to create an inventory model with pockets, stack limits, add and remove operations, and a bag UI facade that only exposes display and selection commands. That wording is not accidental. If your facade has a method called healCreatureWithPotion, that is a smell. If your inventory model has a method called drawSellConfirmationWindow, that is also a smell. A clean clone architecture would have something like item records, bag pocket storage, inventory mutation helpers, and UI commands. The UI command may say, “show item list,” “show command menu,” “ask yes-no,” “show money,” “open party selection,” and “refresh current pocket.” The rule layer may say, “can use item in this context,” “apply item to target,” “give item to creature,” “sell item quantity,” and “remove item quantity.” Keep those verbs separate.

Here is a concrete clone example. Imagine your item table has an item called Antidote. Its record says it belongs in the medicine pocket, has a price, has a field-use behavior, and is consumable on success. The bag contains item ID Antidote with quantity three. The player opens the medicine pocket. The UI facade displays “Antidote x3.” The player chooses Use. The facade does not cure poison. It calls into an item-use flow with the item ID and current context. That flow asks for a party target. The player selects a poisoned creature. The effect succeeds. Only then does the inventory mutation helper remove one Antidote, leaving quantity two. The facade refreshes the row. If the player selected a creature that was not poisoned, the effect should fail gracefully, and the quantity should remain three. That one example tests whether you have separated display, targeting, rules, and mutation.

Now compare a sell example. Same Antidote, quantity three. The player is in a shop sell menu. The facade displays the item and may display expected sale value. The player selects quantity two. The confirmation prompt appears. The player confirms. The rule path removes two Antidotes and adds the correct amount of money. The facade refreshes the list and money window. There is no party target. There is no status cure. Same item ID, different command context, different rule path. If your code handles this by duplicating three separate item-list implementations, you have missed the facade opportunity. If your code handles this by making the item table draw windows and mutate money directly, you have collapsed too many responsibilities into the data layer.

Let me pause for a quick check. In the phrase “the Bag as a UI facade,” what is the facade hiding? It is hiding the fact that underneath one player-facing menu there are several different systems: item data, save-backed pocket arrays, quantity and stack rules, party-held-item state, field-use callbacks, battle-use restrictions, shop economy, text windows, cursor state, and callback return paths. What is the facade exposing? A coherent set of interactions: browse pockets, select an item, choose a command, confirm a choice, show feedback, and return to the correct screen. If that distinction is clear, the rest of today’s lecture becomes much easier.

Now I want to bring in the callback/task model without re-teaching it. Earlier in the course, we treated SetMainCallback2 and RunTasks as the runtime shell. That shell is the reason a menu like the Bag can feel modal without being a blocking function call in the normal desktop sense. The Bag can install a main callback, create tasks for menu behavior, wait across frames for input, and then return through a stored callback when the flow is finished. That is the same broad runtime pattern we have seen in overworld transitions, battle setup, and party screens. The Bag facade is not just a set of drawing functions; it is also a state coordinator living inside that callback/task architecture.

This is where state variables matter. A bag UI has to remember more than the raw inventory. It needs current pocket, scroll position, cursor row, selected item, command menu state, maybe previous callback, and mode, such as normal field use, battle use, berry choosing, or selling. The save data can tell you what items exist. It cannot tell you where the cursor was in the current menu session unless the UI state records that. That distinction is another major exam-level point. Persistent inventory state and transient UI state are not the same state. Persistent state answers, “What does the player own?” Transient state answers, “What is the player currently looking at and doing?”

If you look at the provided source focus, that division is exactly why pokefirered/src/item.c chunks are paired this week with pokefirered/include/bag.h chunk_8f2c0bdfc3224a33. The item code gives us ownership and mutation. The bag interface gives us presentation and interaction. You need both to understand the feature, but you should not flatten them into one mental bucket called “inventory.” For an advanced architecture course, “inventory” is too vague. Say item records when you mean metadata. Say bag pockets when you mean save-backed storage. Say mutation helpers when you mean add, remove, compact, or sort. Say bag facade when you mean the player-facing menu coordinator.

Let’s also connect briefly to battle, since recent lectures covered battle result storage and AI predicates. Items participate in battle, but they do not become battle AI. A battle item selected by the player enters the battle controller flow as an action with item identity and target implications. The battle system includes item headers because item effects and held items matter during battle. The research packet points to pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, which includes item.h and constants/items.h alongside battle headers, move constants, ability constants, hold effects, and weather constants. That include pattern is a good architectural signal. Battle utilities need item facts because held effects, consumables, and battle-use items influence battle logic. But the battle utility file is not the Bag menu. It does not need to know how the Bag list cursor is drawn.

Likewise, pokefirered/src/battle_setup.c, chunk_494d132a59422c85, includes item.h among overworld, script, save, safari, and battle transition headers. That tells us item identity can matter when entering or configuring battle-related flows. Again, shared domain concept, separate UI facade. This is how we weave prior foundations forward. Trainer tables and wild encounter inputs got us into battles. Battle result storage got us back out. AI script predicates let battle choose actions under constraints. Items now cross those boundaries because they are both data and player resources. The architecture succeeds when crossing the boundary does not mean every subsystem owns every other subsystem’s state.

Now, one more board cue. I’m going to draw three boxes: Bag facade, item service, and domain target. Under Bag facade I’ll write list, cursor, windows, prompt, money display, callback return. Under item service I’ll write metadata lookup, pocket lookup, stack capacity, add, remove, compact, price. Under domain target I’ll write party creature, battle battler, shop wallet, field script. The arrows go both ways only at controlled points. The facade sends item ID and command intent. The item service returns facts or mutates inventory. The domain target applies the actual effect or receives ownership. Then the facade refreshes.

That diagram is not just for FireRed. It is the design you should use in your own clone. It scales. If you add a new pocket, the facade should need new display labels and maybe pocket navigation, but your item use effects should not all be rewritten. If you add a new sellable item, the shop flow should ask the item table for price rather than hard-coding it in the sell menu. If you add a new status-curing medicine, the effect table or item-use dispatch should define the cure, and the Bag should simply expose Use when the context allows it. This is the difference between a system that grows through data and one that grows through menu-specific special cases.

Before we move on, recap the three operations in one sentence each. Use means selected item identity is routed to an effect in a context, and inventory is consumed only if the effect succeeds. Give means selected item identity is transferred into party-held-item state, with prompts and swaps handled through UI coordination. Sell means selected item identity and quantity are converted into money through price lookup, confirmation, removal, and wallet update. Same facade, three different rule paths.

And here is the synthesis for this segment. The Bag looks like a menu, but architecturally it is a negotiation point. It negotiates between what the player can see, what the player intends, what the item data says, what the inventory can legally mutate, and what the surrounding game mode allows. FireRed’s source organization, especially pokefirered/src/item.c chunk_1b104a09a7f41ad7, chunk_296b886a4f0b7cc8, chunk_352eff45b08b4413, and pokefirered/include/bag.h chunk_8f2c0bdfc3224a33, gives us a concrete version of that negotiation. Keep that model in mind, because the next step is to look at how quantity, capacity, and compaction make the facade reliable. The player never sees “slot five became empty and slot six slid upward,” but the code has to get that right every time, or the beautiful menu becomes a very polished way to corrupt inventory state.

So, let’s now slow down around quantity, capacity, and compaction, because this is where a lot of student inventory models start to look correct in the happy path and then quietly fail in the cases that real players hit constantly. Buying five Potions, using one Potion, finding a Potion on the ground, tossing all but one Potion, sorting pockets implicitly by removing an empty slot, switching from the Bag to the party menu and back, these are not exotic cases. These are the normal life of the system.

I want you to imagine the board divided into three vertical columns. On the left, I’m writing “storage model.” In the middle, I’m writing “mutation rules.” On the right, I’m writing “facade presentation.” The Bag screen belongs mostly to the right column, but it is only credible because the left and middle columns are disciplined. If the Bag facade prints a quantity, it is trusting the storage model. If it allows “Use,” it is trusting the item data table and the surrounding mode. If it removes an item, it is trusting the mutation rule to leave the pocket in a stable shape afterward.

This is why we do not describe the Bag as “just a menu.” A menu can be a list of labels and callbacks. The Bag is a facade over a constrained inventory database, and that database is small enough to fit in fixed arrays, but complicated enough that you still need database thinking. FireRed’s item system source in pokefirered/src/item.c chunk_296b886a4f0b7cc8 is the part of the packet that should make you think in terms of lookup and mutation flow, not merely button handling. And pokefirered/src/item.c chunk_352eff45b08b4413 continues that support layer, which matters because inventory correctness is not one function. It is a family of operations that agree about what an empty slot means, what a full stack means, and what should happen when a slot reaches zero.

Now, concrete example. Suppose the player already has ninety-eight Potions in the regular items pocket, and then receives three more Potions from an NPC. The visually simple version is: “You obtained three Potions.” The model version is more precise. First, look up the item’s pocket using the item data, because the reward system should not hard-code where Potions live. Second, scan the relevant pocket for an existing Potion stack. Third, check whether adding three exceeds the legal stack limit. Fourth, if the existing stack cannot absorb all three, decide whether the game permits a second stack for that item or whether it treats this as no space. Fifth, if there is no existing stack, find an empty slot. Sixth, write the quantity through the sanctioned mutation path, not by having the NPC script scribble over inventory memory.

And I want to emphasize that last phrase: sanctioned mutation path. In an advanced codebase, you are often tempted to say, “Well, I know where the array is, I’ll just increment the quantity.” That is how you get inconsistencies. The whole point of a file like pokefirered/src/item.c, especially the lookup and mutation material represented in chunk_296b886a4f0b7cc8, is that several callers can ask the same inventory questions and get the same rules. Shops, field pickups, battle rewards, PC item storage, item use, and scripts should not each invent their own definition of space.

Check for understanding here. If a student implementation has a nice scrolling Bag UI, but the shop code can add items by directly pushing into the first empty array slot, while the field pickup code uses a different helper that stacks quantities first, what is the bug? The bug is not simply “duplicated code.” The deeper bug is that the same player-visible inventory has two legal systems. One system thinks stack-first; the other thinks empty-slot-first. The facade will faithfully display whatever result emerges, but it cannot make contradictory mutation policies coherent.

Let’s bring the Bag header back into the picture. The packet identifies pokefirered/include/bag.h chunk_8f2c0bdfc3224a33 as the bag text, windows, yes-no, and money interface. That description is very revealing. Notice what kind of work is being made available across modules: print text in Bag windows, draw or manage Bag-specific prompts, handle money presentation, support yes-no confirmation behavior. This is the visible and interactive layer. It is not the same conceptual layer as “decide whether the inventory has space for three Potions.” The header is a contract for UI operations around the Bag experience.

So if I write on the board, “bag.h equals facade surface,” I do not mean it contains every implementation detail of the inventory system. I mean it tells neighboring systems, “Here are the commands you may use to make the Bag present information, ask the player a question, and show money-like state in the Bag context.” That is a C-style facade. It is not a Java class named BagFacade. It is a header boundary plus a set of source functions plus shared state conventions.

Now let’s talk compaction. Say the player has three occupied slots in a pocket: Potion, Antidote, Escape Rope. The player uses the last Potion. The Potion quantity reaches zero. What should the array look like after removal? You could leave an empty hole in slot zero and keep Antidote in slot one and Escape Rope in slot two. That is possible, but then every display loop, every add-item loop, every count loop, and every save/load assumption must tolerate holes. Or you compact the pocket so Antidote slides into slot zero, Escape Rope slides into slot one, and the final slot becomes empty. That makes display and lookup simpler, but now the mutation function has a responsibility: after deletion, preserve the invariant that used slots are contiguous.

That word “invariant” should be in your notes. Advanced architecture is not just naming the structs. It is naming the invariants those structs rely on. A Bag pocket is not merely “an array of item slots.” It is an array plus a capacity plus rules about how empty entries are represented, whether duplicate item IDs are allowed, whether quantities are bounded, whether quantities must be accessed through helpers, and whether occupied slots must remain compacted. The functions in pokefirered/src/item.c chunk_296b886a4f0b7cc8 and chunk_352eff45b08b4413 are important because they are where those rules become executable.

Let me give you a debugging scenario. A player opens the Bag and sees five items. They use the second item until it is gone. The UI returns to the list. If the model compacts correctly, the cursor might now point to the item that slid into that row, or it might adjust upward if the removed item was at the end. Either behavior can be valid if it is deliberate. But if the UI’s list buffer still thinks the old slot exists, while the underlying pocket has already compacted, then the cursor might select stale data. That is the kind of bug that looks like a UI bug and is actually a facade synchronization bug.

This is why the Bag’s list state and the inventory model state should not be conflated. The list screen may have scroll position, cursor row, current pocket index, and perhaps a cached list of visible item names. The model has item IDs and quantities. The facade sits between them. When the model changes, the facade needs to rebuild or refresh the view’s assumptions. In a task-driven UI, which you already know from our earlier work on callback slots and RunTasks, that refresh may happen across frames. The architectural discipline is the same as the battle and overworld systems we studied earlier: the player experiences one continuous interaction, but the engine experiences a sequence of state transitions.

Let’s connect that to Week 17’s lab. Your lab model with pockets, stack limits, add and remove operations, and a Bag UI facade should not let the UI own the truth. The UI can own selection. The UI can own display formatting. The UI can own prompts. The UI should not be the only place that knows that a Potion belongs in the items pocket or that a stack is full. That belongs in the item model and mutation layer. If your remove button subtracts quantity directly inside the widget callback, you have made the callback too powerful. A better structure is: callback identifies intent, facade asks model operation to apply intent, model returns success or failure, facade updates display and messaging.

Now, because you are advanced students, let’s also consider why FireRed’s design is constrained in a way your modern implementation might not be. This is a Game Boy Advance title. Fixed-size arrays are not just a quaint style; they are a hardware-appropriate design choice. You do not casually allocate arbitrary dynamic lists on every Bag interaction. A pocket has capacity. That capacity is part of gameplay, save layout, and UI layout. In a modern clone, you might choose vectors or lists internally, but if you are learning from FireRed, you should still preserve the idea of explicit capacity and explicit failure. “No room for this item” is not an exception thrown by accident. It is a game rule surfaced by the facade.

Here is a second example, and this one crosses into money. The player enters a shop and buys ten Poké Balls. The shop screen and Bag screen are not identical, but they share inventory and money concerns. The money presentation and helper surface identified in pokefirered/include/bag.h chunk_8f2c0bdfc3224a33 reminds us that money is not only an integer somewhere in the save file. It becomes a UI element, a confirmation element, and a transaction constraint. The transaction sequence is: calculate price, check wallet, check Bag space, ask for confirmation, subtract money, add item, then update the visible money and item displays. If you subtract money before confirming Bag space, you have created a rollback problem. If you add the item before subtracting money, you have created a duplication or interruption problem. The facade can make that transaction feel like a simple yes-no prompt, but the ordering underneath matters.

Pause there and ask yourself: in your own clone, what should happen if the player can afford ten Poké Balls but only has space for nine, or for none? There are several possible design answers, but there should not be several accidental code answers. You might clamp the purchase quantity. You might reject the purchase. You might permit stacking if the existing stack can absorb it. Whatever you choose, the shop should ask the inventory mutation layer, not guess from the UI list length.

This is also a good moment to fold in prior course material without re-teaching it. When we studied trainer tables and wild encounter inputs, we talked about data tables becoming runtime behavior through a chain of lookup, state, and callbacks. The Bag follows the same course thesis. Item records say what the object is. Pocket arrays say what the player currently owns. Mutation helpers say what can legally change. Bag UI functions say how the player sees and selects. The callback and task shell coordinates the interaction over time. That is the recurring pattern: data table to runtime state to callback or task to visible behavior.

The item system has a particularly important relationship to other modules because items are used everywhere. The packet’s excerpts from pokefirered/src/pokemon_summary_screen.c chunk_e8e17a42bbf17d46 show that the summary screen includes item-related headers and constants along with party menu and battle-related material. That tells us something architectural: held items and item display are not isolated inside the Bag screen. The party summary needs item knowledge too. Similarly, pokefirered/src/battle_util.c chunk_9335e5727aa0657d includes item-related headers and constants alongside battle constants, moves, abilities, hold effects, and battle move effects. Again, the point is not to re-open the battle engine today. The point is that item data participates in battle behavior. A held item is inventory-adjacent, party-adjacent, and battle-adjacent.

So the facade has to be selective. It should expose enough to let the player interact with inventory, but it should not become the universal item authority for the entire game. Battle utility code should not need to ask the Bag window how a held item works. The summary screen should not need to pretend it is inside the Bag to show an item. Shared item data and item helpers belong lower than the Bag UI. Bag text and Bag windows belong at the facade level. That distinction is what keeps the architecture from turning into a knot.

Let me put a small pseudo-flow on the board, verbally. Player presses A on an item row. The Bag facade resolves the selected row into an item ID and quantity. It consults item metadata to decide what commands are possible: use, give, toss, register, cancel, or some subset. The player chooses Toss. The facade asks for a quantity, then asks for confirmation. The mutation layer removes that quantity from the correct pocket. If the quantity reaches zero, the pocket is compacted according to the invariant. The facade refreshes the visible list, adjusts cursor and scroll state, and prints the result message.

Now, tell me where the item description text belongs in that flow. It belongs to item data lookup and display formatting. Tell me where the cursor row belongs. It belongs to UI state. Tell me where the decision “quantity cannot go below zero” belongs. Mutation layer. Tell me where the yes-no prompt belongs. Bag facade. That separation is the lecture in miniature.

One more check for understanding. If I can trigger item removal from three places, the Bag Toss command, a field script that takes an item, and a battle effect that consumes a held item, should all three call identical UI code? No. They do not all need Bag windows. Should all three obey compatible item removal rules? Yes. That means they should share model-level removal semantics where appropriate, even if the presentation differs. The Bag is a facade, not the root of all item truth.

This is also why constants matter. Pocket identifiers, pocket capacities, item IDs, hold effect constants, and menu action constants are not decorative names. They are the vocabulary that allows independent systems to coordinate without magic numbers. When pokefirered/src/battle_util.c chunk_9335e5727aa0657d pulls in constants for items and hold effects, and when pokefirered/src/pokemon_summary_screen.c chunk_e8e17a42bbf17d46 pulls in constants for items alongside party and move-related headers, we are seeing those vocabularies cross module boundaries. Good architecture does not eliminate cross-module knowledge. It makes that knowledge explicit and stable.

Let’s bring this back to your Week 17 homework expectation. At this point in the course, I am not impressed by an inventory that only passes “add item to empty bag.” That is Week 3 thinking. For Week 17, your model should handle existing stack, full stack, empty pocket, full pocket, partial removal, complete removal, cursor adjustment after compaction, and failed mutation with a user-facing message. Your facade should be able to display the same model state without becoming the owner of that state. And your tests should target the rules, not only the pixels.

For example, test that adding an item already present increments the quantity and does not create a duplicate slot if your rule forbids duplicates. Test that removing the exact remaining quantity clears and compacts. Test that removing more than owned fails without changing state. Test that a full pocket rejects a new item but still accepts quantity into an existing non-full stack if your design allows that. Then test that the Bag facade responds to those outcomes: success message, failure message, list refresh, money update if relevant. That is how you make the UI facade reliable instead of merely pretty.

Now I want to close this segment, not the lecture, with a synthesis of the architectural pattern. The Bag’s surface is friendly: windows, text, money display, yes-no prompts, scrolling lists. The packet names pokefirered/include/bag.h chunk_8f2c0bdfc3224a33 as exactly that kind of interface surface. Under it, the item source chunks, especially pokefirered/src/item.c chunk_296b886a4f0b7cc8 and chunk_352eff45b08b4413, represent the lookup and mutation responsibilities that make that surface trustworthy. Around it, summary screens, battle utility, shops, scripts, and party interactions all need item knowledge without all becoming Bag UI code.

So when you design your own creature RPG, do not ask, “Where do I draw the inventory menu?” first. Ask, “What are the legal states of the inventory, what operations preserve those states, and what facade commands let the player express intent?” Once you can answer that, the menu becomes much easier. In the next part, we will keep this same mental model and look more closely at how item use routes outward: from a selected Bag row into party selection, field effects, battle constraints, and return callbacks. That is where the facade stops being just a display boundary and becomes a traffic controller between game modes.

So let us take that next step now. We have been treating the Bag as a facade over inventory state, and now I want you to notice something slightly more demanding: a facade is not only a pretty front door. In a game like FireRed, the Bag is also a router. It receives a player intention, such as “use this item,” “give this item,” “toss this item,” “register this item,” or “cancel,” and then it must hand that intention to the correct system without corrupting inventory, UI state, party state, battle state, or overworld state.

I am going to say that again in a more architectural way. The Bag is not the owner of every consequence caused by an item. It is the owner of item selection flow. That distinction matters. The Bag should not become the battle engine just because a Potion can be used in battle. It should not become the party menu just because a TM, held item, or medicine may target a party member. It should not become the field scripting engine just because a key item may trigger an overworld effect. Instead, it should package the selected item, preserve enough return context, and transfer control to the next mode.

Board cue here: I would write three boxes. The first box says “Inventory model.” The second box says “Bag facade.” The third box says “Destination system.” Then I would draw arrows from the Bag facade to party menu, battle, field script, shop, and summary screen. The key point is that all of those destinations may need item knowledge, but none of them should need to know how the Bag scrolls, prints, highlights rows, or draws money.

This is why the source layout we have been using this week is so useful. In pokefirered/src/item.c, chunk_1b104a09a7f41ad7, the item system is grounded in item data records. In pokefirered/src/item.c, chunk_296b886a4f0b7cc8, the lookup and mutation flow gives other systems legal ways to ask item questions and change inventory quantities. In pokefirered/src/item.c, chunk_352eff45b08b4413, the continuation of item support reinforces that item behavior is not just one menu function. And then pokefirered/include/bag.h, chunk_8f2c0bdfc3224a33, exposes the Bag-facing text, window, yes-no, and money interface. That is a contract boundary. It is not merely a list of convenience helpers. It tells us which operations the Bag UI expects to perform without forcing all item logic to live inside the drawing code.

Now, let us work through a concrete example. Suppose the cursor is on a Potion. The player presses A and chooses Use. At that moment, the Bag facade has a row selection, a pocket, and an item id. The item system can tell us what the item is, what pocket it belongs to, whether it has field use behavior, what its price is if we are in a money context, and what kind of restrictions apply. But the Potion’s actual effect, when used on a party member, is not “draw a Bag row differently.” It is “select a target creature, validate that the target can receive healing, mutate that creature’s HP, remove one item from the inventory if the use succeeds, then return to an appropriate UI state.”

Notice the ordering there. Validate first, mutate second, return third. Many student inventory systems get this wrong. They remove the Potion as soon as the player presses Use, then discover the selected creature is already at full HP, and now they need awkward rollback code. FireRed’s architecture pushes us toward the better pattern: selection is not consumption. A selected item becomes an intent. The destination system confirms whether the intent is legal. Only then does the mutation flow remove or decrement the inventory stack through item.c’s inventory operations.

Check for understanding: if I ask, “Should the Bag remove the item before or after the party target confirms a legal effect?” the answer is after. More precisely, after the target system has accepted the use and the effect has succeeded under the rules of that item. The Bag can initiate the command, but it should not eagerly assume success.

This same idea applies to TMs and HMs, and here the connection to earlier weeks becomes important. We do not need to re-teach move learning today, but remember that learn_move.c was described in the packet as a move relearner state machine, with menu and task flow in pokefirered/src/learn_move.c, chunk_af3598df6f092723. That source is not Bag code, but it is a reminder that move-related UI in FireRed is itself a state machine. So if an inventory item leads to move learning, the Bag must route into another controlled flow. It should not inline the whole move learning interaction. It asks, “What item did the player select?” Then the move-learning or party-selection side asks, “Which creature is eligible?” and, “What move slot changes?” Different responsibilities, different state machine.

Now, look at the implication for your lab this week. When you create an inventory model with pockets, stack limits, add and remove operations, and a Bag UI facade that exposes only display and selection commands, I expect you to preserve this separation. Your inventory model should be able to answer, “Can I add three Antidotes?” without knowing where the cursor is. Your Bag facade should be able to say, “The player selected row four in the medicine pocket,” without knowing how poison curing is implemented. Your item-use dispatcher should be able to ask, “Is this a field item, a party-target item, a battle-use item, or a key item?” without redrawing the whole menu.

Slide cue: if I put the word “Use” on the slide, I would put it in quotes, because “Use” is not one operation. It is a family of operations that share an entry point. A Repel, a Potion, an Escape Rope, a Bicycle, a Poké Ball in battle, and a key item all fit under the player-facing word “Use,” but architecturally they route to different handlers with different preconditions.

That is why item data records matter. Last time we treated them as structured facts: name, pocket, price, effect-related fields, and so on. Today we treat them as routing hints. The item record does not have to contain an entire novel of behavior. It contains enough identity and classification for the runtime to choose the correct behavior path. In pokefirered/src/item.c, chunk_1b104a09a7f41ad7, that data-driven foundation is the difference between hard-coding every Bag row and letting item definitions participate in behavior. Then, in pokefirered/src/item.c, chunk_296b886a4f0b7cc8, the lookup and mutation functions keep those records usable by callers that are not themselves the Bag.

Let me connect this to another file from the packet. pokefirered/src/pokemon_summary_screen.c, chunk_e8e17a42bbf17d46, includes item.h and constants/items.h alongside party menu, battle, strings, and summary screen dependencies. That is an architectural clue. The summary screen needs item awareness, particularly around held items and creature information, but it is not the Bag. So item knowledge is deliberately shared through item interfaces and constants, while display ownership remains local to the summary screen. If you put all item behavior in your Bag menu class, your summary screen either duplicates logic or imports UI code it should not depend on. Both are warning signs.

The same pattern shows up on the battle side. The packet points us to pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, which includes item.h and constants/items.h along with battle constants, hold effects, abilities, weather, moves, and battle controllers. That tells us battles need item facts, especially held effects and battle-use consequences, but the battle utility layer does not become the overworld Bag menu. Again, shared item semantics, separate mode ownership. This is the same design discipline we used when tracing battle outcome storage back to the overworld. A system may receive a result or query a data table without owning the whole previous mode.

Let us pause there and test the boundary. Imagine you are designing your own creature RPG, and your Bag screen has a function called useSelectedItem. Inside that function, you check whether the item is a Potion, directly increase the selected creature’s HP, play the healing sound, decrement the item stack, update the Bag row, update the party summary, close the menu, and resume overworld control. Is that convenient? Yes, for the first item. Is it architecture? No. It is a pile-up of responsibilities. The moment you add Revive, Rare Candy, Escape Rope, battle-only balls, held items, key items, registered items, and shop selling, that function becomes the place every bug goes to hide.

A more FireRed-like architecture makes useSelectedItem mostly a routing command. It says: identify the item, identify the context, select a target system, store return information, and let the destination system run its own state machine. Inventory mutation remains centralized through inventory operations. Display remains exposed through Bag window and text helpers. Money display and yes-no prompts remain facade-level services where appropriate. And behavior that belongs to party, battle, or field systems remains there.

Now, a question I would ask in class: what state variables does the Bag have to preserve when it routes away? Think for a moment. It has to preserve the selected pocket. It has to preserve the scroll position or cursor position. It may need to preserve the selected item id. It may need to preserve the previous callback or return callback. It may need to preserve whether we entered from the field, battle, shop, or another menu. These are not cosmetic details. They are what allow the player to come back to the right place after a failed use, a successful use, or a cancellation.

This should sound familiar from our callback and task weeks. We are not restarting that material, but the connection is direct. FireRed uses main callback slots and task-driven per-frame dispatch to move between modes. So when the Bag opens party selection, or returns to the overworld, or hands off to a battle-use path, it is participating in the same runtime shell we studied earlier. The Bag is not a modal dialog in a desktop application. It is a cooperative state machine inside a GBA program, where transitions must be explicit and state must be recoverable.

Let us make the example more precise. The player chooses a Potion from the Bag while standing in the overworld. The Bag records enough information to return to the Bag if the player cancels the party selection. It opens the party menu in an item-use context. The party menu lets the player choose a creature. The healing logic checks whether the creature can be healed. If not, the game displays a message and does not consume the item. If yes, the creature state mutates and the item quantity decrements. Then the UI returns to a sensible place: maybe back to the Bag, maybe back to the party view, depending on the exact flow. The facade is the source of the command, but the command passes through validation gates.

Now compare that to a key item, such as a Bicycle-style field item. There may be no party target. The selected item routes to a field-use function. The item must check location restrictions, player state, and overworld conditions. Again, the Bag itself should not become the overworld movement engine. It should ask the item-use dispatch layer to run the field function. If the effect is legal, control leaves the Bag and returns to the overworld with the player mounted or with a field effect applied. If it is illegal, the Bag or field message layer reports the failure. Same facade, different destination.

And then compare that to a battle item. The packet’s reference to pokefirered/src/battle_setup.c, chunk_494d132a59422c85, reminds us that battle entry and transition code already depends on item.h among many field, script, and battle modules. That is not an accident. Items participate in battle setup and battle-adjacent flow, but they do so as one part of a larger mode transition system. In battle, using an item also consumes turn structure. It may be disallowed in trainer battles for certain item types, allowed for medicine, constrained by battle state, or routed through a controller command. The Bag can provide a battle item list, but battle legality belongs to battle context.

Check for understanding: why is a Poké Ball different from a Potion, architecturally? Both are items. Both may appear in a Bag pocket. Both may be selected. But a Potion targets one of your party creatures and mutates party HP, while a Poké Ball in battle targets the encounter and routes through capture logic. If your item-use abstraction only says “apply item to target,” you have hidden an important distinction: target types differ by mode. Some targets are party slots. Some are enemy battlers. Some are the overworld. Some are no target at all.

This is where advanced design starts to matter. Beginners often ask, “Should I make an Item class with a use method?” Advanced designers ask, “What are the item-use contexts, what state must each context carry, and what system owns each effect?” FireRed’s C architecture does not express this with object-oriented classes, but the boundary is still present. Data records, constants, globals, callbacks, task state, and source-module contracts together create the equivalent architecture.

So, in your own implementation, I would not start with a giant virtual method hierarchy unless your engine already leans that way. I would start with item definitions, pocket definitions, and a small dispatcher table or function switch that maps item type and context to a handler. Your Bag facade calls the dispatcher. The dispatcher either rejects the action with a message or pushes the next mode. The inventory model exposes add, remove, count, and capacity checks. The destination systems own their own validation. That gives you room to add new item categories without turning the Bag into a kitchen-sink module.

Let me bring bag.h back into the discussion. In pokefirered/include/bag.h, chunk_8f2c0bdfc3224a33, the packet identifies the Bag text, windows, yes-no, and money interface. That is exactly the sort of header that should make you ask, “Who is allowed to draw what?” Money is a particularly good example because it appears in shops, item purchase flows, sell flows, and sometimes ordinary menu displays. The Bag facade can expose helpers for printing and updating money, but money itself is a game-state resource. The text box showing a price is UI. The player’s money amount is persistent state. Buying an item crosses both: money decreases, inventory increases, and UI refreshes.

If you mix those together too aggressively, you get subtle bugs. For example, imagine a purchase flow where the UI updates the displayed quantity before checking whether the inventory has room. The player sees the item count change, but the model rejects the add. Or imagine the money display subtracts the price visually before the transaction commits, then the bag is full. Now the display and state disagree. FireRed’s separation of item mutation helpers, Bag display helpers, and menu/money helpers gives us a better mental model: transactions should commit in the model, then the facade should redraw from truth.

That phrase is worth keeping: redraw from truth. Do not let your UI become the truth. The Bag row says “Potion x3” because the inventory model contains three Potions. The row should not be the authority that there are three Potions. If a battle item use removes one Potion, the Bag should eventually display “Potion x2” because the shared inventory state now says two. This is especially important in a GBA-style codebase, where many screens can observe or mutate related state across mode transitions.

Let us also connect this to save persistence, because week 17 is not floating alone. We are in the Items, Menus, and Party UI module, but the course as a whole is moving toward complete RPG architecture. Inventory state must be saved. Bag cursor state usually need not be saved permanently. Item definitions are compiled data. Item quantities are player state. UI windows are transient state. Money is player state. Selected menu actions are transient state. That classification is one of the big skills you are expected to have by now. When homework_w16 and quiz_w16 asked you to decompose a creature-collector RPG into runtime shell, overworld maps, event scripting, creature data, battle, inventory, UI, save, and link systems, this is the level of decomposition I wanted: not just naming systems, but knowing which data belongs to which lifetime.

A quick recap before we move forward. Item records define what items are. Inventory pockets and quantities define what the player currently owns. The Bag facade displays those facts and captures player intent. Item lookup and mutation functions keep state changes legal. Destination systems, such as party, battle, field, shops, and summary screens, use item knowledge without becoming Bag UI code. The architecture works because each layer knows enough to cooperate, but not so much that every module becomes every other module.

Now, let us sharpen this with one more example: held items. A held item touches the Bag, the party menu, the summary screen, and battle utility. The Bag may let the player choose Give. The party menu chooses the creature. The creature data stores the held item. The summary screen displays it; the packet’s pokefirered/src/pokemon_summary_screen.c, chunk_e8e17a42bbf17d46, is a useful source marker here because it includes item interfaces in a screen that is not the Bag. Then battle utility may later read the held item and interpret hold effects; the packet’s pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, supports that battle-side item dependency. One player command, four systems. If you implement held items only as “remove from bag and put text on summary screen,” you have missed the battle behavior. If you implement them only in battle, you have missed ownership transfer and UI affordance. If you implement them only in the Bag, you have made the Bag responsible for creature equipment, summary presentation, and battle effects. None of those are good outcomes.

So what does a good held item flow look like? The Bag selects the held item. The party menu selects a creature. The game checks whether the creature already holds something. If necessary, it asks a yes-no question, using the same kind of menu helper boundary reflected in bag.h’s yes-no interface from pokefirered/include/bag.h, chunk_8f2c0bdfc3224a33. If the give operation succeeds, inventory loses the item and the creature gains it. If the creature swaps items, inventory may receive the previous held item. Then any visible screen redraws from the model. Battle does not need to be notified immediately in most ordinary field contexts; it will read the held item when battle state is constructed or when relevant battle utility checks run.

Check for understanding: where is the held item after the Give command succeeds? Not in the Bag. Not in the summary screen. It is in creature state. The Bag may no longer list it because inventory count changed. The summary screen may display it because creature state changed. Battle may later interpret it because battle logic reads creature-held item data. That is architectural ownership.

This is also a good moment to warn you about naming. In small projects, students often name a module InventoryUI and then put addItem, removeItem, itemPrice, useItemInBattle, drawItemWindow, and saveInventory inside it. That name is lying. A module that mutates inventory, prices purchases, performs battle effects, draws windows, and serializes save data is not a UI module. Names should make boundaries visible. FireRed’s split between item.c responsibilities and bag.h’s Bag-facing interface is not perfect in the abstract textbook sense, but it gives us a real production example of separating item facts and mutations from Bag presentation services.

Now, as we move toward the next part of the lecture, keep one larger course connection in mind. We have repeatedly traced player-visible behavior through data tables, globals, callbacks, tasks, scripts, structs, and source functions. The Bag is another instance of that same trace. It just happens to be deceptively familiar because every RPG player knows how to open a Bag. But the architecture underneath is not trivial. The Bag is where persistent state, transient UI state, data-driven item records, transaction rules, mode transitions, and destination-specific behavior all meet.

So when you work on the lab, I want your inventory model to be boring in the best possible sense. It should have clear pocket rules, stack limits, add and remove operations, and no dependency on screen drawing. I want your Bag facade to be expressive but restrained. It should display pockets, display items, expose selection commands, show money or prompts where appropriate, and route intent outward. And I want your item-use flow to respect context. A medicine item, a held item, a battle item, a field item, and a key item may all begin with the same cursor movement, but they do not end in the same subsystem.

We will continue from here by following that outward route more closely. We have now established that the Bag is a facade and a traffic controller. Next, we will inspect the traffic itself: how a selected row becomes a use request, how party selection or battle constraints refine that request, how cancellation returns to the previous mode, and how successful item use commits state changes without letting the UI become the authority.

Now, when we say “traffic,” I want you to imagine one selected row leaving the Bag and passing through a series of gates. The first gate asks, “What item is this?” The second asks, “Where are we?” The third asks, “Does this item require a target?” The fourth asks, “If it succeeds, who is allowed to mutate inventory state?” That sequence is the architecture. The Bag does not simply say, “Use Potion” and decrement a count. It asks the item system, party system, battle or field context, and mutation helpers to converge on a valid action.

Let me put a small flow on the board. Cursor row, item id, item metadata, context rule, target choice, effect function, inventory mutation, return callback. Notice that only the first two pieces are really Bag-local. The cursor row belongs to the UI. The item id comes from the selected pocket slot. After that, the Bag is mostly handing off. That is why the source focus for today spans both `pokefirered/src/item.c` and `pokefirered/include/bag.h`. The item records and lookup or mutation flow live in `pokefirered/src/item.c`, especially the item system and lookup chunks identified for us as `chunk_1b104a09a7f41ad7`, `chunk_296b886a4f0b7cc8`, and `chunk_352eff45b08b4413`. The Bag-facing window, text, yes-no, and money interface is represented by `pokefirered/include/bag.h`, `chunk_8f2c0bdfc3224a33`. So even at the file boundary, the architecture is telling us something: display commands and inventory authority are adjacent, but not identical.

Concrete example. Suppose the player selects a Potion outside battle. The selected row is not enough. The row maps to an item slot in a medicine pocket, and that slot gives us an item id and quantity. Then the item metadata tells the game that this item is usable and that its use path involves a party target. So the Bag opens or routes into party selection. If the player cancels from the party screen, nothing should be removed. If the player chooses a fainted creature when the item cannot affect fainted creatures, nothing should be removed. If the player chooses a valid injured creature and the effect succeeds, then and only then does the inventory count change. That “then and only then” is the point. Mutation belongs after validation and effect resolution, not at row selection.

Check your understanding here. If your clone project removes the Potion as soon as the player presses A on the Bag row, what bug have you created? Yes, exactly: cancellation and invalid target selection can consume inventory. That is not a UI bug in the narrow sense. It is an authority bug. You let the facade perform a domain mutation before the domain action succeeded.

Now compare that to a key item. Same row selection, different traffic. A key item may not have a stack decrement at all. It may route to a field script, a registered-item behavior, or a special case connected to overworld state. This is where our earlier weeks matter, but I am not going to re-teach the map or script system. Just recall the shape: data record, runtime state, callback or script, visible behavior. The Bag is another entry point into that same course-wide pattern. In week 16, you were assessed on decomposing the whole RPG into runtime shell, overworld, event scripting, party, battle, inventory, UI, save, and link systems. Today’s material is more advanced because we are not just naming those systems. We are watching one player command cross their boundaries.

Slide forward mentally to battle items. In battle, the item-use request has an additional constraint gate. The current battle mode, turn ownership, item category, target legality, and battle controller flow all matter. We already studied battle result storage and win-loss routing, so use that as foundation: battle is not a popup owned by the Bag. It is a state machine with its own rules. The Bag can present item choices during battle, but the battle system must decide whether and how that request becomes a battle action. That distinction is why `pokefirered/src/battle_util.c`, `chunk_9335e5727aa0657d`, is useful as a supporting comparison in the research packet: it shows battle code importing item definitions alongside battle constants, moves, abilities, and hold effects. Items are consumed by battle logic, but battle logic remains battle logic.

Let me pause and ask a sharper question. Why do we prefer this traffic-controller design over putting one large “use selected item” function inside the Bag UI? Because the same item id can mean different things in different contexts, and the same UI selection pattern can terminate in different systems. A facade centralizes the player-facing presentation. It should not centralize every rule. If it does, you get duplication, brittle special cases, and eventually a Bag that knows too much about party healing, battle turns, overworld scripts, money formatting, and save mutation.

The money interface is a good smaller example. Buying and selling visually resemble inventory navigation, and the Bag header may show money, but money is not just decorative text. Money is player state with its own formatting and update rules. The inclusion of money helpers in `pokefirered/include/bag.h`, `chunk_8f2c0bdfc3224a33`, tells us the Bag UI needs to display and coordinate money-related prompts. It does not mean every economy rule belongs in the Bag. In your lab model, your facade can expose “show money,” “ask yes or no,” and “show quantity selector,” but the transaction service or shop state should be the authority that says whether the player can afford the operation and when the item enters inventory.

Board cue: I am underlining “selection is not commitment.” That sentence should be in your design notes. A selected item is an intention. A confirmed target plus a valid context plus a successful effect is a commitment. And after commitment, mutation helpers update the actual inventory state: pocket contents, quantities, stack limits, and compaction if a stack reaches zero. That is where the item mutation flow in `pokefirered/src/item.c`, especially `chunk_296b886a4f0b7cc8` and `chunk_352eff45b08b4413`, belongs in your mental map.

One more example before we close. Imagine a Rare Candy. It begins like a medicine item in the Bag, because it needs a party target. But its effect is not just “change HP.” It may touch level, stats, moves, evolution-related consequences, and party summary display. That connects forward to the party UI and summary screen. The packet’s `pokefirered/src/pokemon_summary_screen.c`, `chunk_e8e17a42bbf17d46`, is relevant here because summary and party-facing UI include item constants and item access in their surrounding dependencies. The item is not isolated. A single inventory action can require creature data, move learning, UI refresh, and persistence to agree.

So here is the synthesis for today. FireRed’s Bag is best understood as a UI facade over a more distributed inventory architecture. Item tables describe what items are. Bag pockets and quantities describe what the player owns. Bag window functions display and collect choices. Context systems, such as party, battle, overworld scripts, shops, and money helpers, refine what those choices mean. Mutation functions commit the result only after the action is valid. That is the architectural lesson I want you to carry into the workshop: build your inventory model so the facade is pleasant to use, but make the model and context rules strong enough that the UI cannot accidentally become the truth.

Next time, we will carry this same discipline into the surrounding menus and party interfaces. We will ask how the game keeps selection state, creature state, item state, and return callbacks coordinated without turning every menu into a copy of every other menu. For now, your test for your own design is simple: can you cancel at every stage without corrupting state, can you reject invalid targets without consuming items, and can you commit successful item use in exactly one authoritative place? If the answer is yes, you are no longer just drawing a Bag screen. You are designing the inventory boundary of a creature RPG.

## Source References
- pokefirered/src/daycare.c
- pokefirered/src/pokemon_summary_screen.c
- pokefirered/src/learn_move.c
- pokefirered/src/battle_util.c
- pokefirered/src/battle_setup.c
