Site Tools


dev:overview

What Free Enterprise Actually Does: A High-Level Code Summary

The Free Enterprise randomizer is a fairly large project; this page is intended to give a summary of the different parts of the project and what happens in the code when the generator runs. It currently applies to version 4.6.0.

Project folders

FreeEnt

This folder is the main guts of the randomizer. At the top level are found all of the Python scripts for the various randomizations that occur, as well as for any game modifications (like item prices, dialogue, and sprite palettes) and some tools for working with specific data. The subfolders contain asset data about FF4/FE (like item descriptions used by the Select button help and all of the databases for items and treasure curves, etc.), compiled Z sprites and TwinHarp music files (see fetools) and a characters binary patch, f4c scripts used by the randomizer to modify the game's code (see f4c), and files that are used to run a webserver instead of just using the command line generator (e.g. for public-facing usage).

f4c

To apply patches to the FF4 base ROM, FE uses .f4c scripting files, parsed using (an old version of) Lark. This folder contains the Lark parser, tools for obtaining information about the FF4 base ROM, and all of the FE-specific grammar required to translate the .f4c scripting instructions into patches.

See the f4c wiki page for more information. Note that patches cannot overwrite other patches (e.g. if you want to change the Black shirt's stats data, then you need to remove the change that's already been made to it and make your own change). Patch conflicts will be reported as errors when generating a seed.

fetools

FE uses external assets in exactly two places: the Zeromus sprite and the TwinHarp music. This folder contains the tools required to import sprites and MIDI files into FE and use them in the game. (Documentation for these tools will eventually be written.)

Code Summary

So, what happens when you generate a seed of Free Enterprise? The flagstring and metaconfiguration options are parsed and fed into generator.py, which is where the bulk of the magic work actually happens.

Imports

generator.py imports a number of global and FE-specific tools. Of note are the [x]_rando.py scripts (the primary randomization tools), the script preprocessor (for conditionals in .f4c files), the version, and the Distribution class (which is used for a number of weighted choices).

f4c Files

The long list of .f4c files, provided as a string, is the list of always-active patches and bugfixes used to create the FE experience. It will be parsed later. Of note are the eventextensions files, which form the basis for checking things like objective completion, whether Fu should learn spells, and so on.

Immediately after the list of .f4c files are the pre-compiled binary patches to be applied.

Class and Function Definitions

The Generator[x] classes collect the options, flags, and output of the randomization process. The Environment class collects data about the randomization and carries it through the entire randomization process; it has a number of subfunctions for collecting that data and setting up the scripting that applies the patches to the ROM. The env object defined later is an Environment; env is passed to every relevant script, so those scripts can use the accumulated information and add more to it. Some of the important fields in an Environment are:

  • options: This data is the parsed input from the command line or webserver as defined in the GeneratorOptions class; options.flags contains individual flags and flag slugs (see flagspec.txt and flagspec information, as well as flagsetcore.py for the output format and ways to inspect the flags), which can be used to write conditionals based on what flags were given.
  • meta: This object is a Python dictionary. It can be used to store basically anything that might need to be used later in a different script. For example, env.meta['starting_character'] returns the starting character as assigned in character_rando.py, which is used later in custom_weapon_rando.py under Chero to choose which supersmith weapon to be the Forge reward.
  • rewards: Collects the character, key item, and MIAB reward assignment data.
  • spoilers: Collects the spoiler log data as the scripts progress.
  • rnd: Given a seed, the randomizer should be deterministic. env.rnd is an instance of a Python random.Random() class that initializes itself based on the given seed; env.rnd should be used whenever one wants to make a random decision.
  • substitutions, toggles, scripts, etc.: These fields accumulate the various pieces of scripting data over the course of the randomization. There are functions that add scripts/etc. to these fields.

There are also some functions that generate pregame text, postgame text, the checksum, etc.

The Build Function

The operation of building the randomization happens in generator.build. After some setup (including initializing the env and checking the flags for errors), the big list of .f4c files are added and basic metadata is embedded into the ROM. After that, many modules are called to perform randomization of different aspects of the game, in three phases: setup, apply, and validate. Not every phase calls every module. More detailed explanations of each module can be found elsewhere.

Because wacky_rando.py makes some wide-scale changes to the game at times, its setup phase is always called first. Then some US-JP version differences are handled (because while FE works off the US 1.1 version, JP features are/can be included), and then the big loop of modules/phases occurs. The order matters; for instance, core_rando handles the quest/MIAB rewards and boss placement, and because that happens before characters are placed, the rewards cannot depend on the available characters in the seed. After that comes the Zeromus sprite and TwinHarp music implementation, followed by some flag-specific changes, changes to item prices, and the check for whether the flags are hidden. wacky_rando is applied at the end.

