# Dex Lookup Compared to FireRed Tables

Lecture ID: lecture_w22_d01
Week 22, Day 1

## Objectives
- Trace FireRed gameplay from data records through globals, callbacks, tasks, scripts, structs, and concrete source functions.
- Connect week 22 material to the overall course plan.

## Transcript
All right, let’s pick up exactly where week 21 left us. We are not restarting the architecture story today. By now, when I say “FireRed system,” I expect you to hear a chain: data record, global state, callback, task, script, struct, concrete function, then visible gameplay. That chain is the spine of the course. Week 22 changes the comparison point. We are now putting Pokemon Showdown’s Dex beside FireRed’s static-table architecture, not because Showdown replaces FireRed, but because it exposes a modern version of a problem FireRed solves in a much more compiled, cartridge-shaped way.

So, on the board, I’m writing two phrases. On the left: “FireRed tables are compiled authority.” On the right: “Showdown Dex is a runtime data facade.” Those are not slogans. They are architectural claims. In FireRed, if we want move data, species data, ability constants, item constants, or battle effects, we usually find ourselves moving through C headers, generated constants, compiled arrays, globals, and engine functions. In Showdown, the caller is often deliberately insulated from the raw storage layout. You ask the Dex for a move, or a species, or an item, and the Dex gives you a normalized object for the active ruleset or generation mod.

That facade idea is explicit in the week’s source packet. The Showdown Dex documentation in pokemon-showdown/sim/DEX.md, chunk_922688d7428150d1, is our anchor for the Dex purpose and move lookup. The generation-specific angle comes from pokemon-showdown/sim/DEX.md, chunk_5fbe60392b5eedf9, where Dex.mod is the key idea: you do not merely look up “Thunderbolt” in an abstract universal database; you look it up through a generation or mod context. And the broader API surface, moves, species, abilities, and items, is grounded in pokemon-showdown/sim/DEX.md, chunk_74ee605430e5596f. Keep those three chunks together in your notes, because together they define the modern comparison target.

Now, let’s connect that to FireRed. Suppose the player selects a move in battle. In FireRed, the move is not fetched by calling a general-purpose object API that merges mod layers at runtime. The move is represented by identifiers and records that the engine already knows how to index. The battle engine uses constants from headers, data arrays, battle globals, and battle scripts. That is why a FireRed trace often starts from something like constants/moves.h, then goes into battle data, then into src/battle_util.c or battle script execution. The packet gives us pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, and the excerpt itself is useful because the include list tells a story. It pulls in battle.h, battle_scripts.h, battle_message.h, constants/moves.h, constants/items.h, constants/abilities.h, constants/pokemon.h, and constants/battle_move_effects.h. That include cluster is not decorative. It tells you that FireRed’s battle behavior is assembled from compile-time contracts across modules.

Let me slow that down. In Showdown, a move lookup tends to ask, “What does this move mean in this Dex context?” In FireRed, the question is more like, “Given this move id and this battle state, which compiled tables, constants, flags, globals, and scripts now participate?” That is a very different shape.

Here is the concrete example I want you to hold for the next twenty minutes. Imagine we are tracing a move like Flamethrower. In Showdown, the lookup-facing version of the story is simple at the entry point. You obtain the Dex for the format or generation, ask for the move, and inspect the returned move record. The record may include base power, type, accuracy, category, flags, secondary effects, and other simulator-facing fields. The data side is visible in files like pokemon-showdown/data/moves.ts, and the packet specifically calls out chunk_012eada95ff7aa5f as secondary move data. That “secondary” word matters, because Showdown’s data can model things that are not just raw cartridge tables. It can hold simulator annotations, modern mechanics, and cross-generation concerns.

In FireRed, Flamethrower’s story is more tightly bound to the compiled game. A move id participates in party data, battle move selection, battle script execution, type and damage calculation, animation, message printing, PP reduction, AI evaluation, and result state. You do not get one friendly object with all behavior behind an accessor. You get a network. That network is why our course has repeatedly traced from data through globals and callbacks. If we only say “the move has base power 95,” we have not understood the architecture. We need to ask where that value is stored, who indexes it, who mutates battle state, who schedules visible output, and which callback or task gets us back to the main loop.

Now, quick check for understanding. If I ask you, “Where is the architectural boundary in Showdown?” your answer should not be “moves.ts.” That is a data file, not the boundary. The boundary we care about today is the Dex interface: moves.get, species.get, abilities.get, items.get, and the generation-specific Dex.mod layer described in pokemon-showdown/sim/DEX.md, chunks chunk_5fbe60392b5eedf9 and chunk_74ee605430e5596f. If I ask the same style of question about FireRed, your answer also should not be just “constants/moves.h.” That is a contract, not the full boundary. FireRed’s boundary is distributed across headers, compiled tables, structs, globals, script commands, callbacks, and battle engine functions.

Let’s make that visible. I’m drawing a line on the board. Top of the line: “data identity.” Middle: “runtime state.” Bottom: “presentation and effects.” In FireRed, a species id or move id starts as a compact identity. It becomes meaningful when runtime state uses it. A party Pokemon struct stores species, moves, PP, stats, status, experience, and other properties. In battle, that party data is copied or projected into battle structs and globals. Then battle functions and battle scripts interpret those values. The player sees text, animation, HP bar changes, fainting, experience, item effects, and post-battle transition.

That is why prior weeks matter. We already covered AgbMain and the callback shell. We already covered SetMainCallback2. We already covered CreateTask and RunTasks. I am not going to re-teach them, but I want you to reuse them. The main loop responsibilities from pokefirered/src/main.c, chunk_b35676322b169f85, and the callback switching represented by pokefirered/src/main.c, chunk_6cfd90f6d0136799, are part of every visible gameplay trace. Task allocation and per-frame dispatch, from pokefirered/src/task.c, chunk_cb0bb91a147bfb59 for CreateTask and chunk_3ffebc0341225936 for RunTasks, are still the runtime shell. Today we are placing data lookup inside that shell.

So when a student says, “Showdown’s Dex is cleaner,” I want to ask, cleaner for what? It is cleaner for querying battle data across many formats. It is cleaner for tools. It is cleaner for tests. It is cleaner for saying, “Load Gen 7, fetch this species, compare this move’s properties, filter nonstandard entries.” FireRed is cleaner for a small, fixed target: one cartridge-era ruleset, one memory budget, one executable, predictable indexes, no need for arbitrary runtime mod stacking. That does not make FireRed primitive. It makes FireRed specialized.

Now let’s turn to generation mods, because this is where the comparison becomes more than cosmetic. Showdown needs to represent many rule worlds. Gen 1, Gen 2, Gen 3, modern generations, DLC variants, custom mods, Pet Mods, National Dex formats, and so on. Dex.mod exists because “the data” is not one thing. pokemon-showdown/sim/DEX.md, chunk_5fbe60392b5eedf9, is important because it tells us to think of the Dex as parameterized by a rules context. A lookup happens through that context.

FireRed, by contrast, is already a context. Its compiled code is the context. The move table is not asking, “Which generation am I?” The whole program is the answer: this is FireRed’s Gen 3 ruleset with FireRed’s content constraints and engine behavior. If you want a different generation in FireRed, you do not usually call Dex.mod. You change constants, tables, engine code, scripts, assets, and sometimes save compatibility assumptions. You rebuild the world.

Let’s use a very precise example. In Showdown, if a script asks for an ability record, it can use the Dex abilities API. The data file pokemon-showdown/data/abilities.ts, chunk_da22cf969179258c, even contains simulator-facing ratings. The excerpt describes ability ratings from detrimental to essential, with examples like Slow Start, Flame Body, Magic Bounce, and Shadow Tag. FireRed does not need an “ability rating” field for its cartridge battle engine. That rating is useful to a simulator ecosystem, teambuilder, AI heuristics, or analysis tools, but it is not a required runtime field for FireRed’s original battle behavior. This is our first important distinction: modern battle data files often mix mechanical truth, simulator support, tooling convenience, and metagame annotations. FireRed data tends to be closer to the minimum compiled substrate needed by the game, with behavior distributed into C and scripts.

Check yourself here. If you inspect Showdown data and see extra fields, do not immediately map every field back to FireRed. Some fields are battle semantics. Some are UI or teambuilder semantics. Some are compatibility or mod semantics. Some are analysis annotations. The architecture skill is to classify the field before comparing it.

Now, let’s talk about nonstandard filtering. This is the part of the week that prevents a lot of bad lab submissions. Showdown has a large data universe. Not everything in the data files is legal or standard in every context. The packet explicitly points us to pokemon-showdown/sim/NONSTANDARD.md, chunk_800f1eafbea0ed7c, with the note that all data requires filtering. That should immediately change how you write lookup scripts. A naive script that prints every move or species in a Dex and says, “This is the game data,” is architecturally sloppy. The Dex can expose records that need to be filtered by generation, availability, format, legality, or nonstandard status.

FireRed has filtering too, but it often appears as content gating rather than Dex-level metadata. A species might exist as a constant. An item might exist in a table. A map might contain or not contain a wild encounter entry. A script might set a flag that permits access. A save block might remember progression. We covered save block ownership and load-save initialization before, and I am only invoking that foundation now: persistence affects what the player can access, but it does not work like Showdown’s nonstandard field. In Showdown, a record can be present yet marked unusable for a format. In FireRed, a record can be compiled in yet never normally reached, or reached only after a flag, map event, item, trade, gift, or script branch.

Let me give you a lab-shaped example. Suppose your workshop script loads a generation mod, asks for Pikachu, asks for Thunderbolt, prints their records, and then filters nonstandard data. For Showdown, that script belongs to the Dex facade layer. It should demonstrate that your lookup context matters. It should probably include species, moves, abilities, and items, because pokemon-showdown/sim/DEX.md, chunk_74ee605430e5596f, frames those as related lookup APIs. But your commentary beside the script should say, “This differs from FireRed because FireRed does not generally perform these as runtime facade lookups. FireRed indexes compiled tables and routes the result through engine state.”

Now, I’m going to put a small trace on the board, and I want you to notice the difference in verbs.

For Showdown, the verbs are: load, mod, get, inspect, filter, simulate.

For FireRed, the verbs are: index, copy, mutate, dispatch, script, render, persist.

That is a little compressed, but it is a useful mental model. Showdown’s Dex interface is designed for callers that want stable access to data across a changing universe. FireRed’s data is designed to be consumed by a fixed runtime. Showdown says, “Ask me for the record in this context.” FireRed says, “Here is the identity; the engine already knows the context.”

Now, because this is an advanced class and not week 3, I want to push one level deeper. The most common mistake at this point is to compare data files to data files. “moves.ts has this field; FireRed’s move table has that field.” That can be useful, but it is incomplete. The better comparison is access pattern to behavior. In Showdown, a move record may include callbacks or structured fields that the simulator turn engine uses. We saw an example of generation-specific script behavior in pokemon-showdown/data/mods/gen2stadium2/scripts.ts, chunk_3480e574205d5d0f, where damage calculation logic checks move identity, immunity, OHKO moves, damage callbacks, fixed damage, and level-based damage. That is not just a table. That is data plus executable behavior in a modded simulation context.

FireRed also has executable behavior, but the split is different. Battle effects are not usually attached as JavaScript callbacks inside move records. They are represented through constants, effect ids, battle scripts, and C functions that interpret battle state. Again, pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, is a useful anchor because its include list puts battle scripts, constants, battle controllers, AI script commands, random, weather, items, abilities, and Pokemon data in the same translation-unit neighborhood. The behavior emerges from that compiled neighborhood.

