This document is the canonical, consolidated reference for the TowerForge elevator system. It merges and replaces:
docs/ELEVATOR_SYSTEM.mddocs/ELEVATOR_IMPLEMENTATION_SUMMARY.md
Use this file for architecture, components, state machine, systems behavior, integration notes, rendering guidance, demo usage, testing, and future improvements.
The Elevator System provides realistic vertical transportation for person entities in the tower simulation. It is implemented with ECS components and systems and integrates tightly with the Person movement system.
Key capabilities:
- Multi-car shafts with configurable floors and capacities
- Smooth interpolation between floors (float positions)
- Door transition timings and open durations
- Stop queues and passenger destination tracking
- Assignment algorithm (first-available by default), extensible to SCAN/LOOK
- Visual rendering with occupancy and state overlays
Defined in include/core/components.hpp.
Represents a vertical shaft that contains one or more elevator cars.
Fields:
int column— grid column where shaft is placedint bottom_floor— lowest served floor (inclusive)int top_floor— highest served floor (inclusive)int car_count— number of cars in this shaft
Methods:
GetFloorRange()— total floors servedServesFloor(int floor)— whether a floor is within range
Represents an individual elevator car with its state machine and queues.
Fields (example):
struct ElevatorCar {
int shaft_entity_id; // reference to parent shaft entity
float current_floor; // float position for smooth movement
int target_floor; // next floor to stop at
ElevatorState state; // current state
int max_capacity; // default e.g. 8
int current_occupancy;
std::vector<int> stop_queue; // sorted list of requested stops
std::vector<int> passenger_destinations; // destinations of onboard passengers
float state_timer; // timer used for transitions
float door_open_duration; // default 2.0s
float door_transition_duration; // default 1.0s
float floors_per_second; // default 2.0
};Helper methods:
GetStateString()— debug string for stateIsAtFloor()— check proximity to integer floorGetCurrentFloorInt()— integer floorHasCapacity()— check free slotsAddStop(int floor)— insert into queue while keeping orderGetNextStop()— compute next target considering directionRemoveCurrentStop()— remove current floor from queue
Attached to Person entities when they need elevator transport.
Fields (example):
int shaft_entity_id— shaft person is usingint car_entity_id— assigned car (-1 if waiting)int call_floor— floor person called fromint destination_floor— target floorfloat wait_time— accumulated waitbool is_boarding— boarding flag
Lifecycle:
- Created when a
Personneeds to change floors - Persists while waiting and riding
- Removed when person exits at destination
enum class ElevatorState {
Idle,
MovingUp,
MovingDown,
DoorsOpening,
DoorsOpen,
DoorsClosing
};Typical flow:
Idle → MovingUp/MovingDown → DoorsOpening → DoorsOpen → DoorsClosing → Idle
Timing defaults:
floors_per_second: 2.0door_transition_duration: 1.0sdoor_open_duration: 2.0s
All systems are registered in src/core/ecs_world.cpp and run as OnUpdate (per-frame) except where noted.
Purpose: move cars, handle state timers and transitions.
Behavior:
- Idle: if
stop_queuenon-empty, settarget_floorand transition to MovingUp/MovingDown. - MovingUp/MovingDown: interpolate
current_floortowardtarget_flooratfloors_per_second. On arrival, transition toDoorsOpening. - DoorsOpening: wait
door_transition_duration, remove current floor from queue, transition toDoorsOpen. - DoorsOpen: wait
door_open_durationto allow boarding/exiting, then transition toDoorsClosing. - DoorsClosing: wait
door_transition_durationand then transition toIdle(or to movement if queue remains).
Purpose: assign waiting people (PersonElevatorRequest) to cars and enqueue stops.
Behavior:
- For each waiting person: find cars for the requested shaft and assign to a car using the first-available algorithm.
- Add both call floor and destination floor to the assigned car's
stop_queue(maintain ordering). - Update
wait_timeonPersonElevatorRequestwhile waiting.
Future: replace first-available with direction-aware algorithms (SCAN/LOOK) or cost-based assignment.
Purpose: handle boarding and exiting when doors are open.
Behavior:
- Boarding: when person is assigned to car and car is in
DoorsOpenat call floor and has capacity:- Transition person to
InElevatorand setcar_entity_id. - Increment
current_occupancyand add passenger destination to car'spassenger_destinations/stop_queue. - Reset person's
wait_time.
- Transition person to
- Exiting: when person is in elevator and car is in
DoorsOpenat person's destination:- Update person's
current_floor, decrement occupancy, remove their destination, removePersonElevatorRequest, and transition toWalkingorAtDestination.
- Update person's
Runs at a slower interval (e.g., 10s) to log car states, floors, occupancy, and queues for debugging and analytics.
- When a
Personneeds to change floors, the enhanced person waiting system creates aPersonElevatorRequestand finds suitable shafts. - If the person is not located at the shaft column, they will walk to the shaft (transition to
Walking) and then wait. - If no shaft is available, fallback simulation uses the legacy timed elevator behavior (simulated wait/travel) to preserve demo compatibility.
- The elevator implementation is backward-compatible and incrementally adoptable.
Visual cues help debugging and understanding elevator behavior:
- Shaft rendering: draw a vertical column per served floor with background and border.
- Car rendering: draw a rectangle positioned using
current_floorand color-coded by state. - Occupancy overlay: show current occupancy as a small number or bar on the car.
- Door indicators: draw door slats when opening/open.
Example snippets (Raylib-like):
// Shaft background
DrawRectangle(x + 4, y + 4, width - 8, height - 8, Color{60,60,70,255});
DrawRectangleLines(x + 4, y + 4, width - 8, height - 8, Color{100,100,120,255});
// Car draw at float position
int yPos = grid_offset_y + (int)(car.current_floor * cell_height);
DrawRectangle(x + 6, yPos + 6, width - 12, cell_height - 12, state_color);
// Occupancy
DrawText(TextFormat("%d", car.current_occupancy), x + 18, yPos + 14, 16, BLACK);Use src/elevator_demo_app.cpp to exercise the elevator system in isolation. The demo shows multiple shafts, cars, and people interacting; it renders a live status panel and can automatically save a screenshot.
Run (example, adapted to your environment):
cd build
# On headless CI use a virtual framebuffer; on Windows run the demo directly
xvfb-run -a ./bin/elevator_demo_appScreenshot: docs/elevator_demo_screenshot.png.
Create a shaft and car and a person who uses the elevator:
// Create elevator shaft at column 10, serving floors 0-5
auto shaft = ecs_world.CreateEntity("MainElevator");
shaft.set<ElevatorShaft>({10, 0, 5, 1});
// Create elevator car
auto car = ecs_world.CreateEntity("Car1");
car.set<ElevatorCar>({
static_cast<int>(shaft.id()),
0, // start at ground floor
8 // capacity: 8 passengers
});
// Create person who will use elevator
auto person = ecs_world.CreateEntity("Alice");
Person alice("Alice", 0, 2.0f);
alice.SetDestination(5, 10.0f, "Going to work");
person.set<Person>(alice);Person lifecycle: walk to shaft → wait → board → ride → exit → walk to destination.
- Elevator cars move between floors and stop at requested levels (smooth movement at configured speed).
- Persons can use elevators to travel vertically, respecting capacity and queueing rules.
- System supports stop queues, passenger destination tracking, and basic scheduling.
- Documented and demoed via
src/elevator_demo_app.cpp.
Testing notes:
- Demo runs and saves screenshots; visual checks validate state transitions and boarding.
- Logging system provides periodic debug output to verify queue and state behavior.
- Stop queue insertions maintain sorted order for efficient next-stop selection.
- Entity lookups cached when possible to reduce overhead.
- State updates performed only when queue or timers require it.
- Designed to support future scheduling algorithms and group control features.
include/core/components.hpp— addedElevatorShaft,ElevatorCar,PersonElevatorRequestsrc/core/ecs_world.cpp— added elevator systems and enhanced person waiting systemsrc/elevator_demo_app.cpp— demo app for elevator systemdocs/elevator_demo_screenshot.png— demo outputdocs/ELEVATOR_SYSTEM.mdanddocs/ELEVATOR_IMPLEMENTATION_SUMMARY.md— historical split docs (marked deprecated)
- Smart scheduling (SCAN/LOOK, direction-aware algorithms)
- Group elevator control and load balancing
- Express elevators and priority passengers
- Maintenance modes and analytics
- Integration with satisfaction, economics, and HUD systems
The elevator system is implemented with realistic behavior, integrates with existing person movement, includes rendering and demo coverage, and is ready for further improvements. The split implementation docs have been merged into this canonical file; the originals are kept for history and can be archived or removed from the working tree.
This file consolidates the full elevator documentation. The old split files can be removed from the working tree once you confirm links have been updated.