Nebula4X is an open-source, turn-based space 4X prototype in C++20, inspired by the genre of deep, logistics-heavy games (fleet ops, industry, colonies, research).
Not affiliated with Aurora 4X or its authors. This codebase is written from scratch; please don’t copy proprietary assets, data, or text from other games.
- Star systems, orbital bodies, ships, colonies, minerals, installations
- Fleets: persistent ship groups (same-faction) for bulk order issuing + basic formation/cohesion logic
- Faction AI profiles: optional basic AI can generate orders for idle ships (pirate raiders / explorers)
- Cargo holds on ships + mineral transfer orders (prototype logistics)
- Fuel: refineries can convert minerals into fuel; ships consume fuel when moving; colonies can stockpile fuel.
- Power (prototype): reactors generate power, some components draw power, and subsystems load-shed deterministically when power is insufficient.
- Day-based turn advancement
- Colony population growth/decline (configurable)
- Habitability & habitation infrastructure (prototype): colonies compute a simple habitability score from body temperature + atmosphere; hostile worlds require "Infrastructure" (habitation capacity) to prevent population decline; terraforming improves habitability
- Shipyard repairs: docked ships repair HP at friendly colonies with shipyards (configurable)
- Shipyard construction (optionally) consumes minerals per ton built (see
data/blueprints/starting_blueprints.json) - Colony construction queue: build installations using construction points + mineral build costs (also configured in JSON)
- Installation targets (auto-build): set desired installation counts per colony; the sim auto-queues construction to reach them
- Orders:
- move-to-point / move-to-body
- orbit body (station keep)
- travel via jump point (multi-system travel)
- attack ship (simple targeting)
- wait days (simple scheduling)
- load/unload minerals (prototype cargo logistics)
- salvage wrecks (recover minerals from destroyed ships)
- auto-freight minerals when idle (optional ship automation; routes supplies from surplus colonies to stalled queues)
- Per-colony mineral reserves: protect local stockpiles from auto-freight exports (UI configurable)
- ship-to-ship cargo transfer
- scrap ship (decommission at a colony; refunds some minerals)
- repeat orders (optional looping of a ship's queue for trade routes/patrols)
- order templates (saved library of named order queues you can apply to ships/fleets)
- Jump points + multi-system state
- Sensors + intel: in-system detection + last-known contact snapshots (saved)
- Stealth signatures (prototype): ship designs have a signature multiplier (derived from components) that scales effective detection range (lower signature = harder to detect).
- EMCON sensor modes: ships can run sensors in Passive/Normal/Active modes; this changes sensor range and detectability at runtime.
- Exploration: factions track discovered star systems; entering a new system reveals it
- Research system:
- tech definitions (JSON)
- research points generation (via
research_labinstallations) - active research + queue
- effects (unlock component / unlock installation)
- Basic combat prototype:
- armed ships auto-fire once/day at hostiles within weapon range
- damage + ship destruction
- destroyed ships can leave salvageable wrecks (optional; configurable)
- JSON save/load (versioned)
- Persistent event log (saved): build/research/jump/combat notifications
- Galaxy map (multi-system view)
- Right click a system in the galaxy map to auto-route the selected ship via jump points (Shift queues)
- Ctrl+Right click a system in the galaxy map to auto-route the selected fleet (Shift queues)
- System map (pan/zoom)
- Ctrl+Left click in the system map to issue move/jump/body orders to the selected fleet (Shift queues)
- Ship list + selection (shows HP, faction)
- Fog-of-war toggle (hides undetected hostiles and undiscovered systems)
- Contacts tab: recently seen hostiles + quick actions
- Diplomacy tab: view/edit faction stances (Hostile / Neutral / Friendly) that gate auto-engagement
- issuing an Attack order against a non-hostile faction will automatically set the stance to Hostile once contact is confirmed
- Log tab: view/filter/clear the saved event log; copy visible entries; export CSV/JSON
- Jump point markers on the system map
- Wreck markers on the system map (salvageable debris)
- Ship tab: quick orders (move, jump travel, attack) + cargo load/unload
- Wreck salvage: queue salvage orders for known wrecks
- Automation: optional Auto-explore when idle toggle (seeks frontier + jumps into undiscovered systems)
- Automation: optional Auto-freight minerals when idle toggle (hauls minerals to relieve shipyard/construction stalls and meet colony stockpile targets)
- Order queue editor: drag+drop reorder, duplicate/delete
- Order templates library: save/apply/rename/delete; apply to ship or selected fleet
- Fleet tab: create/rename/disband fleets; add/remove ships; set leader; issue bulk fleet orders (move/orbit/travel/attack/load/unload)
- toggle repeat orders for simple looping routes
- Colony tab: manage shipyard queue + build installations via construction queue
- Economy window: global Industry / Mining / Tech Tree overview (View → Economy)
- Colony tab supports editing mineral reserves, stockpile targets, and installation targets (auto-build)
- Research tab: choose projects, queue, see progress; set faction control/AI profile
- Tech browser: search/filter all techs (known / locked / researchable)
- Research plan preview: shows prerequisite chain + total cost
- Queue with prerequisites: auto-adds missing prereqs to the research queue
- Design tab: build custom ship designs from unlocked components
- Headless simulation runs
- Optional save/load
- Start a new game from either the built-in Sol scenario or a seeded random scenario
- Content validation helper (
--validate-content) for blueprint/tech modding - Save canonicalizer (
--format-save) to re-serialize JSON with stable ordering - Event log dump (
--dump-events) to print saved simulation events - Event log export to CSV (
--export-events-csv PATH) for spreadsheets/analysis (PATHcan be-for stdout) - Event log export to JSON (
--export-events-json PATH) for tooling/analysis (PATHcan be-for stdout) - Event log export to JSONL/NDJSON (
--export-events-jsonl PATH) for streaming tools (PATHcan be-for stdout) - Event log filters:
--events-last,--events-category,--events-level,--events-faction,--events-system,--events-ship,--events-colony,--events-contains,--events-since,--events-until - Event log summary:
--events-summary(counts by level/category) for the filtered set - Event log summary export:
--events-summary-json PATH(PATHcan be-for stdout) - State export to JSON:
--export-ships-json PATH--export-colonies-json PATH--export-fleets-json PATH--export-bodies-json PATH(PATHcan be-for stdout)
- Tech tree export:
--export-tech-tree-json PATH(definitions)--export-tech-tree-dot PATH(Graphviz DOT) (PATHcan be-for stdout)
- Research planner:
--plan-research FACTION TECH(prints a prereq-ordered plan)--plan-research-json PATH(optional machine-readable plan;PATHcan be-for stdout)
- Time warp:
--until-event Nto advance day-by-day until a new matching event occurs (defaults to warn/error; configurable via--events-*) --quietto suppress non-essential summary/status output (useful for scripting)- Script helpers:
--list-factions,--list-systems,--list-bodies,--list-jumps,--list-ships,--list-colonies(print ids/names, then exit)
- Tiny built-in runner for deterministic core logic
- CMake 3.21+
- A C++20 compiler (MSVC 2022, clang 15+, gcc 12+)
Optional UI dependencies:
- SDL2 (tries
find_package(SDL2)first; falls back to FetchContent) - Dear ImGui (fetched via CMake for the UI target)
The core uses small in-repo utilities for JSON (save/load + content files) and logging.
git clone <your repo>
cd nebula4x
# Core + tests only
cmake -S . -B build -DNEBULA4X_BUILD_UI=OFF -DNEBULA4X_BUILD_TESTS=ON
cmake --build build --config Release
# Or build UI too (requires SDL2)
cmake -S . -B build -DNEBULA4X_BUILD_UI=ON -DNEBULA4X_BUILD_TESTS=ON
cmake --build build --config ReleaseIf you have a recent CMake, you can use the included CMakePresets.json:
# Core + tests (no UI, isolated/headless build dir to avoid IDE contention)
cmake --preset core-tests-headless
cmake --build --preset core-tests-headless --config Release
ctest --preset core-headless -C Release
# Note: in Visual Studio debugger, some tests intentionally trigger and catch
# exceptions (first-chance). If `nebula4x_tests.exe` exits with code 0, tests passed.
# Windows helper with isolated per-test execution + timeout guard:
powershell -ExecutionPolicy Bypass -File .\tools\run_tests.ps1 -BuildFirst -PerTestTimeoutSeconds 180
# (`run_tests.ps1` stops stale `nebula4x_tests.exe`, runs tests one-by-one, and kills timed out tests)
# It also stops orphaned cmake/ninja/msbuild processes older than 90s by default.
# Build/test scripts now run without a mutex by default to avoid lock-wait stalls.
# Enable mutex when needed: -UseBuildMutex
# Enforce lock acquisition (fail instead of continue): -BuildLockRequired
# Optional hard cap for total script runtime: -MaxTotalSeconds N
# Default test runtime log level is `error` to keep output clean; override with:
# powershell -ExecutionPolicy Bypass -File .\tools\run_tests.ps1 -BuildFirst -LogLevel warn
# Quick help (returns immediately; does not require built test binaries):
# powershell -ExecutionPolicy Bypass -File .\tools\run_tests.ps1 -?
# Disable orphan-process cleanup if you're running another build in parallel:
# powershell -ExecutionPolicy Bypass -File .\tools\run_tests.ps1 -BuildFirst -KillOrphanedBuildTools:$false
# Optional: stop at first failing test (faster triage)
powershell -ExecutionPolicy Bypass -File .\tools\run_tests.ps1 -ContinueOnFailure 0
# Optional: machine-readable report
powershell -ExecutionPolicy Bypass -File .\tools\run_tests.ps1 -BuildFirst -JunitPath out\test-results\nebula4x_tests.xml
# If PowerShell execution policy blocks scripts:
.\tools\run_tests.cmd --filter simulation
# (`run_tests.cmd` invokes the same isolated/timeout-safe runner path)
# Fast core + CLI only (no UI, no tests)
cmake --preset core
cmake --build --preset core --config Release
# (build preset `core` targets only `nebula4x_cli` for fast feedback)
# (MSVC builds print per-file timing/progress by default)
# Windows helper (watchdog + mutex + stale-process cleanup; optional clean retry via -RetryCleanOnFailure)
powershell -ExecutionPolicy Bypass -File .\tools\build_core.ps1 -Configure
# Quick help (returns immediately; does not start configure/build):
# powershell -ExecutionPolicy Bypass -File .\tools\build_core.ps1 -?
# (`build_core.ps1` also stops a running target process by default to avoid LNK1104 file-lock errors)
# It also stops orphaned cmake/ninja/msbuild processes older than 90s by default.
# Build/test scripts run without a mutex by default; enable when needed with -UseBuildMutex.
# If mutex is enabled, require lock acquisition with -BuildLockRequired.
# Optional hard cap for whole script runtime: -MaxTotalSeconds N
# Optional watchdog tuning for slow/fragile systems:
# powershell -ExecutionPolicy Bypass -File .\tools\build_core.ps1 -Configure -BuildTimeoutSeconds 3600 -ConfigureTimeoutSeconds 900
# Disable orphan-process cleanup if you're running another build in parallel:
# powershell -ExecutionPolicy Bypass -File .\tools\build_core.ps1 -Configure -KillOrphanedBuildTools:$false
# Convenience wrapper with sane defaults for core-tests target:
# .\tools\build_core.cmd
# If you still need nested PowerShell -Command, use safe quoting:
# C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command "& { powershell -NoProfile -ExecutionPolicy Bypass -File .\tools\build_core.ps1 -Preset core-tests-headless -Target nebula4x_tests -Config Release -Configure -BuildTimeoutSeconds 600 -WatchdogSeconds 15 -KillOrphanedBuildTools -OrphanedToolMinAgeSeconds 1 -EmitScriptRc }"
# UI + core + tests (isolated/headless build dir)
cmake --preset ui-headless
cmake --build --preset ui-headless --config Release
# Main executable dependency wiring check (single target):
# - always builds nebula4x
# - also builds nebula4x_tests when tests are enabled in the preset
cmake --preset ui-headless
cmake --build --preset ui-main-all-headless --config Release
# UI runtime only (no tests; fastest/stablest way to build nebula4x.exe)
cmake --preset ui-runtime-headless
cmake --build --preset ui-runtime-headless --config Release
# Windows convenience wrapper:
# .\tools\build_game.cmd
# (default target is nebula4x_main_all for dependency wiring sanity checks)
# (fast-path: skips rebuild when nebula4x.exe already exists and no forwarded build args are provided)
# (use -ForceBuild to force rebuild; use -MaxTotalSeconds N for a hard wrapper timeout)
# Real UI runtime build with dependency fetch (requires network access):
cmake --preset ui-runtime-fetchdeps
cmake --build --preset ui-runtime-fetchdeps --config Release
# Wrapper equivalent:
# .\tools\build_game.cmd -FullUI -ForceBuild
# (in FullUI mode, wrapper runs a quick preflight and exits 125 if neither
# local SDL2 config nor github.com:443 connectivity is available)
# UI-configured test target only (safer/faster than building every UI target)
cmake --preset ui-tests-only-headless
cmake --build --preset ui-tests-headless --config Release
# Windows watchdog wrapper for UI-configured tests (kills stale cmake/ninja/msbuild)
powershell -ExecutionPolicy Bypass -File .\tools\run_tests.ps1 -Preset ui-tests-headless -BuildFirst -PerTestTimeoutSeconds 180Run:
# UI
./build/nebula4x
# If UI deps are unavailable, the fallback launcher prints a clear reason and exits with code 0.
# Use `./build/nebula4x --require-ui` to force a non-zero exit when UI is required.
# CLI (Sol scenario)
./build/nebula4x_cli --days 30
# (`nebula4x_cli` is batch/non-interactive and exits when finished; exit code 0 means success)
# CLI (random scenario)
./build/nebula4x_cli --scenario random --seed 42 --systems 12 --days 30
# CLI (validate content files)
./build/nebula4x_cli --validate-content
# CLI (canonicalize a save file)
./build/nebula4x_cli --format-save --load save.json --save save_canonical.json
# CLI (dump recent warning/error events)
./build/nebula4x_cli --days 30 --dump-events --events-last 50 --events-level warn,error
# CLI (event log summary for scripts/analysis)
./build/nebula4x_cli --days 30 --events-summary --events-level warn,error
# CLI (summary of warn/error events in a date range)
./build/nebula4x_cli --days 365 --events-summary --events-level warn,error --events-since 2200-01-01 --events-until 2200-12-31
# CLI (export event log to CSV)
./build/nebula4x_cli --days 30 --export-events-csv events.csv --events-level all
# CLI (export event log to JSON)
./build/nebula4x_cli --days 30 --export-events-json events.json --events-level all
# CLI (export event log to JSONL/NDJSON)
./build/nebula4x_cli --days 30 --export-events-jsonl events.jsonl --events-level all
# CLI (export JSON to stdout for scripting; suppress other output)
./build/nebula4x_cli --load save.json --quiet --export-events-json - --events-level warn,error
# CLI (script-friendly export, no summary output)
./build/nebula4x_cli --load save.json --quiet --export-events-csv events.csv --events-level warn,error
# CLI (list factions in a save)
./build/nebula4x_cli --load save.json --list-factions
# CLI (list systems in a save)
./build/nebula4x_cli --load save.json --list-systems
# CLI (list bodies in a save)
./build/nebula4x_cli --load save.json --list-bodies
# CLI (list jump points in a save)
./build/nebula4x_cli --load save.json --list-jumps
# CLI (list ships in a save)
./build/nebula4x_cli --load save.json --list-ships
# CLI (list colonies in a save)
./build/nebula4x_cli --load save.json --list-colonies
# CLI (export ships/colonies state to JSON)
./build/nebula4x_cli --load save.json --quiet --export-ships-json ships.json
./build/nebula4x_cli --load save.json --quiet --export-colonies-json colonies.json
# CLI (export tech tree)
./build/nebula4x_cli --quiet --export-tech-tree-json tech_tree_flat.json
./build/nebula4x_cli --quiet --export-tech-tree-dot tech_tree.dot
# CLI (plan research)
./build/nebula4x_cli --load save.json --plan-research "United Earth" colonization_1
./build/nebula4x_cli --load save.json --quiet --plan-research "United Earth" colonization_1 --plan-research-json -
# CLI (time warp until next warning/error event, then save)
./build/nebula4x_cli --until-event 365 --save autosave.json
# CLI (time warp from an existing save, script-friendly)
./build/nebula4x_cli --load save.json --quiet --until-event 365 --save save_after.json
# tests
ctest --test-dir build
# direct test runner with per-test output + heartbeat for long-running tests
out/build/core-tests-vs/Release/nebula4x_tests.exe --verbose --heartbeat-seconds 10
# direct test runner for one exact test name
out/build/core-tests-vs/Release/nebula4x_tests.exe --verbose --exact simulation --heartbeat-seconds 10Using vcpkg makes SDL2 detection painless:
vcpkg install sdl2
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=<path-to-vcpkg>/scripts/buildsystems/vcpkg.cmake
cmake --build build --config ReleaseIf you ever see a linker error like LNK2019: unresolved external symbol main when building the UI,
it's usually SDL redefining main to SDL_main. This repo opts out of that behavior and calls
SDL_SetMainReady() before SDL_Init() so MSVC links cleanly.
include/nebula4x/public headerssrc/core/simulation implementationsrc/ui/UI implementationdata/JSON content (tech + blueprints)docs/design notes
- More granular ship components (power, fuel, heat, maintenance)
- Better galaxy view + exploration mechanics (surveying, unknown exits, exploration orders)
- More combat depth (initiative, tracking, missiles, armor layers)
- Multi-faction diplomacy and intel
- Data-driven mod support (hot reload, content packs)
MIT. See LICENSE.
See THIRD_PARTY_NOTICES.md for dependency licenses.