So if I ask, “Where does Flamethrower burn the target?” a Showdown-oriented answer might inspect the move record’s secondary effect and then follow simulator handling. A FireRed-oriented answer must identify the move effect or secondary-effect representation, then trace into battle script or utility logic, then into globals representing battlers, status, random chance, messages, animation, and controller output. The player-visible result is similar. The architectural path is not.

Let’s pause for a check for understanding. Imagine I give you two source paths: pokemon-showdown/data/moves.ts and pokefirered/src/battle_util.c. Which one is more likely to be the facade boundary? Neither, strictly. moves.ts is a data source. battle_util.c is an engine implementation file. The facade boundary in Showdown is the Dex API described in pokemon-showdown/sim/DEX.md. FireRed does not have an equivalent universal facade; it has module contracts and engine entry points. That distinction is the core of today’s lecture.

Now, we should also address learnsets, because week 22 includes them, and because they are a trap if you treat them as battle data. Showdown learnsets are a secondary modeling reference. The packet names pokemon-showdown/data/mods/gen9dlc1/learnsets.ts as a high-signal modern learnset file, but also warns us that it is not FireRed behavior. Learnsets tell us how a species may obtain moves under a rules context. They are legality and construction data. They are not the same thing as the battle engine deciding what a move does after it is selected.

In FireRed, learnability exists through level-up moves, TMs, tutors, eggs, and species evolution data, but once a Pokemon enters battle with a move in its move slots, the battle engine mainly cares that the party data says the move is there and that the move can be executed under current battle rules. In Showdown, legality can remain very close to the Dex and team validation pipeline. That is why our next lecture, “Legality Is a Filter Over Data,” follows naturally from today. Today we are asking, “How do I look up the data?” Next time we ask, “After I can look it up, who is allowed to use it?”

Let me tie this to the course plan. Weeks 1 through 21 built FireRed as a runtime architecture: startup, callbacks, tasks, maps, scripts, creature data, battle, inventory, UI, save, and link. Week 20 already introduced Showdown as a secondary comparison for battle data hooks and deterministic testing. Now weeks 22 through 24 are not replacing the primary source. They are a verification and comparison module. We use Showdown to sharpen our vocabulary around data facades, mods, filtering, and tests. Then we bring those words back to FireRed and say, “Where is the equivalent responsibility located in a compiled GBA RPG?”

And because your recent homework and quizzes already checked whether you can identify FireRed files, structs, functions, constants, data tables, and state variables, I am going to expect more precision now. Do not write, “FireRed uses tables while Showdown uses objects,” and stop. That is a beginner comparison. Write, “Showdown’s Dex exposes generation-contextual lookup APIs for moves, species, abilities, and items, while FireRed consumes compiled ids and tables through battle structs, globals, callbacks, tasks, and battle scripts.” That sentence has architecture in it.

One more concrete trace before we break this first segment. Consider an item used in battle. In Showdown, item data can be fetched through the Dex items API in the same family as moves, species, and abilities. In FireRed, an item id participates in bag state, menu code, item effect code, battle item restrictions, script contexts, and sometimes save-backed inventory state. We already covered the save machinery, so I will not reopen flash sectors today, but notice how prior knowledge now becomes a supporting beam. The item’s existence as a data record is not enough. Its availability depends on inventory state; its use depends on callback and UI flow; its effect depends on concrete engine functions; its persistence depends on save-owned structures.

That is the recurring course move: never stop at the table. The table is the beginning of the trace, not the trace itself.

So, as we continue, keep three questions in front of you. First, what is the lookup context? In Showdown, that usually means a Dex or Dex.mod context. In FireRed, that usually means the compiled game plus the currently active engine state. Second, what is the filtering boundary? In Showdown, nonstandard and legality filters are explicit concerns, grounded today by pokemon-showdown/sim/NONSTANDARD.md, chunk_800f1eafbea0ed7c. In FireRed, filtering often appears through map access, scripts, flags, inventory, species availability, and battle restrictions. Third, what consumes the result? A Showdown lookup result may be consumed by a simulator, teambuilder, validator, or test. A FireRed table entry is consumed by fixed C code, globals, battle scripts, callbacks, tasks, and UI routines.

All right, hold those questions. In the next stretch, we are going to walk through the lookup APIs one by one, moves first, then species, then abilities and items, and each time we will force ourselves to name the closest FireRed equivalent and the place where the analogy breaks.

So, moves first. Imagine I type, in a Showdown-side lookup script, something like Dex.mod of gen3, then dex.moves.get of “Flamethrower.” The important thing is not just that I get a move object. The important thing is that I get a move object through a facade that knows which generation context I asked for. That is the point of pokemon-showdown/sim/DEX.md, chunk_922688d7428150d1: the Dex is not merely a pile of records; it is the lookup surface that normalizes names, resolves IDs, and gives simulator-facing data.

Now compare that to FireRed. In FireRed, “Flamethrower” is not looked up by a flexible string API during normal gameplay. The move has a numeric constant, and runtime code walks from that constant into compiled data. When battle code needs move properties, it is not saying, “Please search the Dex facade for this ID in this generation mod.” It already has a move number in memory. That number came from party data, an enemy trainer party record, a wild encounter decision, a script, or a battle setup path. Then battle functions use constants and data tables to interpret it.

Let me put that on the board as two paths. On the left: Showdown, string or ID, Dex facade, mod-aware move record, simulator consumer. On the right: FireRed, numeric move ID, compiled table, battle globals and structs, battle script or controller consumer. Same conceptual goal, very different runtime shape.

This is where students often flatten the comparison too much. They say, “Showdown has move data and FireRed has move data.” True, but too weak. At this level, you should ask, “Who is allowed to ask the question, and in what language?” Showdown allows a tool, simulator, test, or validator to ask by name-like identifiers. FireRed mostly expects the game engine to already be carrying compact numeric state. That is a consequence of platform, toolchain, memory model, and the fact that FireRed is a shipped GBA executable rather than a server-side battle simulator and database library.

For a concrete example, take a move with secondary behavior. Showdown’s pokemon-showdown/data/moves.ts, chunk_012eada95ff7aa5f, is useful here because it reminds us that a move record may include not only base power and type, but secondary move data: chances, effects, and flags that the simulator can interpret. In Showdown, the data object itself can be rich enough that a test or battle engine reads a structured property and applies it in a fairly direct way. In FireRed, the equivalent behavior is often distributed. Some information lives in move data tables, some in constants, some in battle scripts, and some in C functions that know how to interpret move effects.

Now, check your understanding here. If I ask, “Where is the burn chance for a damaging Fire move?” I do not want the answer, “In the Dex.” That is a Showdown-shaped answer. For FireRed, I want you to ask, “Is it in the move’s effect code? Is it in a secondary effect table? Is it handled by battle script logic? Which global battle state is updated when it succeeds?” The architecture question is not merely where the value is stored. It is how the value becomes behavior on screen.

Let’s connect that to a FireRed source anchor. The research packet points us to pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, and even the include list in that chunk is revealing. It pulls in battle headers, battle scripts, battle messages, controllers, AI script commands, move constants, item constants, weather constants, ability constants, Pokémon constants, hold effects, and battle move effects. That include cluster tells you something architectural. Battle behavior in FireRed is not a neat single lookup object. It is a crossing point where many table-driven systems and stateful systems meet.

So when Showdown says, “Dex moves API,” we should hear, “a clean access boundary around battle data.” When FireRed says, through its structure, “include constants/moves.h, constants/battle_move_effects.h, battle_scripts.h, battle_controllers.h,” we should hear, “compiled identifiers flowing through a large state machine.” That contrast is the heart of today’s lecture.

Now species. In Showdown, species lookup has the same basic facade feel. You ask the Dex for a species record. The source focus for today includes pokemon-showdown/sim/DEX.md, chunk_74ee605430e5596f, which covers moves, species, abilities, and items APIs. The point is that species, like moves, are accessed through a coherent lookup family. The caller does not need to know which raw file contained Bulbasaur’s stats or Charizard’s typing. The caller asks the Dex.

In FireRed, species are again primarily numeric constants. A party Pokémon stores species-related information in a compact structure. Wild encounter data yields a species ID. Trainer party records name species through constants. UI code later turns that into names, icons, cries, front sprites, stats, and Pokédex state. There is no universal “species object” that every subsystem shares in the Showdown sense. There are multiple tables and multiple consumers. Base stats are one table-shaped concern. Evolution is another. Learnsets are another. Graphics are another. Pokédex text is another. Availability is not just data; it is map placement, scripts, flags, trades, gifts, and version rules.

Let’s pause on that word availability, because it is one of the bridges into Wednesday’s lecture on legality as a filter over data. Showdown has to model “exists in data” separately from “is legal in this format.” That is exactly why pokemon-showdown/sim/NONSTANDARD.md, chunk_800f1eafbea0ed7c, matters for this week. All data requires filtering. A species can exist in some broad data universe and still be filtered out by generation, format, event legality, or nonstandard status. FireRed has the same conceptual issue, but it is not presented as a single validator layer. Mew may exist as a species constant and may have data, but that does not mean ordinary map progression will hand it to the player. The boundary is enforced by content scripting, distribution assumptions, encounter tables, trade scripts, and sometimes by absence from ordinary gameplay paths.

That is a sophisticated distinction, so let me say it a second way. Showdown often asks, “May this requested object be used under these rules?” FireRed often asks, by its construction, “Can the player reach a state where this object is obtained?” Those are related questions, but not identical. A simulator and teambuilder must reject illegal input. A cartridge RPG usually prevents illegal state through progression structure, though as we know from save editing and link behavior, state can still be manipulated outside the ordinary path. We are not re-teaching save sectors today; use our save block work as prior foundation. The point is that FireRed’s legality boundary is distributed through the game’s state machines.

Now, abilities. Here the comparison gets especially interesting because FireRed is a generation-three game with abilities, but Showdown’s ability data carries modern simulator metadata. The packet gives us pokemon-showdown/data/abilities.ts, chunk_da22cf969179258c, where ability ratings are documented. Those ratings are not FireRed cartridge behavior. They are simulator and tooling metadata, useful for teambuilding evaluation and competitive context. If you treat that as equivalent to FireRed’s ability implementation, you will misread the architecture.

In FireRed, an ability is a compact identifier attached to a species possibility and ultimately to an individual Pokémon. Battle code checks abilities at specific points. Intimidate on switch-in, Levitate during immunity checks, Overgrow during damage adjustment, and so on. The engine does not need a general-purpose rating field. It needs fast conditional behavior at known battle phases.

So here is the board cue: I am writing “semantic data” under Showdown and “phase-triggered behavior” under FireRed. Showdown ability records can include descriptive and competitive metadata in a broad data layer. FireRed ability behavior appears when battle code reaches the phase where that ability matters. The same named concept, “ability,” is therefore shaped by two different consumers.

And this is why source boundaries matter. pokemon-showdown/data/abilities.ts, chunk_da22cf969179258c, can support a claim about Showdown’s ability metadata and ratings. It should not be used to claim that FireRed has an equivalent rating table. For FireRed, the better architectural support is the battle code’s dependency on constants and battle-state machinery, such as the cluster visible in pokefirered/src/battle_util.c, chunk_9335e5727aa0657d. Evidence discipline matters. Advanced architecture work is partly knowing which source proves which kind of claim.

