Overview
This genre pack targets casual games — the low-barrier, short-session, broadest-reach corner of the medium (the largest player base by reach in the genre taxonomy, Casual & Party family). That family spans four flavors: casual (light, mass-market loops), hypercasual (one-thumb, instantly-understood mechanics), idle / incremental (clickers that play themselves), and party (social multiplayer minigames).
Of these, this pack centers on the idle / incremental loop, because it is the richest UGAS
showcase: its signature mechanic — exponential economic growth — is exactly the core modifier
Channel mechanism (additive within a channel, multiplicative across channels) driving a periodic
passive-income effect. Idle games turn UGAS’s attribute pipeline into the entire game. The same
pieces generalize directly to the energy- / lives-gated loops that define the rest of casual: the
energy gate here is the same cost-gated-ability pattern a hypercasual "play a round" button or a
match-3’s "lives" system uses.
Unlike the Platformer, Racing, and ARPG packs, the core specification ships no dedicated casual case
study, so this pack is designed from first principles. It still leans entirely on core constructs —
the modifier Channel mechanism (core spec §5.3) for income aggregation, a
periodic Infinite effect (§9.3) for the income tick, an AttributeBased magnitude (§9.4.2) so
that tick pays out the live income rate, a custom ExecutionCalculation (§9.5) for offline progress,
and effect-granted tags (§7.5) for the meta-progression state machine.
Relationship to the core specification
This document is additive. It defines genre-specific Attributes, Tags, Abilities, and Effects on top of the core Universal Gameplay Ability System specification.
-
It MUST NOT redefine, override, or contradict any concept in the core spec.
-
All entities in
entities/validate against the sameschemas/*.jsonas the core. -
It reuses the core lifecycle tag (
State.Alive) by reference — the Idle action set activates while the profile is alive — and adds casual-specific states (Meta.State.Prestiged,Booster.State.DoubleIncome, …). -
Meta-progression state is mutated only through Effects (core spec §7.5) — abilities gate on tags and apply Effects, never write tags directly — and the income stacking is the core modifier
Channelmechanism, not a new construct.
Genre Attributes
Defined in entities/attribute_set.yaml as the IdleEconomySet set. The base values describe a
fresh save — zero income, full energy, run one — so the set is playable as shipped.
| Attribute | Category | Role |
|---|---|---|
|
Resource |
Soft currency the loop accumulates; clamped |
|
Statistic |
The aggregated passive-income rate — driven by the flat |
|
Statistic |
Display of the |
|
Statistic / Resource |
|
|
Statistic |
Run progression — current world and active-area tier; advanced by milestones and reset on prestige. |
|
Meta |
Total earned this run; the engine compares it against the prestige threshold to grant |
|
Meta |
Elapsed real time since the session was last seen; read by |
Exponential economic growth (the core idle mechanic)
An idle game lives or dies on its growth curve, and in UGAS that curve is the modifier pipeline
itself. The whole economy lands on one attribute — CurrencyPerSecond — which a periodic effect
then pays into Currency every tick.
Income aggregation: flat Add subtotal multiplied by two channels
CurrencyPerSecond is the showcase of the core Channel mechanism. Recall the pipeline (§5.3): flat
Add modifiers sum first, then each Multiply channel contributes an effective factor of
\(1 + \sum m_k\), and those channel factors multiply across each other. The idle economy
maps cleanly onto this:
| Source | What goes in it | Stacking |
|---|---|---|
Generators |
Flat |
Additive (flat sum — not a channel) |
|
|
Additive within, multiplied across the others |
|
|
Additive within, multiplied across the others |
Generators contribute flat income, so N of them sum in the additive pass — GE_Generator_Mine
(entities/effect_generator_mine.yaml) adds \(+5\), GE_Generator_Factory adds
\(+50\). Prestige and boosters each live in their own Multiply channel, so they multiply
across the generator total rather than diluting into it — which is exactly what produces the
runaway big-number growth idle players chase.
entities/gameplay_controller.yaml)A save with one generator’s worth of income, after a single prestige:
The base of 0 matters: because generators use flat Add, the channels multiply a non-zero
subtotal (here 50), so the arithmetic stays clean — a generator-less save earns nothing, exactly as
intended. The worked controller drives this further with three mines, a factory, and a double-income
booster active at once (see Periodic passive income).
Multiple modifiers within one channel
The "additive within a channel" half of the rule is what lets prestige tiers compound smoothly:
two GE_PrestigeBoost instances of \(+2.0\) in the Prestige channel yield
\(1 + 2.0 + 2.0 = 5.0\times\), not \(3.0 \times 3.0 = 9.0\times\) — additive within the
channel, so prestige power scales predictably rather than exploding. PrestigeMultiplier mirrors the
channel factor for display.
Periodic passive income
GE_PassiveIncome (entities/effect_passive_income.yaml) is the heartbeat of the loop: an Infinite
effect with Period: { Period: 1.0 }, which behaves like an Instant effect fired once per second
(§9.3), permanently adding to the Currency base value each tick. The amount is not static — it is
the live, fully-aggregated CurrencyPerSecond — so the magnitude is AttributeBased (§9.4.2) with
BackingAttribute: CurrencyPerSecond:
As generators and prestige push CurrencyPerSecond up, every tick automatically pays out more, with
no change to the effect itself. For the worked save — three mines (\(3 \times 5 = 15\)) plus a
factory (\(+50\)) = \(65\) flat, the Prestige channel (\(\times 3.0\)), and
the Booster channel (\(\times 2.0\)):
These are exactly the CurrentValue entries recorded for the example profile.
The energy gate
Active casual play is rationed by energy — the same lever as a match-3’s lives or a hypercasual
"plays remaining". GA_Play (entities/ability_play.yaml) declares a Cost effect (GE_PlayCost,
an Energy subtraction). Because an ability cannot activate if it cannot pay its cost, an empty
Energy pool simply blocks play — no explicit energy-check tag is needed. This is the exact
analogue of the Shooter pack’s ammo gate (GA_Fire cannot fire on an empty magazine); here the
"magazine" is energy and it refills on a timer rather than on reload.
The refill is GE_EnergyRegen (entities/effect_energy_regen.yaml): an Infinite + Period effect
that adds Energy every few seconds, capped by the attribute’s own [0, MaxEnergy] clamp. GA_Play
is additionally blocked while Session.State.OutOfEnergy so the UI can present a refill prompt
instead of a silent failure. GE_PlayCost is trivial (a flat resource cost) and is referenced by
name rather than shipped as a file, the same convention the Racing and Shooter packs use for their
cost/cooldown effects.
Genre Tags
Defined in entities/tag_registry.yaml (additive only):
-
Meta-progression states —
Meta.State.PrestigeReady(threshold gate for prestige),Meta.State.Prestiged(granted byGE_PrestigeBoost). -
Booster states —
Booster.State.DoubleIncome(granted byGE_DoubleIncome). -
Generator classification —
Generator.Type.Mine|Factory|Bank(AllowMultiple, so the engine can count installed generators). -
Ability types —
Ability.Type.Tap|Buy|Prestige|Play. -
Session state —
Session.State.OutOfEnergy.
Genre Abilities
-
entities/ability_tap.yaml—GA_Tap: the active click; appliesGE_TapReward(+Currency). No cost, no cooldown — the lowest-barrier interaction. -
entities/ability_buy_generator.yaml—GA_BuyGenerator: spendsCurrency(Cost: GE_BuyGeneratorCost, referenced by name) and applies aGE_Generator_*, raisingCurrencyPerSecond. The cost gate prevents buying without enough currency. -
entities/ability_prestige.yaml—GA_Prestige: requires the threshold tagMeta.State.PrestigeReady; appliesGE_PrestigeBoost. The reset itself is documented as engine logic. -
entities/ability_play.yaml—GA_Play: spendsEnergy(Cost: GE_PlayCost); blocked whileSession.State.OutOfEnergy. The energy-gated active round.
Genre Effects
-
entities/effect_passive_income.yaml—GE_PassiveIncome:Infinite+Period;AttributeBased+CurrencyfromCurrencyPerSecondeach tick. -
entities/effect_generator_mine.yaml—GE_Generator_Mine:Infinite; flat+5CurrencyPerSecond; grantsGenerator.Type.Mine. -
entities/effect_generator_factory.yaml—GE_Generator_Factory:Infinite; flat+50CurrencyPerSecond; grantsGenerator.Type.Factory. -
entities/effect_prestige_boost.yaml—GE_PrestigeBoost:Infinite;Multiplyin thePrestigechannel onCurrencyPerSecondandPrestigeMultiplier; grantsMeta.State.Prestiged. -
entities/effect_energy_regen.yaml—GE_EnergyRegen:Infinite+Period;+Energyeach tick. -
entities/effect_double_income.yaml—GE_DoubleIncome:HasDurationreward; \(\times 2\)CurrencyPerSecondin theBoosterchannel; grantsBooster.State.DoubleIncome. -
entities/effect_offline_progress.yaml—GE_OfflineProgress:Instant; runs theExecCalc_OfflineProgressExecutionCalculationto pay accrued offline income intoCurrency. -
entities/effect_tap_reward.yaml—GE_TapReward:Instant; flat+Currency, the payload ofGA_Tap.
Engine seams
Three pieces are deliberately left to the adopting engine — the rest is data:
-
Prestige reset —
GA_Prestigetriggers the bookkeeping wipe (zeroCurrency, remove the generator effects, resetStage/Level, re-grantGE_PassiveIncome). UGAS captures the reward (GE_PrestigeBoost) and the gate; the wipe itself is engine logic. -
Threshold detection — attribute comparisons cannot be activation tags, so the engine watches
LifetimeCurrencyagainst the prestige requirement and grantsMeta.State.PrestigeReady(andSession.State.OutOfEnergywhenEnergyhits 0). -
ExecCalc_OfflineProgress— the idle "welcome back" payout readsCurrencyPerSecondandOfflineSecondsand writes a capped/discounted lump sum intoCurrency. This is the idle analogue of the Racing pack’s traction calculator and the Shooter pack’s hit-resolution calculator — the seam where the genre’s signature math plugs into UGAS.
Using this pack
-
Copy
genres/casual/into your project (or loadentities/directly via theugas-schema-authorskill). -
Tune the economy in
IdleEconomySetfirst — generator income values and the prestige magnitude set the whole growth curve — then add generator tiers as newGE_Generator_*effects and rewards asBooster-channel effects. -
Author new income modifiers by choosing the right home: per-generator income is flat
Add; permanent multipliers go in thePrestigechannel; timed multipliers in theBoosterchannel. Reserve anExecutionCalculationfor non-linear math like offline progress. -
Implement the engine seams (the prestige reset, threshold detection, and
ExecCalc_OfflineProgress); everything else is data. -
Add new states as
State./Meta.State.tags granted by Effects (never mutate tags directly), and new mechanics as Effects + Abilities. -
Validate with
python scripts/validate_schema_examples.pybefore committing.