-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Idleology uses a layered structure that separates Discord command handling from game logic, UI, and persistence. This organization developed alongside the many systems in the game.
The project is primarily vibe-coded: design principles are generally followed and have proven useful for maintainability, but there are inconsistencies and legacy patterns in places. This page simply describes the architecture as it exists.
cogs/ → Discord command handlers (primarily thin entry points)
core/ → Game logic, models, UI views, and mechanics
base_view.py → Base class used by most Discord views
models.py → Backward-compat shim re-exporting dataclasses (see combat/items/settlement/partner models)
util.py
images.py → Central image URL handling
npc_voices.py
[module]/
mechanics.py / logic.py → Business logic and calculations
views.py → Primary discord.ui.View classes (simpler modules)
views/ → View subdirectory (used in complex modules)
list_view.py, detail_view.py, gear_view.py, modals.py, ...
upgrades/ → Upgrade flow views
ui.py / <module>.py → Stateless embed and component builders
data.py → Asset / lookup data
items/
models.py → Equipment dataclasses (Weapon etc.)
factory.py → DB rows → equipment dataclasses
equipment_mechanics.py → Forge, refine, temper, imbue, potential, etc.
essence_mechanics.py
essence_views.py
combat/ → Combat engine + Player model (subdivided)
database/
__init__.py → DatabaseManager (single entry point, exposes repositories)
base.py → BaseRepository
repositories/ → SQL code lives here
assets/ → Game data (monsters.csv, partners.csv, exp tables, etc.)
scripts/ → One-off tools (image handling, migrations, audits)
Guiding idea: Keep cogs light. Put gameplay logic and views in core/. Keep all SQL in database/repositories/.
Most views inherit from core/base_view.py:BaseView (rather than discord.ui.View directly).
Key points:
- Normal views:
BaseView(bot, user_id=..., server_id=...) - Child / sub-views:
BaseView(bot, parent=parent_view)to inherit identity - Supplies
self.bot, user/server IDs,interaction_check(), and timeout cleanup that clears active state viastate_manager - After sending a response, code usually does
view.message = await ...
Complex areas split code:
-
core/inventory/:inventory.py(stateless builders) +views/+upgrades/ -
core/settlement/views/: multiple focused files (construction, black_market, dashboard, plots, etc.) -
core/combat/:calc/,turns/,mobgen/,economy/,ui/,views/,dojo/ - Similar splits appear in
partners/,alchemy/,character/,codex/,apex/, etc.
Stateless UI building is normally kept in separate files (ui.py, inventory.py, etc.) rather than inside View classes.
When a file grows large or a distinct sub-feature appears, splitting is common.
- Register commands and act as thin coordinators.
- Common pattern: check state, defer, fetch data via
bot.database.*, construct a view from core, send it. - A few simpler or legacy View classes are defined directly inside cogs (inheriting BaseView).
-
models.py: backward-compat re-export shim. Actual dataclasses live incore/combat/models.py(Player),core/items/models.py, etc. No DB calls in models. -
<module>/mechanics.py(or logic.py): functions that implement rules. - Views extend BaseView.
- Equipment is usually built via
core/items/factory.py. -
core/combat/is a larger self-contained subsystem.
- All raw SQL is in
database/repositories/. - Access:
bot.database.users,bot.database.equipment,bot.database.settlement,bot.database.partners,bot.database.slayer,bot.database.codes,bot.database.maw, etc. (seedatabase/__init__.pyfor the full current list). - Writes are typically followed by
await repo.commit(). - Currencies were migrated to a dedicated
player_currenciestable (runes, keys, tomes, curios, fragments, etc.). Access and mutations go through users repo helpers (modify_currency, etc.) rather than the main user row.
-
Player (re-exported from
core/models.py; definition incore/combat/models.py): central dataclass. Holds level/stats/gear (populated via factory), companions, partners, monster parts (Consume), alchemy passives, codex state, ascension, slayer data, settlement context, combat transients, mastery fields, and more. Most consumable currencies (runes, keys, fragments, curios, etc.) live outside the Player dataclass in theplayer_currenciestable. - Equipment:
Weapon,Armor,Accessory,Glove,Boot,Helmet(plus essences). Built viacore/items/factory.pyand models now live incore/items/models.py. - Others:
Companion,Partner,MonsterModifier,CodexTome,Settlement,Building, delve state, etc. - Note:
core/models.pyis now a backward-compat shim that re-exports from domain modules (combat/models,items/models,settlement/models,partners/models).
core/combat/ is broken into focused areas:
-
calc/— math for hits, damage, crit, ward, etc. -
turns/— turn engine, player/monster actions, passives, jewels. -
mobgen/— encounters and modifier data. -
economy/— rewards, XP, drops, victory handling. -
ui/— embed builders. -
views/— the many interactive UIs (regular, elemental, dojo, multiple uber variants, warnings...). -
dojo/— training dummy support.
- Ascent, Codex, Uber Bosses, Maw (weekly boss)
- Settlement (buildings, workers, Black Market, projects, plots, Zeal, DT, Nursery, Idlem Foundry, Uber Shrine)
- Partners (gacha, dispatch, affinity, boss parties)
- Consume / Hematurgy + Hatchery
- Slayer (tasks + Mastery Tree)
- Alchemy (synthesis + distillation passives)
- Apex (hunts + Soul Stones)
- Delve, Journey, Prestige (cosmetic), Quests, Gathering skills (with mastery), PvP, Curios, Events, Minigames, Trade, Ideology, Companions (incl. mastery)
- Codes / redeem system (flexible reward codes granting currencies and items)
- Fetch player data then use factory functions to attach equipped gear.
- Child views use
parent=to avoid repeating IDs. - State-changing buttons usually use a
_processingflag to avoid re-entrancy. - Top-level interactive features use
state_manager.set_active/clear_active. -
BaseView.on_timeouthelps with cleanup. - Modifiers and passives are generally handled through registries rather than hardcoded per monster.
- New images/assets are processed via the tools and scripts under assets/.
- Schema change in
database/schema.sql+ repository methods. - Model updates (usually
core/models.pyor module-local). - Logic in
<module>/mechanics.py. - Views extending BaseView + any stateless builders.
- Thin command handler in a cog.
- State management around long-running interactions.
- Update asset pipelines if new visuals are involved.
Reference areas that demonstrate current factoring: core/inventory/, core/combat/, core/settlement/.
Changes that fit the style of nearby code tend to integrate cleanly.
Test changes by running the bot locally.
See the main README.md for setup instructions.
Last updated: June 2026 — synced with currency migration (player_currencies table), new codes repo + /redeem_code, models reorganization (shim + domain splits), settlement view logic refactors, and other June changes. The project follows the layering in spirit.