Let me ask a check question. Suppose a student says, “Abilities are easier in Showdown because they are just data.” What is wrong with that? The answer is that Showdown abilities are not just inert data. They are data plus event hooks plus simulator interpretation. The lookup API gives access to a record, but the battle engine still has to consume it at the correct event. Conversely, FireRed abilities are not “hardcoded only.” They use identifiers, constants, tables, and shared battle utilities. So the correct contrast is not data versus code. It is facade-mediated structured data and hooks versus compiled identifiers interpreted by tightly coupled engine phases.

Now items. Items are a useful third case because they live across more subsystems. In Showdown, the item lookup API gives battle-relevant item data to the simulator. The DEX.md API chunk, pokemon-showdown/sim/DEX.md, chunk_74ee605430e5596f, groups item lookup with moves, species, and abilities. That grouping is telling. From the simulator’s perspective, these are all battle-relevant named resources accessed through the Dex.

In FireRed, an item is not only a battle resource. It is bag pocket data, shop inventory, field use behavior, script reward, hold item, mail or key item behavior, UI text, icon, and sometimes battle modifier. A Potion and a Choice Band are not just different records with different properties; they enter different flows. The Potion can be selected from a bag UI, target a party member, call healing logic, update party data, play feedback, and return to a menu or overworld callback. A held battle item may be checked inside battle phases. A key item may call field-use code or script logic. So a single item ID fans out through more engine surfaces.

This is why the FireRed architecture course spent so much time earlier on callbacks, tasks, scripts, and globals. It was not background trivia. When you trace item behavior, those are the roads the data travels on. A bag menu is not just a table lookup. It is a UI state machine running through callbacks and tasks. Use the earlier AgbMain and SetMainCallback2 material, supported in the packet by pokefirered/src/main.c, chunk_b35676322b169f85, and pokefirered/src/main.c, chunk_6cfd90f6d0136799, as the shell around this. Use the task system material, pokefirered/src/task.c, chunk_cb0bb91a147bfb59 for CreateTask and chunk_3ffebc0341225936 for RunTasks, as the frame-by-frame dispatch model. I am not re-teaching those mechanisms now; I am showing you why they remain necessary when we compare a Dex lookup library to a cartridge RPG.

Let’s walk one concrete trace. A player selects a healing item in FireRed. At the data level, there is an item ID. At the UI level, the bag system displays a name and pocket organization. At the selection level, code decides whether the item can be used now, whether it needs a party target, and what effect routine should run. At the party level, the chosen Pokémon’s HP or status fields may change. At the persistence level, later, that changed party state belongs to the save-owned world we already studied. At the player-visible level, text boxes and sound effects confirm the result. A Showdown Dex item lookup, by contrast, may return a battle item record for Leftovers or Choice Band and then the simulator applies it at residual or move-choice phases. It is not managing an overworld bag UI on GBA hardware.

Now, is one architecture better? That is the wrong question. The right question is: better for what constraints? Showdown is better suited to programmatic lookup, generation comparison, format validation, and deterministic battle tests. FireRed is better understood as a complete game runtime where data tables are compiled into a constrained executable and behavior is distributed across systems. Our course is not trying to replace FireRed with Showdown. Homework and quiz work around week 20 already checked that you can use Showdown as a secondary comparison for battle data hooks, Dex mods, simulator turns, and regression testing without replacing FireRed as the main source. Week 22 now asks you to be more precise.

Let’s bring generation mods into the room. pokemon-showdown/sim/DEX.md, chunk_5fbe60392b5eedf9, is the source focus for Dex.mod generation-specific data. A modded Dex is a powerful idea: instead of having one universal record for a move or species, you can ask for the data as it exists in a particular generation or ruleset. Gen 3 Thunderbolt is not the same architectural object as Gen 9 Thunderbolt if the surrounding mechanics differ, even if many fields appear similar. The mod context is part of the lookup.

FireRed does not have a runtime Dex.mod of gen3 because FireRed itself is already a specific compiled generation-three product. If you want to change mechanics, you change source, tables, scripts, assets, and rebuild. There may be conditional behavior for link, battle type, map, or flags, but there is not a general-purpose “give me the Gen 5 version of this move” facade. So when your lab asks you to write a Showdown-side lookup script that loads a generation mod, prints selected move and species records, filters nonstandard data, and documents how this differs from FireRed static tables, the key learning is not the script alone. The key learning is the architectural gap revealed by the script.

Board cue again: I am drawing three boxes. First box, “lookup context.” Second box, “filter context.” Third box, “consumer context.” For Showdown, lookup context is Dex.mod; filter context includes nonstandard and format legality; consumer context may be simulator, validator, teambuilder, or test. For FireRed, lookup context is compiled game plus current runtime state; filter context is progression, scripts, flags, maps, inventory, encounters, and battle constraints; consumer context is C engine code, callbacks, tasks, scripts, battle controllers, and UI.

Now, learnsets. We need to be careful with learnsets because they are very tempting to overuse. The packet names pokemon-showdown/data/mods/gen9dlc1/learnsets.ts as a high-signal modern learnset file, but it also explicitly says secondary source-use note: not FireRed behavior. So if we inspect a modern learnset file, we are not learning what FireRed does byte for byte. We are learning how a modern simulator organizes “which species can learn which moves under which source conditions.” That can sharpen our thinking about FireRed, but it cannot substitute for FireRed source.

For example, in Showdown, learnsets are part of legality modeling. They help answer, “Can this species have this move in this generation or format?” In FireRed, learnability is split across level-up data, TM and HM compatibility, move tutors, egg moves, event distributions, and scripted gifts or trades. The cartridge does not need to validate arbitrary imported team text in the way Showdown does. It usually controls acquisition paths. Again, same domain, different boundary.

Let me test that. If I hand you a Showdown learnset entry and ask, “Does this prove that FireRed Bulbasaur can learn this move this way?” what should you say? You should say, “No, not by itself.” It may be a useful comparison, especially if the mod is generation-specific, but FireRed authority must come from FireRed tables and routines. Conversely, if I ask, “Can a Showdown learnset help me design a verification script for a clone?” the answer is yes, if you label it as secondary and account for generation differences. That is exactly the kind of disciplined comparison expected this week.

Now let’s tie back to battle setup. The packet includes pokefirered/src/battle_setup.c, chunk_494d132a59422c85, as a relevant source module. Even from the name and placement in the course packet, you should hear the architectural role: before a move can be used, before a species can be displayed in battle, before an ability can trigger, the battle has to be set up from overworld or trainer context into battle state. That transition is one of FireRed’s key bridges from map runtime to battle runtime. Showdown does not have an overworld-to-battle transition in the same sense. It constructs battles from team data and format rules. FireRed constructs battles from map encounters, trainer events, scripts, flags, party state, and callback transitions.

So if we trace a wild Pidgey, FireRed starts with map and encounter context, produces a species and level, initializes a battle opponent, enters battle setup, installs battle callbacks, and eventually reaches battle commands where move IDs are interpreted. Showdown starts with a battle format, team data, species lookups, move lookups, ability and item lookups, legality assumptions or validation, and then a simulator turn loop. Both reach “a Pokémon uses a move,” but the path into that sentence is totally different.

This is also where our earlier work on link state quietly remains relevant. I am not going back through RFU mode constants or VBlank timers; those were covered in the link manager lectures. But remember the broader principle: FireRed often gates behavior through active mode, callback state, and communication state. A linked battle is not just a different Dex lookup. It is a different runtime situation with different controllers and synchronization requirements. Showdown may have multiplayer clients, but the simulator’s Dex lookup abstraction remains server-side and data-oriented in a way the GBA link runtime is not.

Now, one more advanced point before we move to the next stretch. In Showdown, because Dex lookup is an explicit API, it becomes very easy to write tests around data access. You can ask, “Does this move exist in this mod? Does this species have this property? Is this item nonstandard?” The packet’s broader guidance points us toward pokemon-showdown/test as a recurring course module for assertions and battle verification. FireRed testing is different. You often need to test by building, instrumenting, scripting emulator behavior, or isolating C functions and tables. This is why Showdown is attractive as a comparison and verification aid. It gives us fast questions to ask of a modern data model. But fast does not mean authoritative for cartridge behavior.

So, as we continue, keep the discipline tight. When I say “Dex lookup,” I mean Showdown’s facade over battle-relevant data, grounded in pokemon-showdown/sim/DEX.md chunks like chunk_922688d7428150d1, chunk_5fbe60392b5eedf9, and chunk_74ee605430e5596f. When I say “FireRed table lookup,” I mean numeric identifiers flowing through compiled data, globals, callbacks, tasks, scripts, structs, and concrete source functions, with battle integration visible in places like pokefirered/src/battle_util.c, chunk_9335e5727aa0657d. When I say “filter,” I mean explicit nonstandard and legality filters in Showdown, grounded by pokemon-showdown/sim/NONSTANDARD.md, chunk_800f1eafbea0ed7c, and distributed progression and state constraints in FireRed.

All right, take a breath. The next thing we are going to do is more mechanical. We will trace a single requested lookup across the four Showdown categories, move, species, ability, item, and for each one we will write the FireRed counterpart as a path from record to visible behavior. This is where the comparison stops being vocabulary and starts becoming architecture.

So on the board, I am going to write four requested lookups in the Showdown style first: Dex moves get Thunderbolt, Dex species get Pikachu, Dex abilities get Static, Dex items get Oran Berry. I am saying those in speech rather than writing JavaScript syntax because the syntax is not the point yet. The point is that each lookup asks a single facade, the Dex, for a normalized battle data object. That facade is exactly the architectural role described in pokemon-showdown/sim/DEX.md, especially chunk_922688d7428150d1 for Dex purpose and move lookup, chunk_74ee605430e5596f for the moves, species, abilities, and items APIs, and chunk_5fbe60392b5eedf9 for generation-specific mods.

Now let’s compare that with FireRed. If I ask FireRed, “What is Thunderbolt?” FireRed does not normally answer through one object-shaped facade. The move is a numeric constant, and that constant indexes compiled data. Then battle code interprets that data through engine state. If I ask, “What is Pikachu?” again, I am not handed a rich species object in the Showdown sense. I am usually moving through a species number, a base stats table, party structs, Pokémon substruct fields, battle Pokémon structs, and whatever current callback or script made the lookup necessary. That is why I keep saying FireRed is not less data-driven. It is data-driven in a different physical shape.

Let’s take Thunderbolt first, because moves make the contrast sharp. In Showdown, a move lookup gives you a record with many properties that are already close to battle semantics: name, type, category, base power, accuracy, flags, secondary effects, generation availability, and so on. The packet points us to pokemon-showdown/data/moves.ts, chunk_012eada95ff7aa5f, as a high-signal example for secondary move data. That is not just cosmetic metadata. The secondary-effect fields are modeling hooks. They let the simulator say, “This move has a chance to paralyze,” or “This move has a recoil interaction,” or “This move makes contact,” without requiring every consumer to manually reconstruct that meaning from unrelated arrays.