The randomization is complete, so now the patches must be finalized and applied. Included in this process is pulling the Select button item description data into a binary patch, setting up the pregame text, and handling test settings (like the boss-fight event). Afterwards, the scripts are pre-processed (to make the relevant flag-dependent substitutions) and combined into one big script, which is then applied to the ROM. If a public spoiler log should be generated, that also happens. The generator output includes the new ROM, the script file, a private full spoiler log, any public spoiler logs, and the list of symbols created through the scripting process along with their associated values. When using the webserver, of course, only the ROM and the public spoiler log (if any) are provided.

Rando Modules

The list of modules mentioned above covers all of the randomization that occurs in FE. Below are high-level summaries of what each module does.

core_rando

This module handles the assignment of quest/MIAB rewards (the possible K flag locations), MIAB locations, and boss placement, as well as building the spoiler logs for the quest rewards and list of key items. Assignment is performed by random fill and then testing to make sure that the fill satisfies flag logic and all checks are doable.

character_rando

This module handles most things to do with characters and character placement according to C flag logic and objectives, like fashion, naming, adding in the Chero script, placement and equipment spoiler logs, and so on.

objective_rando

This module handles selection of objectives and writing the patches for them, as well as the spoiler log entry. It also handles the pregame objectives screen.

keyitem_rando

This module only builds the postgame spoiler reel that shows the key items in their locations (in a random order).

boss_rando

Together with the pre-generated boss_rando_formation_data.py, the boss_rando module implements the entirety of the boss-scaling system in FE (including scaling of in-battle stat changes), documented in boss_randomization. It also handles the sprite/palette/music changes, the delay for Wyvern's MegaNuke in the back-attack spot, and the spoiler log for bosses.

The big “stat_scaling_reports” spreadsheet can be created here, by uncommenting a line right before the spoiler log information.

treasure_rando

While core_rando handles the rewards from quests and MIABs, treasure_rando handles the items that you can pick up from non-MIAB boxes, as well as the treasure spoiler log (including MIAB locations). There is also logic for handling the remapping of MIAB locations and inserting the Pass and DkMatters according to flags. Note that many of the T flags only apply to non-MIAB boxes and not quest/MIAB rewards (for example, Tmaxtier).

shop_rando

This module handles the randomization of shops according to the S flags (and places the Pass if appropriate) and builds the relevant spoiler log. It also handles changing of sell prices via pre-made scripts.

fusoya_rando

FE implements spell-learning and HP-growth for FuSoYa; this module determines which spells are learned after how many boss fights completed, and writes the spoiler log.

The script changes required to actually teach FuSoYa the spells happen in fusoya_challenge.f4c and eventextensions_randomizer.f4c.

encounter_rando

This module handles changes to the encounter rates according to the E flags, mostly by adding files or making script substitutions. It also handles the TrapDoor and Behemoth encounters.

sprite_rando

FE randomizes the sprites that show up when you use the Package to burn mist and when you get saved by statues during the liberation of Baron Castle. This modules handles that randomization of sprites.

summons_rando

This module handles the summons that Rydia learns at Hobs and at Dwarf Castle (subject to the -vanilla:hobs and -vanilla:growup flags). It also handles the sprite changes for the Hobs cutscene.

wyvern_rando

This module handles the changes to Wyvern's scripting based on the B flag.

dialogue_rando

This module makes the script substitutions for the Job Dwarf in Tomra, Zeromus in Owin:game seeds, and all of the dialogue changes for every NPC in the game. The text is stored in assets/db.

kit_rando

This module handles the selection of and scripting for any starter kits, and builds the spoiler log. It also defines every kit, some through generic specification and some via special cases (including kits specific to wacky flags).

custom_weapon_rando

This module deals with the reward from forging the Adamant with the Legend sword at Kokkol's forge. If the -smith: flag specifies a custom weapon, then this module replaces a dummied out weapon by the supersmith weapon; the weapon's equipment bytes, user data, Select button description, etc. are specified based on pre-exiting asset data and the scripting is done here (including a description override). If the -smith: flag specifies a random “alt” reward, then that is chosen here as well. In addition, this module has error-checking for the case the database information for a potential custom weapon is impossible in-game.

dev/overview.txt · Last modified: 2024/08/07 03:09 by wylem