Red Alert 2 Yuri's Revenge — rebuilt from scratch in Rust
The entire engine is built from two things: structs and functions. There are zero abstractions layers. Code are logically organized in files and folders. Codebase is therefore very machine and human friendly.
All game state lives in one struct: Simulation.
It contains:
entities: EntityStore — every unit/building/aircraft in the gameproduction: ProductionState — build queues, credits, rally points per playerfog: FogState — shroud/visibility per playerpower_states — per-player power grid (output, drain, blackout)super_weapons — per-player superweapon countdownsoccupancy: OccupancyGrid — which entity occupies which cellhouses — per-player state (alliances, defeat status)terrain_costs — pathfinding cost gridszone_grid — zone connectivity for unreachability checksoverlay_grid — ore, gems, walls on the mapbridge_state — bridge health and connectivityrng: SimRng — single deterministic random number generatortick: u64 — current game tick counterEach of those is a plain struct or a map of structs. No behavior attached to them.
GameEntity is one struct with optional fieldsEvery object in the game — tank, soldier, building, aircraft — is the same struct. Always-present fields: stable_id, position, health, owner, facing, type_ref, category. Optional fields are Option<T>: a tank has locomotor + turret_facing + drive_track, a building has production, a harvester has miner. No component has methods — they’re all data.
(Example functions below)
tick_movement() — reads entity positions and locomotor data, writes new positionstick_combat() — reads attack targets and weapon stats, applies damagetick_production() — advances build queues, spawns finished unitstick_power_states() — recalculates per-player power from buildingstick_superweapons() — counts down timers, fires effectstick_ore_growth() — spreads ore across the mapThese functions all read and write to the same Simulation struct. 45 times a second at 45 FPS(standard multiplayer FPS) There is no message buses, no event systems.
Simulation::advance_tick() calls: commands → movement → combat → vision → power → superweapons → production → AI → defeat check → state hash. Every tick, same order.
render/ reads GameEntity.position, .facing, .health, .is_voxel etc. to decide what to draw and where. It never writes to simulation state.
You can work on a module without neccesarly knowing anything on outside. Sim is hermetically sealed from render.