In FireRed, by contrast, the question “What happens when Thunderbolt is used?” is distributed. The move’s base data gives the engine part of the answer. Constants identify the move and its effect. Battle globals hold the current attacker, target, selected move, hit results, status flags, side conditions, abilities, held items, and so forth. Then source functions read those globals and branch through battle scripts and utility functions. The high-signal FireRed source cited in the packet, pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, is useful here because its include list alone reveals the density of cross-module battle dependencies: battle headers, battle scripts, battle messages, constants for moves, items, weather, abilities, hold effects, and battle move effects. That file is not “the Thunderbolt file.” That is the point. Thunderbolt behavior emerges from a web of constants, tables, runtime state, and battle script execution.

Pause on that distinction. Showdown’s Dex record tends to make the data object more semantically expressive at lookup time. FireRed tends to keep lookup smaller and lets engine code interpret the record inside a broader state machine. Neither approach is automatically superior. Showdown is optimized for simulator extensibility, validation, mods, and testable battle behavior across many generations. FireRed is optimized for a fixed cartridge-era engine, memory constraints, compiled assets, and predictable runtime dispatch on the GBA.

Now, check yourself here. If I ask, “Where is the paralysis chance of Thunderbolt?” what answer would you give? In Showdown, you are thinking, “Look at the move record and its secondary data,” with pokemon-showdown/data/moves.ts, chunk_012eada95ff7aa5f, as the supporting source packet reference. In FireRed, you should resist giving one tidy answer. You trace the move constant to move data, the move effect constant to battle effect handling, the current battler state through globals, and then the battle script or utility function that actually applies status if conditions allow. That is the correct advanced answer: not “it is in the table,” but “the table participates in a runtime path.”

Now species. Put Pikachu on the board. In Showdown, Dex species get Pikachu is a lookup into normalized species data. The species record can expose types, base stats, abilities, formes, generation behavior, tags such as nonstandard status, and other simulator-facing fields. And because Showdown has Dex.mod, the same species name can be interpreted through a generation-specific lens. That is what pokemon-showdown/sim/DEX.md, chunk_5fbe60392b5eedf9, gives us: not merely “there are mods,” but that generation-specific data selection is a first-class part of lookup. If I say Dex.mod gen3 and then ask for Pikachu, I am asking for Pikachu as understood under a particular rules and data environment.

FireRed does not need a runtime mod facade because it is not trying to be a multi-generation battle simulator. It is already one concrete game. So Pikachu’s species identity flows through constants and compiled species data, and the runtime Pokémon instance stores species plus individual properties: level, personality, experience, moves, IV-like data, EV-like data, status, held item, and so on. In battle, that party object is transformed or copied into battle-specific structures. Then battle functions operate on the battle representation, not merely on the species table. So if you ask, “What are Pikachu’s stats?” the full answer depends on species base stats, level, individual data, effort data, nature or personality-derived behavior where applicable in the engine, current stat stages in battle, status effects, held items, abilities, and side effects.

This is where advanced students sometimes overcorrect. They say, “Showdown has objects; FireRed has tables.” True, but incomplete. Showdown also has runtime Pokémon objects and battle state. FireRed also has structs. The real distinction is where semantic unification happens. Showdown centralizes much of the lookup-facing semantics in the Dex layer, and then the battle engine consumes those normalized records. FireRed spreads meaning across compiled data and engine-specific consumers. When you trace FireRed, you must identify not only the table but also the callback, task, script, or battle routine that gives that table a use.

Let me connect this to our earlier weeks without reteaching them. When we studied AgbMain in pokefirered/src/main.c, chunk_b35676322b169f85, and SetMainCallback2 in pokefirered/src/main.c, chunk_6cfd90f6d0136799, we were establishing the runtime shell: the game advances because the main callback points at a mode of operation. When we studied CreateTask and RunTasks in pokefirered/src/task.c, chunks chunk_cb0bb91a147bfb59 and chunk_3ffebc0341225936, we were establishing the per-frame task scheduler. Today’s Dex comparison plugs into that same mental model. A data lookup becomes visible only when some callback, task, script, or battle loop asks for it and then uses it to update state, draw UI, play animation, or commit a battle result.

So, species example. Imagine a player opens the party menu and inspects Pikachu. The species number alone is not the visible behavior. The party menu callback has to run. UI tasks have to update. The Pokémon struct has to be read. Text and graphics have to be loaded. Stats may be calculated or displayed. That is FireRed’s path. Now imagine a Showdown script prints Dex species get Pikachu. The facade can return a record suitable for inspection immediately. That difference matters in your lab this week. When you write the Showdown-side lookup script, do not claim you have reproduced FireRed’s runtime. You have reproduced a particular kind of data access.

Now ability lookup. Use Static. In Showdown, Dex abilities get Static returns an ability record. The ability data may include rating information, descriptions, event handlers, or other simulator-facing metadata depending on the file and generation. The packet gives pokemon-showdown/data/abilities.ts, chunk_da22cf969179258c, where ability ratings are explained. Ratings are not FireRed cartridge behavior. They are Showdown’s competitive and simulator ecosystem metadata. That is a beautiful example of the Dex facade carrying more than raw game data. It may carry evaluation-oriented information that is useful for team analysis, AI hints, validation, or user interfaces, but not equivalent to a FireRed ROM table.

In FireRed, Static as an ability is a constant and a behavior integrated into battle contact handling or encounter-related logic depending on the ability. The table can say a species may have Static. But Static’s effect is not fully “in” the species table. The ability constant must be read at the relevant moment. Did a contact move occur? Is the defender’s ability active? Is the attacker already statused? Are there immunities or safeguards? Is this an overworld encounter modification rather than a battle event? The architecture is event-shaped. The data identifies the ability; the engine decides when that identity matters.

Here is the conceptual checkpoint. If a junior engineer says, “I found Pikachu’s ability in the base stats table, so I found Static’s implementation,” what do we say? We say, “You found one reference to the ability, not the behavior.” The behavior is wherever the runtime checks that ability constant under concrete conditions. That is the same reasoning you used in week 18 and week 21 assessments, where you had to identify not just files and structs but the functions, constants, data tables, and state variables that implement a system. At this point in the course, I expect that answer to be automatic.

Now item lookup. Let’s use Oran Berry because it is simple enough to reason about and still shows the distinction. In Showdown, Dex items get Oran Berry returns an item record under the current Dex or generation mod. In a modern Showdown environment, item records may include event handlers or data that supports battle-time activation. Under a generation mod, the item’s behavior and availability may change. Again, pokemon-showdown/sim/DEX.md, chunk_74ee605430e5596f, is the API anchor, and chunk_5fbe60392b5eedf9 is the generation-mod anchor.

In FireRed, an item is typically an item constant indexing item data, bag pockets, usage callbacks, hold effects, battle interactions, and script-facing consequences. Oran Berry as an inventory item, Oran Berry as a held item, and Oran Berry as a battle-triggered healing effect are not the same architectural site. They share an item identity, but the path differs. In the bag, the player navigates UI and selects an item. In the field, a script or menu function may determine whether the item is usable. In battle, held item logic may trigger when HP crosses a threshold. That means “item lookup” in FireRed is a routing problem. Which subsystem asked about the item? Inventory? Battle? Script? Save restoration? Link battle serialization? You already know the save and link foundations from prior weeks, so I am only naming them here as constraints, not reopening those lectures.

Now I want to put a small table on the board, but I’ll describe it aloud. The first column says requested concept. The rows are move, species, ability, item. The second column says Showdown lookup. Every row begins with the Dex facade. The third column says FireRed path. Every row begins with a numeric identifier or struct field and then moves into compiled tables plus engine consumers. The fourth column says visible behavior. For move, visible behavior is damage, animation, status, messages. For species, stats, sprites, cries, evolution, encounters, party display. For ability, triggered battle or overworld effects. For item, bag behavior, held effects, scripts, battle use.

That fourth column is the one students forget. Architecture is not a scavenger hunt for data definitions. Architecture is an explanation of how a record becomes behavior.

Let’s make it concrete with a mini-trace. Suppose Pikachu uses Thunderbolt against Squirtle. In a Showdown-side lookup script, you might load a generation mod, retrieve the species records for Pikachu and Squirtle, retrieve the Thunderbolt move record, retrieve Static if you want Pikachu’s ability, retrieve an item if held, and then filter out nonstandard data before printing. The nonstandard filter matters because Showdown’s data universe intentionally includes things that may not be legal in a given format. That is the point of pokemon-showdown/sim/NONSTANDARD.md, chunk_800f1eafbea0ed7c: all data requires filtering. Existence in the data set is not the same as legality in a battle format.

In FireRed, by contrast, if Pikachu uses Thunderbolt against Squirtle in an ordinary battle, the path starts earlier. How did the battle start? Wild encounter? Trainer script? Link battle? We do not need to re-teach those systems today, but the entry path sets battle type, parties, scripts, and callbacks. Once in battle, the selected move is stored in battle state. The attacker and target are battler indexes. The move constant indexes move data. The damage calculation reads species-derived stats from battle structs, types, current stat stages, random factors, STAB, type effectiveness, abilities, held items, and field effects. Then scripts and controllers produce visible messages, HP bar movement, animation, sound, and post-hit effects.

Notice the asymmetry. Showdown lookup can be a useful preflight inspection before simulation. FireRed lookup is usually embedded inside simulation. That is why your lab asks you to document how the Showdown script differs from FireRed static tables. The point is not to write a better FireRed with TypeScript. The point is to use Showdown to see the advantages of a facade and then return to FireRed with sharper eyes.

Now, let’s check for understanding in a more demanding way. If I give you a Showdown move object and ask, “Is this legal in Gen 3 OU?” should you answer from the move object alone? No. You need the format rules, generation mod data, nonstandard status, learnsets, and possibly event or transfer constraints. Learnsets are especially important as a secondary modeling reference this week. The packet names pokemon-showdown/data/mods/gen9dlc1/learnsets.ts as a high-signal modern learnset file, but it also warns us that this is not FireRed behavior. That means we can study the modeling shape: species-to-move acquisition data as a separate source of truth. We cannot pretend a modern Gen 9 DLC learnset file explains FireRed’s exact move acquisition system.

In FireRed, learnability is distributed across level-up learnsets, TM/HM compatibility, tutor data, egg moves, event gifts, and scripts. A Pokémon knowing Thunderbolt is not proven merely by Thunderbolt existing. It has to enter the Pokémon’s moveset through some legal game path, or through debug, trade, event, or external manipulation. FireRed itself may enforce some boundaries at acquisition time, while other legality questions are outside the runtime because the cartridge does not continuously validate every possible historical origin the way a simulator validator might. This is the bridge to our next lecture, “Legality Is a Filter Over Data.” Today we are still mostly looking at lookup. Next time, the filter becomes the center.

Let’s revisit nonstandard data because it is easy to underestimate. Showdown’s Dex can know about a move or species that is not legal in a particular format. That is not a bug. It is a consequence of unifying many generations, side formats, past mechanics, special cases, and modded environments under one data system. The NONSTANDARD document, pokemon-showdown/sim/NONSTANDARD.md, chunk_800f1eafbea0ed7c, is our anchor for the rule that data existence is broader than usable legality. FireRed’s equivalent is not a single nonstandard flag. FireRed’s equivalent is a set of gates: script flags, story progress, item possession, map access, trade availability, encounter tables, party state, and battle mode. Some gates are explicit checks. Some are just consequences of the player not being able to reach a map or obtain an item yet. Some are persisted in save blocks, and we use that as a prior foundation from the save lectures without re-opening sector validation today.

Here is a clean way to say it. Showdown often asks, “Given this broad data universe, which records are allowed under this format?” FireRed often asks, “Given this current game state, which interaction path can the player actually take?” Both are filters over data, but the filter lives in different architectural layers.

