Conquerors is an original single-player strategy roguelike prototype written in Odin with Raylib.
The player leads a Conqueror, places cards on a 5 by 5 Realm Grid, develops each card through its own Card Skill Tree, and defends the Realm from deterministic enemy armies.
The playable slice includes:
- One Conqueror: Ilyra Venn, Wardline Marshal
- Twelve cards across Troop, Structure, and Economy categories
- Four Skill Nodes per card with two branches and mutually exclusive capstones
- A 5 by 5 isometric Realm Grid
- Gold costs, income, placement rules, and adjacency decisions
- The Wardline passive for mixed-category formations
- Three normal enemy types, one elite, and one boss
- Ten deterministic Encounters
- Automatic fixed-tick ECS Battles with individual units
- Troop cards that deploy authored squads from their Realm Plots
- Enemy composition entries that expand into visible formations
- A separate Battle approach between the Realm and enemy staging area
- Enemy movement, stable targeting, health, attacks, and death
- Missing-health damage, structure-breaking, and command-aura abilities
- Twelve distinct geometric card constructions
- Original generated vector art for cards, enemies, and the Realm backdrop
- Card experience, Levels, Skill Points, and Skill Node unlocks
- Reward, Victory, Defeat, and restart states
- Content validation and deterministic simulation tests
Save data, audio, projectile entities, and Meta Progression are not part of this slice yet.
Runtime art lives in assets/generated. Editable SVG sources are kept beside the PNG atlases so the artwork can be reviewed and regenerated instead of existing as opaque binary output.
The game loads textures once after Raylib creates the graphics context. Card and enemy enum order maps directly to fixed atlas cells. Missing files, invalid dimensions, or changed enum order disable the affected atlas and use the geometric renderer instead.
See assets/README.md for atlas order, dimensions, provenance, and ImageMagick regeneration commands. The current pack was AI-authored for this project without external copied assets or artist-style prompts. Human art, similarity, licensing, accessibility, and legal review are still recommended before commercial release.
- Odin
dev-2026-06or a compatible newer build - Raylib from Odin's
vendorcollection - A desktop OpenGL environment
From the repository root:
odin run src| Input | Action |
|---|---|
| Left click a hand card | Select a card |
| Number keys 1 through 5 | Select a hand card |
| Left click a Plot | Place the selected card or inspect when no card is selected |
| Right click an occupied Plot | Inspect its card and Card Skill Tree |
| Left click a Skill Node | Attempt to unlock it |
| Enter | Begin the current Encounter |
| Space | Claim a Battle reward |
| R | Start a new Run after Victory or Defeat |
| WASD | Pan the camera |
| Middle mouse drag | Pan the camera |
| Mouse wheel | Zoom the camera |
Cards can only be placed on empty Plots allowed by their placement rule. Placing a card spends Gold. Economy cards add Gold when an Encounter begins.
Ilyra's Wardline passive uses orthogonal mixed-category links. Each linked card gains 1 Guard, up to 2 Guard. Troop formations gain 10% health from each adjacent Structure and 10% damage from each adjacent Economy card. Up to two mixed-category neighbors also add one deployed unit each. The Realm and card inspector show these links and their resulting Battle profile.
Check the application:
odin check src -vetRun deterministic simulation tests:
odin test src/sim -define:ODIN_TEST_THREADS=1 -define:ODIN_TEST_RANDOM_SEED=42Build an executable:
odin build src -out:conquerorssrc/sim is the authoritative gameplay package. It owns immutable content definitions, mutable Run state, Realm Grid rules, placement, progression, the Battle ECS, and validation. It does not import Raylib.
The root src package owns the window, camera, input mapping, and rendering. It sends player actions through procedures exposed by sim. Rendering reads Run state but does not define game rules.
Battle uses a fixed-capacity ECS with generation-safe entity handles and separate component arrays. Before Battle, each occupied Plot produces a deterministic Battle_Spawn_Profile from its card stats, squad metadata, Skill Nodes, and adjacency. Spawns and destruction are queued. Targeting, movement, attacks, damage, death, and Battle results run in a fixed order. Camera movement and rendering frame rate do not change Battle results.
Source files stay below 300 lines and are split by responsibility. Content definitions remain separate from mutable runtime entities. Rendering reads Battle_Entity_View values and never mutates ECS components.
src/
├── main.odin
├── renderer.odin
├── render_assets.odin
├── render_realm.odin
├── render_queue.odin
├── render_constructions*.odin
├── render_battle.odin
├── render_battlefield.odin
├── render_formations.odin
├── render_synergy.odin
├── render_hud.odin
├── ui.odin
├── ui_input.odin
├── ui_status.odin
├── ui_side_panel.odin
├── ui_hand.odin
└── sim/
├── battle.odin
├── battle_types.odin
├── battle_entities.odin
├── battle_spawn.odin
├── battle_formation.odin
├── battle_targeting.odin
├── battle_combat.odin
├── content_cards.odin
├── content_encounters.odin
├── content_skills_*.odin
├── content_lookup.odin
├── grid.odin
├── progression.odin
├── rng.odin
├── run.odin
├── *_test.odin
├── types.odin
└── validation.odin