Time in the game works like this: each frame, the game calls a tick function on the airship, passing the number of milliseconds that have passed since the last frame. The airship passes on this information to its crew and modules by calling their tick functions.
Modules count down the amount of time left until they shoot, or require more coal, and they keep track of things like how much ammo they have left, and how damaged they are.
The airship has a list of crew objects. Each of those airsailors is always at a particular tile location. They move by accumulating time in their tick function. Once they have accumulated enough time to move out of their current tile, they move to an adjacent tile of their choice. Corridors require the least amount of time to move through, only 300 ms, whereas busy places like gatling guns require 800 ms.
It's the crew's job to run around in the ship, supplying modules with coal and ammo and repair, putting out fires, and manning modules. This means they have to know how to get from any tile to any module in the ship. To make this go quickly, I pre-calculate all those paths whenever the ship's layout changes.
These paths are a mapping of pairs of origin tile and target module to lists of adjacent tiles that are the path from origin to target. Crew can look up these mappings to figure out where to go.
Calculating the pathing is quite nice and clean, actually: Loop over all of the target modules. For each module, use a flood fill to figure out how far each tile is away from the target module. Then, loop over all source tiles, and use a simple gradient descent strategy to figure out the fastest path.
In the long term, I may have to change how this works, as fires, damage, and congestion can radically alter what's considered the best path.
Each module exposes a number of jobs that may need doing, such as "feed me coal" or "repair me". These jobs can be active or inactive, depending on whether e.g. the module is currently damaged. They also have a priority between 0 and 1 - putting out a raging fire is more important than fetching ammunition for a gun that won't need it for a while yet.
The nice thing about the jobs is that they're all of the form "fetch resource X to me" or "come to me" - the latter being just a simpler version of the former.
Each tick, the airship gathers up all the active jobs, filters out the ones that are already being taken care of, and ranks them in priority. It then awards these jobs in priority order to idle crewmen. Additionally, it then looks at non-idle crewmen, and if one can be found who has a much less urgent job than the most important unassigned one, it reassigns the crewman. So it will tend to let the crew finish one assignment before going on to the next, unless there's something much more important to do.
Crewmen with a fetch job move from the current tile to the best-placed module that can supply them with the resource (coal, ammo, water, repair tools) they need, and then move to the module that's asked them to do their job. Once there, they "give" the resource to the module and clear their job, to be assigned a new one next tick.
Those with a job that's just "go to this module" move to that module and then stand there, doing their job, until assigned something more urgent.
So at a semantic level, a crewman is always in one tile. Visually, it's nicer to have them move smoothly. The drawing code calculates how many milliseconds the crewman has accumulated towards being in next tile and interpolates his position, making the movement smooth.
Putting all of this together, it means that the airships are now alive: crew are running around, doing work, and modules are consuming resources.
There's some minor bugs such as modules that require manning, such as guns, running in the absence of crew. This just requires some extra logic and should be straightforward.
After that, the time has come for a code reorg: the editor code will get moved to its own class instead of being in the main game class, to make way for having a combat mode to switch to.
Soon after, the lives of the little airsailors will get a lot more complicated, with things catching fire and breaking down, and the occasional horrific injury... Combat!