Now I want to slow down and give you a diagnostic pattern you can use in the homework. When you compare a Showdown lookup to FireRed, ask four questions. First, what identifier names the thing? In Showdown, often a string ID normalized by the Dex. In FireRed, often a numeric constant or enum-like define. Second, where is the base data? In Showdown, TypeScript data files under pokemon-showdown/data and possibly data/mods. In FireRed, compiled C data, constants, headers, and binary assets. Third, who consumes it? In Showdown, Dex clients, the battle engine, validator, team builder, tests. In FireRed, callbacks, tasks, scripts, battle functions, UI functions, save and link systems when relevant. Fourth, what makes it visible? In Showdown, simulator output, logs, validation messages, battle state. In FireRed, rendered sprites, text boxes, animations, HP bars, map changes, party menu changes, saved state.

That pattern should sound familiar because it is the week 1 course thesis growing up. Back then we decomposed the creature RPG into runtime shell, overworld maps, event scripting, creature data, battle, inventory, UI, save, and link systems. In week 22, we are not changing the decomposition. We are verifying it against a second architecture. Showdown gives us a different answer to “Where should battle data live?” and that difference makes FireRed’s choices more visible.

Let me give one more example before we transition. Suppose your script loads a generation mod and prints Flamethrower, Charizard, Blaze, and Charcoal. Again, Showdown can hand you records for move, species, ability, and item. You can inspect types, base power, abilities, item effects, and nonstandard flags. But in FireRed, Charizard using Flamethrower with Blaze active and Charcoal held is a runtime condition. The species table does not decide that Blaze is active. The item table does not decide that Charcoal modifies this exact move in this exact moment. The battle engine reads current HP, ability, held item, move type, attacker state, target state, and field conditions. The behavior appears only when all of those pieces line up during battle execution.

So if I were grading your trace, I would not give full credit for “Charizard has Blaze; Flamethrower is Fire-type; Charcoal boosts Fire moves.” That is data description. The architectural answer is: the selected move constant flows into battle move data; the attacker battle struct supplies species-derived stats, current HP, ability, and item; battle utility and script logic consult constants for moves, items, abilities, hold effects, and battle move effects, with pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, showing exactly that kind of cross-module dependency; then the battle controller and message systems make the result visible. That is the level of trace I want.

And to be clear, I am not asking you to memorize every function name in FireRed’s battle engine. I am asking you to stop at every boundary and name the kind of boundary it is. Data record to struct. Struct to global. Global to callback. Callback to task or script. Script to engine function. Engine function to visible behavior. That boundary naming is what lets you debug unfamiliar subsystems later.

All right, quick comprehension check. I’ll say a statement, and you decide whether it is architecture-level or merely data-level. “Thunderbolt has 95 base power in older generations.” Data-level. Useful, but not enough. “The selected move identifier is read from battle state, used to index move data, then interpreted by battle logic that checks type, target, damage modifiers, secondary effects, messages, and animation.” Architecture-level. “Pikachu exists in the Dex.” Data-level. “A Pikachu in the player party is a saved and runtime creature instance whose species field connects to base data, whose current fields connect to party UI and battle structs, and whose behavior becomes visible through callbacks and tasks.” Architecture-level. Good. That is the distinction.

Now, as we move into the next segment, keep the four lookups on the board: move, species, ability, item. We have treated them as parallel categories, but in real battle they are not parallel. They compose. A move’s meaning depends on the species using it, the ability currently active, the item held, the target’s properties, and the format or game state that allowed the situation to exist. Showdown’s Dex facade makes each category easy to ask for independently, and then the simulator composes them under rules. FireRed’s tables make each category compact and static, and then the cartridge runtime composes them through battle state, callbacks, tasks, and scripts. That composition is where the architecture lives, and that is where we are going next.

So, let’s make that composition concrete. Imagine the player selects Thunder Wave. In a Showdown-side lookup script, you might ask the Dex for the move record, then ask the Dex for the user’s species, the user’s ability, and the held item. The documentation packet points us directly to that pattern in pokemon-showdown/sim/DEX.md chunk_74ee605430e5596f, where moves, species, abilities, and items are presented as API lookup categories. That is the facade idea. You are not opening a C array and remembering which integer constant means paralysis. You are asking a named service for a normalized record.

Now, board cue here: I’m writing “lookup is not legality.” Put a box around that. This is the mistake advanced students often make when they first compare Showdown to FireRed. If a move can be looked up, that does not mean the move is permitted in a format. If a species record exists, that does not mean it should appear in the current ruleset. Showdown’s NONSTANDARD document, pokemon-showdown/sim/NONSTANDARD.md chunk_800f1eafbea0ed7c, is important for precisely this reason: all data requires filtering. Existence is not permission. Availability is a layer over data.

FireRed has a different shape, but the architectural principle is recognizable. FireRed’s static tables may contain a species, a move, an item, or an ability constant, but whether the player encounters that state depends on map scripts, event flags, trainer parties, item pockets, evolution rules, and battle setup. We are not going to reteach save ownership or sector validation here; those are prior foundations. Just remember that those systems preserve the world state that determines which scripts have run, which flags are set, and which creatures and items the player has. The tables are not the whole game. The tables are the vocabulary from which the runtime composes a game state.

Let’s stay with Thunder Wave, because it is familiar enough that we can use it without getting distracted by the move itself. In Showdown, a script can do something like, conceptually, dex.moves.get of Thunder Wave, dex.species.get of Pikachu, dex.abilities.get of Static, dex.items.get of Light Ball, and then it can print the records. The Dex documentation in pokemon-showdown/sim/DEX.md chunk_922688d7428150d1 is part of the source packet for this week because it frames the Dex as the battle data access layer, with move lookup as a central example. That is exactly what I want you to see: the simulator is not telling every call site to know where move data lives. It concentrates that knowledge behind the Dex.

FireRed, by contrast, asks you to trace the same conceptual question through constants and tables. Thunder Wave is represented by a move constant. The battle code includes move constants and battle move effect constants. The packet’s FireRed anchor here, pokefirered/src/battle_util.c chunk_9335e5727aa0657d, is valuable because even from the include surface you can see the architecture pulling together battle.h, battle_scripts.h, battle_message.h, battle_controllers.h, constants/moves.h, constants/items.h, constants/abilities.h, constants/pokemon.h, and constants/battle_move_effects.h. That include cluster tells you something architectural before you read a single branch: battle behavior is a composition site. It is where species identity, move identity, item identity, ability identity, battle scripts, messages, and controller behavior meet.

Pause there. Check for understanding. If I ask, “Where does Thunder Wave live?” the correct advanced answer is not just “in the move table.” That is the beginner answer. A better answer is, “Its base record lives in move data, its availability lives in learnsets or party construction or scripts, its in-battle behavior runs through battle state and script/control flow, and its visible effect is mediated by battle messages, animations, and controller callbacks.” That sentence is long because the architecture is layered.

Now, let’s compare what happens when generation-specific behavior enters the picture. Showdown has a formal mechanism for this: Dex.mod. The packet points us to pokemon-showdown/sim/DEX.md chunk_5fbe60392b5eedf9 for generation-specific data. Conceptually, you can ask for a Gen 3 Dex, a Gen 9 Dex, a DLC-modified Dex, or a custom mod’s Dex. That means the lookup facade is not only hiding where data lives; it is also selecting which universe of data you mean. That is a very modern simulator problem. The same species name, move name, or item name can have different meanings or availability across generations and formats.

FireRed does not have that same runtime abstraction. FireRed is already one concrete generation target, compiled for one cartridge. Its “mod,” if we may use that word carefully, is mostly decided at build time by the source tree, constants, generated assets, and compiled data tables. There is no ordinary gameplay path where FireRed says, “Load the Gen 4 definition of this move instead.” The cartridge does not need a multi-generation facade because the product boundary is fixed. If you hack the ROM or alter the decompilation and rebuild, you can change the data. But that is a toolchain operation, not the same kind of runtime Dex.mod lookup.

This distinction matters for your lab this week. When you write the Showdown-side lookup script, I want you to load a generation mod explicitly. Do not just ask the default Dex and call it done. Ask yourself, “Which data universe did I select?” Then print a selected move and species. Then filter nonstandard records. Then write down how that differs from FireRed. The answer should not be sentimental. It should be architectural. Showdown says, “Choose a Dex, ask it for records, then filter according to rules.” FireRed says, “Compile the target data into tables, enter battle through setup and callbacks, and let runtime state and scripts determine how those tables become behavior.”

Now, concrete example two. Let’s use a species rather than a move. Suppose we ask for Charizard. In Showdown, Charizard as a species record is retrieved through the species API, again within that group of lookup categories documented in pokemon-showdown/sim/DEX.md chunk_74ee605430e5596f. The record can include properties that the simulator needs: typing, base stats, abilities, forme information, and so on. But Showdown also has data that is not merely “the battle stat line.” Learnsets are a secondary modeling reference. The week packet names pokemon-showdown/data/mods/gen9dlc1/learnsets.ts as a high-signal modern learnset file, and we are using it carefully: not as FireRed behavior, not as evidence about the Game Boy Advance engine, but as evidence of how a modern simulator represents move availability as data adjacent to species and moves.

That phrase “secondary modeling reference” is worth repeating. Learnsets are not the move’s effect. They are not the battle engine. They answer a different question: how could this species know this move under this modeled ruleset? In FireRed, you have comparable categories, but they are not arranged behind the same Dex facade. You have species data, level-up learnsets, TM/HM compatibility, move tutor data, egg moves, party structures, and battle structures. When a Pokémon enters battle, the battle engine is not asking a legal-team validator, “Should this Charizard have Dragon Dance?” It is operating on the creature that exists in party data. Legality, encounter history, player action, and save state are upstream.

Let me slow down because this is a place where architecture and policy can get mixed together. A battle engine often assumes that its input state is already valid enough to simulate. That does not mean validation is unimportant. It means validation belongs to a different boundary. Showdown has to handle arbitrary teams submitted by users, so legality and format filtering are first-class concerns. FireRed usually generates and mutates party state through its own game systems, so impossible states are harder to reach in normal play. You can still create impossible states through debugging, corruption, link edge cases, or external tools, but that is not the normal player path. The architecture reflects the threat model.

Board cue: I’m drawing two pipelines. Left side, Showdown. “Raw data, mod selection, Dex lookup, format filter, team validation, battle simulation.” Right side, FireRed. “Compiled tables, save/world state, scripts and callbacks, party/bag globals, battle setup, battle engine.” These are not identical pipelines. They are comparable pipelines. And because they are comparable, they help us understand what each system is optimizing for.

Showdown optimizes for data reuse, multi-format simulation, and testability across rule variations. FireRed optimizes for a fixed commercial game running on constrained hardware, where table compactness, predictable control flow, and integration with the overworld matter a great deal. That is why we can use Showdown to sharpen our thinking, but we cannot replace FireRed with Showdown. This has been the rule since the course comparison module began, and it is especially important in weeks 22 through 24. Showdown is a reference for modeling and verification. FireRed remains the primary architecture source.

Now let’s bring in abilities and items, because moves and species are still too clean. The packet includes pokemon-showdown/data/abilities.ts chunk_da22cf969179258c, which begins with ability ratings. Ratings are a simulator data convenience. They help the software and tooling reason about how useful an ability is in battle contexts. FireRed does not need that same concept in its core battle tables. FireRed needs to know what the ability does, whether it is present, when it triggers, and how it changes state. A rating like “very useful” or “essential” is not a cartridge runtime necessity. It belongs to a data-rich ecosystem where teambuilders, AI heuristics, formats, and human-facing tools may benefit from metadata.

This is a good example of a broader architectural principle: not all data attached to a concept is gameplay state. Some data is simulation behavior. Some data is validation policy. Some data is UI support. Some data is editorial or analytical metadata. In Showdown, those categories can sit near each other because the project is a simulator and battle platform. In FireRed, many of those categories are absent, compiled elsewhere, or represented indirectly through UI text, scripts, constants, or hard-coded logic. Advanced architecture work means you do not flatten all of that into “the ability data.”

Let’s use an item example. Suppose a held item changes move power. In Showdown, the item record can be looked up through the item API, and the simulator can apply hooks during battle. In the packet, pokemon-showdown/data/mods/biomechmons/scripts.ts chunk_1434b1000eb1576c gives us an extreme modded example where item-like behavior can even involve looking up abilities and moves by string through the battle Dex. We are not using that file as normal cartridge design; we are using it to show how flexible the Showdown Dex-centered architecture can become in a mod. A mod script can treat battle data categories as fluid lookup targets because the Dex facade supports that style.

FireRed’s item model is more rigid. Items have IDs. Held effects are constants. Battle code checks held effects and item parameters in known places. Again, that rigidity is not a flaw; it is an optimization for the product. It makes sense when memory is constrained, when the ruleset is fixed, and when all data is shipped together. But it means the investigation technique changes. In Showdown, you ask, “Which Dex record and hook?” In FireRed, you ask, “Which constant, which table, which global battle struct field, which function or battle script consumes it, and which callback or controller makes the result visible?”

Check yourself here. If you are tracing Leftovers recovery in FireRed, and your notes stop at the item table, you have not traced behavior. You have found vocabulary. If your notes continue into battle utility functions, battle scripts, message buffers, health box updates, and the task or callback layer that animates the result, then you are doing the course method. Data table to global state to control flow to visible behavior. That method is the same method we used for maps, scripts, party data, bag state, battle turns, and link entry points. We are now applying it against a modern comparison source.

Let’s do one more board pass, because I want the lab implementation to be precise. On the board I’m writing four questions your script should answer. First, what generation or mod am I loading? Second, what records can I retrieve by name? Third, which retrieved records are nonstandard or filtered under my chosen policy? Fourth, what would the equivalent FireRed trace require instead of this lookup? Notice the fourth question is not asking you to write a FireRed parser this week. It is asking you to document the architectural delta. That documentation is part of the engineering work.

For example, your lab output might say: “In Showdown, I loaded a Gen 9 DLC mod and retrieved a move record by string ID. The move exists in the data layer, but my filtering step excludes records marked nonstandard. In FireRed, I would not perform a runtime string lookup through a generation Dex. I would follow the move constant through compiled data and battle code.” That is a strong answer. It distinguishes existence from permission, and it distinguishes lookup facade from static table composition.

Now, I want to connect this back to battle setup. The packet includes pokefirered/src/battle_setup.c chunk_494d132a59422c85 as a source module for battle entry. We do not need to unpack every function in that file right now, but conceptually, battle setup is the bridge from overworld conditions into battle state. That is where encounter type, trainer context, party participants, battle flags, and transition into the battle engine become relevant. Showdown typically begins from constructed teams and a format. FireRed begins from a running world: a grass encounter, a trainer event, a script, a map, a party, a bag, flags, and callbacks. We have covered overworld and scripting in earlier weeks, so today we only need the bridge: FireRed’s battle is not an isolated lookup exercise. It is entered from the runtime shell.

That is why I keep saying callbacks and tasks even in a Dex lecture. If this were only about data files, we could have done it in week two. But the course objective for today is to trace gameplay from data records through globals, callbacks, tasks, scripts, structs, and concrete functions. Showdown helps us name the data categories. FireRed forces us to follow the runtime consequences. A move selected in battle is not simply read; it is chosen through command input, stored in battle state, resolved through battle logic, expressed through scripts, shown through controllers, and eventually returned to the main game loop.

Let me ask a quick understanding question. Suppose Showdown’s Dex returns a move record for a move that does not exist in FireRed. Is that a contradiction? No. It is a selected data universe difference. Suppose FireRed has a move constant compiled into the ROM but no ordinary player path lets a given species learn it. Is that a contradiction? Also no. That is a legality or availability boundary. Suppose a battle engine receives a party creature with a strange move because of debugging or external manipulation. Is the battle engine necessarily responsible for proving the whole historical legality of that creature? Usually no. It may only be responsible for simulating the state it was given, unless the architecture explicitly places validation at that boundary.

Those distinctions are what separate an advanced architecture reading from a catalog reading. A catalog reading says, “Here are the moves.” An architecture reading says, “Here are the records, here are the boundaries, here are the consumers, here is where policy is applied, and here is where behavior becomes visible.”

Now let’s tie in secondary move data. The packet names pokemon-showdown/data/moves.ts chunk_012eada95ff7aa5f as secondary move data. Showdown’s move records can include a large amount of semantic data: categories, flags, secondary effects, callbacks, and properties used by the simulator. For our purposes, secondary effects are useful because they show why “move lookup” is not just name and base power. A move may damage, inflict a status, change boosts, call a callback, interact with protection, or have generation-specific differences. In FireRed, similar gameplay outcomes are distributed through move effect constants, battle scripts, and utility functions. Again, the shape is different. The concept is comparable.

Here is the concrete tracing exercise I would expect an advanced student to be able to perform. Pick a move with a secondary status chance. In Showdown, retrieve its move record and inspect the secondary data. Then identify whether the record is standard for the selected mod. In FireRed, identify the move constant, identify the battle move effect or associated effect script, trace where the battle engine applies the chance or status, and then trace how the message and animation reach the player. You do not have to memorize every function name to understand the architecture. But you do have to know which layer you are in.

And this is where week 22 fits in the course plan. Weeks 1 through 21 built the FireRed mental model: runtime shell, callbacks, tasks, maps, scripts, creature data, battle, inventory, UI, save, and link systems. We are no longer discovering that these systems exist. The recent homework and quiz work already checked that you can identify files, structs, constants, state variables, and functions across major systems. Week 22 raises the bar. We now compare FireRed with a living simulator whose architecture solves a related but different problem. The purpose is not to say one is better. The purpose is to make your own architecture vocabulary sharper.

When you later design your own creature-collector RPG, this comparison will become practical. If your game is a fixed single-player cartridge-like project, FireRed’s approach may suggest compact tables, explicit state machines, and tightly integrated scripting. If your game supports live rulesets, custom formats, modded generations, or server-side validation, Showdown’s Dex facade and filtering boundaries become more relevant. Most modern projects need a hybrid. They need authoritative data records, a validation layer, a runtime battle state, and a clear separation between “this record exists” and “this record is legal in this mode.”

So, before we move forward, I want to recap the key distinction in plain language. Showdown’s Dex gives you an addressable data facade. You ask it for moves, species, abilities, and items within a selected mod. Then rules and filters decide what belongs in a format. FireRed gives you compiled tables and constants. The runtime composes those through globals, scripts, callbacks, tasks, battle structs, and concrete source functions. In Showdown, lookup is a service. In FireRed, lookup is usually a table access embedded in a fixed engine path. In both systems, behavior emerges only after data meets control flow.

Hold onto that, because in the next part we are going to push on legality more directly. We will ask what it means to say a team, a move, or a species is “allowed,” and we will separate three things that are often confused: data existence, game availability, and competitive legality.

Now, let us take that distinction and make it sharper, because this is where advanced students often start to blur categories. Existence is not availability. Availability is not legality. Legality is not behavior. Those four terms are related, but they are not the same layer.

If I write on the board, “Does this move exist?” that is a data lookup question. In Showdown, this is the easy case. You ask the Dex for the move. The Week 22 packet points us to pokemon-showdown/sim/DEX.md, chunk_922688d7428150d1, for the basic purpose of the Dex and move lookup. The important idea there is not merely that a move can be found by name. The important idea is that lookup is mediated through a Dex object that knows which data universe it is operating in. That means the question is not just “what is Thunderbolt?” It is “what is Thunderbolt in this generation mod, under this data layer, with this normalized identifier?”

Now compare FireRed. In FireRed, Thunderbolt is not normally looked up by asking a facade object, “please give me a move record.” Thunderbolt is a move constant, and the engine reaches into compiled tables using that constant or an index derived from it. The source packet points us to pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, where the battle utility layer includes constants for moves, items, abilities, Pokemon species, battle move effects, and so on. That include list itself is a signal. FireRed’s battle code is not abstracting data access behind a generic Dex service. It is binding together concrete domains through headers and constants, then executing fixed engine paths.

So, pause there. If I ask, “Does Thunderbolt exist in the project?” Showdown and FireRed both can answer yes. But they answer through different architectural habits. Showdown says, “resolve the ID through the Dex for the selected mod.” FireRed says, “the constant and table entry exist in the compiled program, and battle code uses those constants in engine logic.”

Now let’s add the second question: “Can this creature learn Thunderbolt?” That sounds similar, but it is not the same question. In Showdown, learnsets become a secondary modeling reference. The prompt for this week specifically names pokemon-showdown/data/mods/gen9dlc1/learnsets.ts as a high-signal modern learnset file, but also warns us that it is not FireRed behavior. That warning matters. Showdown’s learnset file can help us reason about how a simulator models learnability as data, especially across generation mods, but we must not smuggle that model backward into FireRed and pretend FireRed has the same runtime abstraction.

In FireRed, learnability can appear through several concrete systems. A level-up move table is one source. A TM or HM compatibility table is another. Tutor logic, egg moves, evolutions, party manipulation, and scripted gifts all live in different places in the engine’s broader architecture. The player-visible result, “this Pokemon has this move,” might come from wild encounter generation, a trainer party definition, a starter script, daycare or breeding rules, or direct party mutation in a special event. FireRed’s architecture does not require all of those to pass through a single “legality” object before the creature can exist. The creature exists as party data, battle data, save data, and display data, depending on which subsystem currently owns the question.

That is why our tracing method from earlier weeks remains valuable. We do not ask only, “where is the data?” We ask, “what function reads it, what global or struct receives it, what callback or task advances it, and where does the player see the result?” That is the whole course pattern again: data records through globals, callbacks, tasks, scripts, structs, and concrete source functions. Showdown helps us name the data boundary. FireRed forces us to trace the runtime path.

Let me give a concrete example, and I’ll keep it small. Suppose we choose a species and a move. Let us say Pikachu and Surf, because it is a useful example precisely because it creates tension between “possible in some official context,” “ordinary game availability,” and “legal in a particular ruleset.” In Showdown, the simulator can have a move record for Surf and a species record for Pikachu. Those are existence checks. If we load a generation mod using the Dex.mod idea described in pokemon-showdown/sim/DEX.md, chunk_5fbe60392b5eedf9, then we are no longer asking about an eternal universal Surf or an eternal universal Pikachu. We are asking about those records as viewed through a generation-specific data world. Then a format validator or rule layer may decide whether Pikachu with Surf is allowed.

In FireRed, the question takes a different shape. Surf exists as a move constant and move table entry. Pikachu exists as a species constant and base data entry. But the ordinary path by which the player obtains a Pikachu, teaches moves, and enters battle is distributed. A wild encounter path creates or selects a species. A party struct stores the individual creature. A move teaching interface checks compatibility or special conditions. A battle setup path transforms party state into battle state. And battle utility code later interprets moves, effects, abilities, items, and statuses using concrete constants, as signaled by pokefirered/src/battle_util.c, chunk_9335e5727aa0657d.

Here is the check for understanding. If a move record exists, does that prove a species can learn it? No. If a species can learn it in one generation, does that prove it is legal in another generation? No. If a creature with that move is present in FireRed party memory, does that prove it was obtainable by normal gameplay? Also no. Good. Those are three different claims, and the architecture keeps them separate even when the UI collapses them into one player-facing question.

Now, on the slide, I would draw three boxes. First box: “data existence.” Second box: “game availability.” Third box: “rules legality.” Under Showdown, I would draw arrows from Dex lookup to modded data to filters. Under FireRed, I would draw arrows from constants and tables into engine paths: scripts, menu callbacks, tasks, party structs, battle setup, battle execution. The visual contrast is important. Showdown centralizes the read interface. FireRed centralizes much less at the lookup boundary; it centralizes behavior in engine systems.

This is also where NONSTANDARD.md matters. The packet points us to pokemon-showdown/sim/NONSTANDARD.md, chunk_800f1eafbea0ed7c, with the note that all data requires filtering. That is a compact but powerful idea. Showdown can contain records that should not automatically be admitted into every competitive context. A move, species, ability, or item may exist in the data corpus and still be marked in a way that requires a format to exclude it or treat it specially. In other words, the Dex is not the same thing as the rulebook. The Dex can tell you what something is. The rules decide whether you may bring it.

FireRed does have boundaries, of course, but they are not expressed in quite that same generic filter vocabulary. FireRed’s boundaries are often mechanical and path-dependent. Can the player reach this map? Has this flag been set? Does this script give this item? Does this mart sell this object? Is this HM badge condition satisfied? Does the party menu allow this action right now? Is the current battle type compatible with this behavior? Those are legality-like constraints in the broad software sense, but they are not necessarily implemented as a reusable validator over a full Dex dataset.

And that distinction prepares you for the workshop. When you write the Showdown-side lookup script this week, I do not want a script that merely prints “Charizard exists” or “Thunderbolt exists.” That is too shallow for Week 22. I want you to load a generation mod, retrieve selected move, species, ability, and item records using the APIs described in pokemon-showdown/sim/DEX.md, chunk_74ee605430e5596f, then inspect which records need filtering. If something is nonstandard, your script should not just print it as though existence equals permission. It should document the boundary. The lab write-up should say, in plain engineering language, “this is a Dex lookup result; this is not the same thing as FireRed runtime availability.”

Let’s connect this to move data specifically. The packet names pokemon-showdown/data/moves.ts, chunk_012eada95ff7aa5f, as secondary move data. A Showdown move record can carry rich descriptive and mechanical fields. The text side is even separated in a file like pokemon-showdown/data/text/moves.ts, chunk_1620277751dc01f4, where descriptions explain effects such as redirection or screen removal. That separation is very simulator-friendly. You can have data records, text records, and rules code working together around stable IDs.

FireRed’s move behavior, by contrast, is more tightly woven into battle execution. Yes, there is move data. But when the move is actually used, the battle engine is not simply displaying a record. It is evaluating effects, type interactions, accuracy, damage, status, animations, controller messages, and battle scripts. The include list in pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, is a useful reminder because it pulls together battle scripts, battle messages, battle controllers, animation constants, weather constants, ability constants, item constants, and move effect constants. That is the compiled engine doing work, not a pure data browser.

So if Showdown says, “here is the move object,” FireRed more often says, “here is the move ID flowing through battle state into an effect command and message sequence.” That is why direct one-to-one comparisons can mislead you. You may compare Showdown’s move object to FireRed’s move table, but the player-visible behavior is not in the table alone. It is in the table plus the battle engine path.

Let me make the architecture distinction even more concrete. Imagine a debugging session. In Showdown, your bug report says: “In Gen 7, this move has the wrong base power.” A reasonable first stop is Dex.mod for Gen 7, then moves lookup, then inherited or overridden data. You inspect whether the modded data resolves correctly. If the record is correct but behavior is wrong, you move into simulator scripts.

In FireRed, your bug report says: “This move displays correctly but behaves incorrectly in battle.” Your first stop might be the move’s table entry, yes, but you quickly have to follow the effect constant into battle utility code, battle scripts, animation handling, and controller output. You ask which battle struct fields are set, which script command runs, which global battle state changes, and which callback continues the frame. That is the FireRed discipline you have built since the early weeks.

And notice how this reaches back to the runtime shell without re-teaching it. We already covered AgbMain, SetMainCallback2, task allocation, task IDs, and RunTasks. The chunks in the packet for pokefirered/src/main.c and pokefirered/src/task.c gave us that foundation earlier: AgbMain startup responsibilities in chunk_b35676322b169f85, SetMainCallback2 in chunk_6cfd90f6d0136799, CreateTask in chunk_cb0bb91a147bfb59, and RunTasks in chunk_3ffebc0341225936. Today we are using that as prior foundation. The important connection is this: FireRed’s data does not become gameplay until one of those runtime paths is active. A table entry sitting in ROM is inert. A task, callback, script, menu, or battle function makes it live.

Now, let me ask another check question. If Showdown has a clean Dex API, does that mean Showdown has no hard-coded behavior? No, absolutely not. The Dex is a facade for data lookup, not a replacement for the simulator. We saw in the packet that mod scripts exist too. For example, pokemon-showdown/data/mods/gen2stadium2/scripts.ts, chunk_3480e574205d5d0f, shows generation- or format-specific damage behavior logic: checking immunities, OHKO handling, damage callbacks, fixed damage, level damage, and related move evaluation. That is not just a passive table. So the real contrast is not “Showdown is data and FireRed is code.” That would be false. The contrast is “Showdown exposes a data facade and mod layering as a major organizing pattern, while FireRed uses compiled tables and engine-specific control paths as the normal organizing pattern.”

That correction matters because advanced architecture comparison should avoid caricature. Both systems contain data. Both systems contain behavior. Both systems contain rules. But they place the abstraction boundary in different places.

Let’s bring abilities and items into the picture briefly. The Week 22 topic list includes move, species, ability, and item lookup. In Showdown, the same Dex style applies across these categories. You can ask for an ability record or an item record through the relevant API. The packet’s pokemon-showdown/data/abilities.ts, chunk_da22cf969179258c, even shows that ability data may include simulator-facing ratings and qualitative categories such as detrimental, useful, very useful, or metagame-defining. That kind of metadata is not simply “what happens in cartridge battle?” It is simulator and competitive ecosystem knowledge layered into the data model.

FireRed does not need that rating metadata to run. It needs ability constants, item constants, effect logic, party fields, battle fields, and UI text. A held item’s existence, availability, and battle behavior are again separate. An item may exist in constants. It may or may not be obtainable in normal gameplay. It may or may not be usable from the bag in a particular context. It may or may not have a battle hold effect. Those questions route through different engine paths. In FireRed style, “item lookup” is less likely to be one universal question and more likely to be, “which subsystem is asking, and what table or function does that subsystem use?”

At this point, someone usually asks, “Professor, which architecture is better?” That is the wrong question unless you specify the design pressure. Showdown is built for a long-lived simulator supporting many generations, mods, formats, tests, and rule variations. A facade like Dex is an excellent fit because it gives battle code, validation code, and tools a common vocabulary. FireRed is a shipped GBA game with static assets, compiled data, constrained memory, fixed content, and a frame-driven engine. Its architecture optimizes around cartridge-era constraints and concrete gameplay flows, not around arbitrary future mod loading.

So the better engineering question is: “What problem does this boundary solve?” Showdown’s Dex boundary solves cross-generation lookup and tooling consistency. FireRed’s table-and-engine boundary solves fast, predictable integration with a fixed runtime. When you design your own creature RPG, you have to choose deliberately. If you expect mods, multiple rulesets, or simulator-style validation, you probably want a Dex-like facade. If you are building a small fixed game, you may not need that abstraction early, but you still need clean ownership of data and runtime state.

Let’s do one more board cue. I’m writing: “A record is not a permission.” Underline “not.” A move record is not permission to use the move. A species record is not permission to encounter the species. An item record is not permission to buy the item. An ability record is not permission for a species to have the ability. Permission is produced by a rule context. In Showdown, that context is often explicit: selected mod, selected format, validation rules, nonstandard filters. In FireRed, that context is often embodied in progression flags, scripts, map access, menu state, battle type, and hard-coded engine paths.

And this is why the next lecture, “Legality Is a Filter Over Data,” is not a side topic. It is the natural continuation of today. Once you can separate existence from availability, legality becomes easier to reason about. A validator is not magic. It is a structured answer to the question, “Given this data universe and this rule context, which combinations are admitted?” Showdown makes that question visible. FireRed often answers it implicitly through the only paths the game exposes to the player.

For today’s local recap, keep these three sentences in your notes. Showdown’s Dex is an addressable facade over modded battle data. FireRed’s tables are compiled resources activated by concrete engine paths. In both, the player-visible result is produced only when lookup meets control flow and rules.

We will keep moving from that point next, and we are going to tighten the vocabulary around filters, because once you stop treating existence as legality, a lot of simulator design and a lot of cartridge design suddenly become much easier to compare.

Now, let’s tighten that word “filter,” because it is doing a lot of architectural work here. A filter is not just an if statement. It is a boundary between “the data universe contains this record” and “this particular mode of play accepts this record.” So if I write on the board, “record exists,” and then below it, “record is selectable,” and below that, “record is legal in this ruleset,” those are three different claims. In a small cartridge RPG, those claims may collapse together most of the time because the player never gets a general-purpose query interface. In a simulator like Showdown, those claims must be separated, because the user, the validator, the battle engine, the team builder, and the mod system all ask related but different questions.

Think about a move first. In Showdown, the Dex can answer, “What is Thunderbolt?” as a data lookup. The week packet’s source focus points us to pokemon-showdown/sim/DEX.md, especially chunk_922688d7428150d1 for Dex purpose and move lookup, and chunk_74ee605430e5596f for the APIs around moves, species, abilities, and items. That gives us a facade: you ask the Dex for a move, you get a normalized move record. But that does not yet mean a given species may learn it. It does not mean the current generation admits it. It does not mean a format allows it. It does not mean a particular mod has not overridden or deleted some property. So the Showdown lookup story is deliberately layered. Lookup first. Mod context second. Rule and legality filter after that.

Now compare FireRed. In FireRed, the move data is not exposed as a general Dex object that arbitrary tools ask questions of at runtime. The move ID is a compact constant. The move table is compiled into the program. The party Pokémon has move slots. The battle engine reads those slots and interprets them through battle code and scripts. The player does not normally type “Thunderbolt” into a lookup API. The player teaches a move through a TM path, level-up path, breeding path, or scripted gift path, and those paths are where most of the practical legality boundary lives. By the time the battle engine sees the party data, it mostly treats those move slots as facts.

Let me say that again, because it is a useful advanced distinction: FireRed’s battle engine is not primarily a legality validator. It is a consumer of already-formed state. That state came from data tables, scripts, menu tasks, item effects, party mutation routines, and save restoration. We have spent earlier weeks tracing that kind of path. We are not reopening the entire save system today, but remember the foundation: save blocks preserve party, bag, flags, and world state; loading restores those structures; then ordinary callbacks and tasks consume them. Today’s point is that once a Pokémon’s four moves are present in the party structure, battle code does not rediscover the full historical proof that each move was obtained legally. It runs the battle.

This is where the FireRed include structure is a useful clue. In pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, the file pulls in battle, battle scripts, battle message, battle controllers, constants for moves, items, abilities, Pokémon, hold effects, and battle move effects. That is not a validator-shaped dependency list. That is an execution-shaped dependency list. It says, in effect, “I need the constants and runtime battle state necessary to resolve effects.” It is a concrete engine module, not a general data facade. So when we compare it to Showdown’s Dex, we should not say, “FireRed lacks a Dex.” That is too vague. We should say, “FireRed distributes lookup across compiled tables, constants, structs, and engine-specific routines, while Showdown centralizes much of that access behind an addressable Dex facade.”

Let’s do a concrete example. Suppose our selected move is Thunderbolt, and suppose our selected species is Pikachu. In Showdown, a script can load a generation mod, ask the Dex for the move record, ask the Dex for the species record, and then separately inspect learnsets or legality data. If we load a newer generation mod, the same string lookup might resolve in a data universe that includes different species forms, abilities, move flags, or mechanical changes. The DEX.md generation-mod section, chunk_5fbe60392b5eedf9, is exactly why this matters this week: Dex.mod is not just a namespace convenience. It is a way of saying, “Answer my data questions from this generation-specific universe.”

In FireRed, the equivalent workflow is not “load gen3 and ask Dex.moves.get.” The equivalent workflow is more like this. The move constant names an index. The species constant names an index. Learnability is represented through the game’s compiled learnset and TM/HM compatibility data. A menu or script path checks whether an action is possible, then mutates the party data if the player completes it. A callback controls the screen. A task may manage the menu interaction over frames. A script may have brought the player to the item, tutor, or event in the first place. Then later, battle setup copies the relevant Pokémon state into battle globals, and battle utility functions resolve the effect. The player sees “Pikachu used Thunderbolt,” but architecturally that sentence is the final visible surface of several earlier boundaries.

Check your understanding here. If a move record exists in Showdown’s data files, is it automatically legal in every Showdown format? No. Existence is not legality. If a move constant exists in FireRed’s constants, is every ordinary player path guaranteed to let every species use that move? Again, no. The constant exists so the engine can name the move. The access path still matters. That is the same conceptual distinction wearing two different architectural costumes.

Now, I want to connect this to nonstandard filtering, because this is where advanced students often make a subtle mistake. You look at a simulator data repository and you think, “The data file is the truth.” But the data file is too broad to be the final truth for a format. The packet points us to pokemon-showdown/sim/NONSTANDARD.md, chunk_800f1eafbea0ed7c, with the note that all data requires filtering. That is the key phrase: all data requires filtering. Some entries are past-generation only, event-only, unreleased, custom, future, CAP, LGPE, or otherwise outside the format being validated. The Dex may still need to represent them, because other modes, historical formats, tests, tools, or mods may care. The mistake is expecting one flat data table to encode every answer.

FireRed creates a different illusion. Because the cartridge is narrower, you may be tempted to think no filter exists. But the filter is there. It is just embodied in control flow. Which maps can the player reach? Which flags have been set? Which scripts are active? Which bag items exist? Which menu options appear? Which tasks run when the player presses A? Which functions write to the party’s move slots? That is filtering. It may not be called “nonstandard,” and it may not be documented as a validator rule, but it decides what combinations become reachable in normal play.

Let me put a small board diagram up. On the left, I’m writing “Showdown.” Under it: “Dex data, mod context, rule table, validator, battle.” On the right, I’m writing “FireRed.” Under it: “compiled data, globals, callbacks/tasks/scripts, struct mutation, battle.” The arrows are important. In Showdown, the validator can stand between the team description and the battle start. In FireRed, many filters occur before the state ever looks like a battle team. They occur in the acquisition path. The final battle engine consumes a party that the rest of the game has already shaped.

This is also why learnsets are a secondary modeling reference for us this week, not a replacement authority for FireRed. The packet names pokemon-showdown/data/mods/gen9dlc1/learnsets.ts as a high-signal modern learnset file. That is valuable because it shows how a simulator organizes species-to-move availability in a modern data ecosystem. But it is not FireRed behavior. It can help us reason about data modeling. It can help us design a lab script that prints a species record and then asks what learnset information exists. It should not cause us to retrofit Showdown’s architecture onto the GBA engine.

Let’s make that concrete in lab terms. If your workshop script loads a generation mod, prints a selected move, prints a selected species, and filters out nonstandard entries, the important paragraph in your write-up is not “I found the move.” The important paragraph is “This lookup answers a different question than FireRed’s battle path.” A good answer will say: Showdown can ask for data by textual ID through a Dex facade; FireRed uses numeric constants and compiled tables. Showdown can select a mod such as a generation-specific rules universe; FireRed is already a fixed executable and data bundle, unless we are building a ROM hack or a decomp modification. Showdown must filter broad data for a format; FireRed filters ordinary play mostly through reachable scripts, menus, flags, and item paths.

Now, let’s fold in abilities and items briefly, because this makes the comparison sharper. Showdown’s data model gives abilities their own lookup space. The packet includes pokemon-showdown/data/abilities.ts, chunk_da22cf969179258c, where the comments describe ability ratings from detrimental through metagame-defining. That rating field is not a FireRed battle mechanic in the same way an ability effect is. It is simulator ecosystem metadata. It helps tools evaluate or present data. FireRed’s ability constants and effects are part of battle execution, but FireRed is not storing a singles metagame usefulness rating beside each ability for a team builder. Same creature concept, different surrounding software system.

Items show the same pattern. Showdown can ask the Dex for item data. A mod may reinterpret, override, or extend behavior. The packet even includes an example from pokemon-showdown/data/mods/biomechmons/scripts.ts, chunk_1434b1000eb1576c, where modded scripting performs unusual cross-lookups among items, abilities, and moves. That kind of flexibility is normal in a simulator designed to host many formats and mods. FireRed can absolutely have item behavior, held effects, battle item effects, and inventory menus, but those are compiled engine pathways. You do not get the same universal dynamic lookup surface unless you build it.

Pause for a second and ask yourself: why does this matter for architecture? It matters because once you design the lookup layer, you are also designing the possible extension layer. A centralized Dex facade makes it easier to write tools that say, “Give me all moves in this generation,” or “Hide nonstandard species,” or “Compare item records across mods.” A compiled-table engine makes it easier to run fast on a constrained device, with predictable memory and direct control flow, but it spreads the meaning of legality and access across many systems. Neither is morally superior. They optimize for different machines, different workflows, and different eras.

Now let’s bring this back to the course’s main trace pattern. We have used the phrase “data table to runtime globals to callback or task to player-visible behavior” all semester. In FireRed, if the player opens a menu to teach a TM, that is not merely data lookup. It is UI state, input handling, task scheduling, bag state, party selection, compatibility checking, move replacement, and then a write into the creature’s data. If the player later enters battle, battle setup and battle utility code read the resulting state. The constants and includes visible in pokefirered/src/battle_util.c, chunk_9335e5727aa0657d, remind us that battle resolution is tied to concrete source modules and constants. That is exactly the tracing discipline you practiced in week 21 homework: decompose the RPG into runtime shell, overworld maps, scripting, creature data, battle, inventory, UI, save, and link systems, and then explain how one visible behavior crosses boundaries.

Showdown asks for the same discipline, but the boundaries have different names. A team importable string or object enters the simulator environment. A Dex associated with a mod answers data questions. A validator filters the set against the format. A battle engine consumes the admitted team. Tests can then assert deterministic outcomes. So when we use Showdown in weeks 22 through 24, we are not changing the course thesis. We are adding a comparison instrument. FireRed remains the primary architecture source. Showdown helps us see what a modern simulator exposes explicitly: mod selection, data facades, broad records, filtering, and testable battle assumptions.

Here is a common failure mode I want you to avoid in homework_w22. Do not write, “FireRed has no legality system.” That is imprecise. A better sentence is, “FireRed does not expose legality as a general simulator validator in the Showdown style; many ordinary legality boundaries are enforced earlier by acquisition paths, scripts, menus, flags, and table-driven compatibility checks.” That sentence is longer, but it is architecturally correct. It tells me you understand both systems. It also respects the fact that FireRed has link battles, trading, save loading, and data validation concerns without dragging us back into the full save-sector lecture.

Another failure mode: do not write, “Showdown’s Dex is just like FireRed’s move table.” It is not. The move table comparison is only one slice. Showdown’s Dex is an interface for data lookup across categories and mods. FireRed’s move table is a compiled resource used by concrete engine code. If you want to compare them, compare the question each one can answer. FireRed’s table can answer, “Given this move ID, what are the properties needed by the engine?” Showdown’s Dex can answer, “Given this ID in this modded data universe, what record should simulator systems use?” Then legality filtering asks the next question.

Let’s do one more check for understanding, and I’ll phrase it as an exam-style prompt. You are debugging a simulator team where a species has a move in the data files, but the team validator rejects it. Where do you look? You look beyond move existence. You inspect the mod generation, species data, learnset data, format rules, and nonstandard status. Now the FireRed parallel: you are debugging a ROM modification where a move exists and the battle engine can execute it, but the player cannot teach it by TM. Where do you look? You inspect TM compatibility data, item behavior, menu task flow, party mutation routines, relevant scripts, and whether the item is reachable. In both cases, the move record existing is only the first fact.

That is the vocabulary I want you to carry forward: existence, lookup, reachability, compatibility, legality, execution. Existence means the record is present. Lookup means some system can retrieve it. Reachability means normal control flow can bring the player or tool to it. Compatibility means a rule or table permits a pairing. Legality means the complete rule context admits the final combination. Execution means the battle or game engine consumes the result and produces behavior. If you keep those six words separate, the FireRed and Showdown comparison becomes much cleaner.

So, to close today’s lecture, let’s synthesize. Showdown’s Dex is an addressable facade over a broad, modded data universe. It is built for tools, validators, formats, historical generations, and simulator battles that need explicit filtering. FireRed’s architecture is a compiled, stateful game engine where data tables become behavior through globals, callbacks, tasks, scripts, structs, and concrete source functions. Its filters are often not named as filters; they live in the only paths the game gives the player. That is why the same player-facing sentence, “this creature can use this move,” means different things depending on where in the architecture we are standing.

For next time, keep the lab script practical. Load a Showdown mod. Print selected move and species records. Filter nonstandard data. Then write the comparison paragraph carefully. The goal is not to prove that one architecture is more advanced. The goal is to show that you can trace data from representation to rule boundary to visible behavior. That tracing skill is the bridge from week 22 into the rest of the module, where we will use Showdown not as a replacement for FireRed, but as a verification mirror for the battle-data questions FireRed leaves distributed across the engine.

## Source References
- pokefirered/src/battle_util.c
- pokemon-showdown/data/abilities.ts
- pokemon-showdown/data/mods/biomechmons/scripts.ts
- pokemon-showdown/data/mods/gen2stadium2/scripts.ts
- pokemon-showdown/data/text/moves.ts
- pokefirered/src/battle_setup.c
