Blind Effect
Blind Effect
Status: Designed Author: Nathan + game-designer Last Updated: 2026-04-07 System Index: Extension of Status Effect System (#7) and Enemy Data & AI (#6)
1. Overview
Blind is a status effect applied to the player that hides enemy intents for the duration of the effect. While blinded, the intent display for all living enemies is replaced with a concealment overlay — the player cannot see what any enemy will do on their next turn. Blind is a pure information denial mechanic: it does not change the dice, reduce damage, or alter scoring. The only thing it takes away is the player's ability to plan around incoming enemy actions. Blind lasts for exactly 1 turn by default, though specific sources can apply extended durations. The effect expires at the end of the player's scoring phase (before the enemy phase executes), meaning the player plays their hand without the information, and the reveal happens as enemies act — not before.
The system is introduced through the Merchant's POCKET_SAND action (shop combat)
and can appear on select interference-type enemies in later floors. It integrates
with the existing Status Effect System as a new TIMED debuff with a new
modifier_type of INFORMATION_DENY, and hooks into the Dice Combat UI's
intent rendering pipeline.
2. Player Fantasy
The terror of playing blind. Most of the game is about reading the battlefield — "the skeleton is attacking for 12, the shaman is about to heal, I should kill the shaman." Blind strips that away. For one turn, the player is flying without instruments.
The fantasy has two moments:
-
The panic moment — the intent icons go dark. The player has to make a decision with incomplete information. Do they prioritize the enemy most likely to deal damage? Kill the most dangerous target even without confirmation? Use a consumable as insurance? This engages the player's pattern recognition ("I know what this enemy type usually does") and tests their mental model of enemy behaviors.
-
The resolution moment — the player scores and commits. Then the enemy phase plays out. Finding out what was hidden is a small dramatic beat — relief if enemies did nothing devastating, dread if the hidden action was exactly what the player feared.
Secondary fantasy: counterplay mastery. Veteran players will know which relics counter blind and keep them specifically for floors where blinding enemies appear. Recognizing the Merchant's POCKET_SAND setup and having a Clarity Lens relic ready feels like reading an opponent.
Target MDA aesthetics: Challenge (primary — plays without information), Discovery (secondary — learning enemy behavior by heart to compensate), Fantasy (tertiary — the world pushes back in unexpected ways).
This mechanic does NOT serve Submission (relaxation). Blind is a tension spike, not a comfort mechanic. It should be used sparingly.
3. Detailed Design
3.1 Core Rules
- Blind is a status effect (
"blind") applied to the player, not enemies. - While blind is active (stacks > 0), all enemy intent displays are hidden.
- Blind hides intent only — enemy HP bars, shield values, and status effect icons on enemies remain fully visible. The player can still see how healthy enemies are and what statuses they carry; they just cannot see the action those enemies will take next.
- Blind uses
DurationType.TIMED. Duration is measured in player turns: the stack count decreases by 1 at the start of the player's phase (before the player rolls dice). - Blind stacks extend duration, they do not intensify effect. Applying Blind 2 to a player already at Blind 1 results in Blind 3 (3 turns hidden).
- When Blind expires (stacks reach 0), intent icons are immediately restored. The restore happens before the player rolls, so the player always enters their turn with full information unless they are currently blinded.
- Blind is a debuff (
is_debuff = true). Future cleanse mechanics (consumables, relics, shrine blessings) can remove it. - Multiple sources of Blind (e.g., Merchant + a Shadow Rogue in the same encounter) stack additively on duration. The player can accumulate multiple blind turns.
3.2 What Is Hidden vs. Visible During Blind
| Information | Blinded State | Visible State |
|---|---|---|
| Enemy HP bar | Visible | Visible |
| Enemy shield / block value | Visible | Visible |
| Enemy status effect icons (Burn, Freeze, etc.) | Visible | Visible |
| Enemy name label | Visible | Visible |
| Enemy intent icon | Hidden | Visible |
| Enemy intent tooltip (hover) | Hidden | Visible |
| Enemy intent value (damage number / heal amount) | Hidden | Visible |
| Targeting label ("will attack you for 12") | Hidden | Visible |
The hover tooltip is also suppressed while blind is active. The player cannot work around the visual by hovering — the information is simply unavailable.
3.3 Visual Treatment
Intent display during Blind:
- The intent icon slot is replaced with a solid "?" icon (or a closed eye icon, per art direction). Use the existing 1-bit art style.
- A subtle desaturated overlay (greyscale tint, ~30% opacity) appears over each enemy's intent area — not the whole enemy sprite, just the intent badge.
- The targeting label beneath each enemy reads: "???" instead of the normal action description.
- A status indicator on the player HUD shows the Blind debuff icon with the remaining stack count (same visual system as existing status icons).
Blind application animation:
- When Blind is applied, the intent icons "close" with a brief fade-to-grey animation (~0.3 seconds). This is not a screen-wide effect — only the intent badges animate.
- Optional: brief screen-edge darkening pulse (vignette flash, 1 frame) to communicate "something happened to you."
Blind expiry animation:
- At the start of the player's turn when stacks hit 0, intent icons "open" with a fast fade-in (~0.2 seconds).
- No fanfare. The reveal is understated — the icons just come back.
3.4 Enemy Usage — Who Can Blind?
Blind is a rare, high-value interference. It should feel notable when it appears, not routine. Placement follows the principle: blind appears on enemies whose thematic identity centers on deception, misdirection, or information warfare.
Tier 1 — Existing enemy: Merchant (POCKET_SAND)
Already defined in shop-combat-system.md. The Merchant applies Blind 1 with 20% action weight. This is the player's introduction to blind in a controlled context (a chosen fight with a known, special enemy).
Tier 2 — New interference-type enemies (recommended additions)
The following enemies are designed to carry Blind as their primary interference. These are proposals — the enemy database owner should review for balance fit:
| Enemy | Floor Range | Tier | Blind Mechanic | Other Actions |
|---|---|---|---|---|
| Shadow Rogue | 8-12 | Elite | SNEAK_ATTACK: Blind 1 + deal 8 damage (combined action) | STAB: 12 damage |
| Smoke Cultist | 5-8 | Basic | RITUAL_SMOKE: Blind 1 | CURSE: target one die |
| Blind Oracle | 11-15 | Elite | PROPHECY_VEIL: Blind 2 | WEAKEN: -20% player damage next turn |
| Arch Demon (Act 3 Boss) | Floor 15 | Boss | DREAD_AURA: Blind 1 on turn 2 of phase 2 | Full existing kit |
Design constraint: no more than 1 blinding enemy per encounter. The blind effect is disruptive enough that stacking it across multiple enemies in one fight would feel oppressive rather than interesting. If the encounter generator places multiple blinding enemies together, one of them should have its Blind action weighted out (set weight to 0 for that encounter slot).
Tier 3 — Arch Demon passive consideration
The Arch Demon's Phase 2 (boss-specific) can include a DREAD_AURA action that blinds for 1 turn. This is a thematic fit (Act 3 boss creating dread and uncertainty) and a late-game skill test. It should appear at most once per phase.
3.5 Counterplay
Blind is meaningful only if the player has counterplay options. The following counterplay vectors are designed into the system:
Intrinsic counterplay (no items required):
- Enemy behaviors are learnable. Veteran players who have memorized what Shadow Rogues and Smoke Cultists do can play optimally even without seeing the intent. Pattern AI enemies follow fixed sequences — a player who counts turns knows exactly what's coming.
- The player can still see enemy HP and statuses, so priority targeting (kill the low-HP enemy, focus the burning one) remains available.
- If an enemy is the only surviving enemy, the player knows the intent must be one of that enemy's possible actions. Narrowing the possibility space is a skill expression.
Relic counterplay:
| Relic Name | Effect | Availability |
|---|---|---|
| Clarity Lens | Immune to Blind. Intent always visible. | Rare relic, shop or elite reward |
| Smelling Salts | When Blind is applied, immediately reduce stacks by 1 (minimum 0). Blind 1 = no effect; Blind 2 = Blind 1. | Uncommon relic |
| Oracle's Monocle | While Blind, deal +10% damage (fighting blind makes you reckless and powerful). | Uncommon relic |
Consumable counterplay:
| Consumable | Effect | Notes |
|---|---|---|
| Eye Drops (new) | Remove all stacks of Blind immediately. Single use. | Sold in shops, found in rewards |
| Reforge | Does not cleanse Blind (wrong tool category) | Existing item |
Elemental counterplay:
- Freeze applied to a blinding enemy prevents that enemy from executing their next action. Freezing an enemy before they can apply Blind wastes their turn. This is the primary offensive counterplay — control the enemy, deny the blind.
- Wind combo (Frost Lance, Tempest) AoE can freeze multiple enemies simultaneously, shutting down coordinated blind setups.
Cleanse mechanic (future-proofing):
The Status Effect System already notes a future cleanse mechanic. When cleanse
is implemented, Blind (is_debuff = true) should be cleansable. Any cleanse
consumable, relic, or shrine blessing should remove Blind along with other debuffs.
3.6 Interaction with Interference System
Blind is a status effect, not an interference type. Interference types (SNIPE, CHAOS, etc.) are instantaneous effects that happen during the enemy phase. Blind is a persistent debuff that affects the player's information state across a full player turn.
The two systems coexist:
- POCKET_SAND (Merchant action) applies the Blind status during the enemy phase, taking effect immediately — the player's next turn will be blinded.
- If a CHAOS interference also fired the same enemy phase, the dice are scrambled AND the player plays next turn without knowing what enemies will do. Stacked pressure is intentional for the Merchant encounter.
- Blind does not prevent or modify any interference type. If a die is SNIPED while the player is blind, the snipe still happens normally. The player still sees the die being affected.
3.7 Interaction with Per-Enemy Turn Limit
The turn limit is unchanged by Blind. The player has the same number of turns to defeat the enemy whether blinded or not. Blind does not pause or reset the turn counter.
4. Formulas
4.1 Blind Duration
applied_blind_stacks = source_base_stacks
if target already has "blind":
target.statuses["blind"].stacks += applied_blind_stacks
else:
target.statuses["blind"] = { stacks: applied_blind_stacks }
Where source_base_stacks is defined per enemy action:
| Source | Base Stacks | Notes |
|---|---|---|
| Merchant POCKET_SAND | 1 | 20% action weight |
| Smoke Cultist RITUAL_SMOKE | 1 | 100% action weight on that action |
| Shadow Rogue SNEAK_ATTACK | 1 | Combined with 8 damage |
| Blind Oracle PROPHECY_VEIL | 2 | Elite — 2-turn blind |
| Arch Demon DREAD_AURA | 1 | Phase 2 only, once per phase |
4.2 Blind Tick (Duration Decrease)
Blind is DurationType.TIMED. Ticking follows the existing tick rule:
# At the START of the player's turn:
if player has "blind":
player.statuses["blind"].stacks -= 1
if player.statuses["blind"].stacks <= 0:
remove_status(player, "blind")
signal blind_expired # Triggers intent reveal animation in UI
This means:
- Blind applied during the enemy phase of Turn N → player is blinded during Turn N+1, expires at the start of Turn N+2.
- Blind 2 applied → player is blinded during Turns N+1 and N+2, expires at Turn N+3.
4.3 Smelling Salts Relic Interaction
# Called during apply_status, before committing:
if player has relic "smelling_salts":
applied_blind_stacks = max(0, applied_blind_stacks - 1)
if applied_blind_stacks == 0:
return # Blind fully absorbed, nothing applied
Net result: Smelling Salts converts Blind 1 into no effect, Blind 2 into Blind 1, Blind 3 into Blind 2.
4.4 Oracle's Monocle Relic Interaction
# In damage calculation, after base scoring:
if player has "blind" and player has relic "oracles_monocle":
final_damage *= 1.10
Applies to hand damage only, not elemental combo bonus damage.
4.5 Eye Drops Consumable
# On use:
if player has "blind":
remove_status(player, "blind")
signal blind_expired # Same intent reveal animation as natural expiry
else:
# No-op — consumable still consumed (wasted use, player's mistake)
Consumable is wasted if used while not blinded. This is consistent with how other consumables behave on null targets.
5. Edge Cases
| Situation | Resolution |
|---|---|
| Blind applied when player is already at Blind 3 | Stacks add normally. No cap. Blind 6 is possible at extreme karma debt (multiple Merchants + bodyguards). |
| Player uses Eye Drops when not blinded | Consumable consumed, no effect. No refund. Warning tooltip on hover: "Only effective while Blinded." |
| Player kills the blinding enemy before it acts | Enemy dies during player phase; its queued intent never executes. Blind is never applied. The player avoided the blind entirely — this is correct and a valid strategic reward. |
| Blind applied to player on the very last turn (turn limit turn) | Blind applies normally but is essentially irrelevant — the player has no more turns. The enemy phase will execute either as the player's last action or after their loss. |
| Multiple blinding enemies in same encounter | Stacks accumulate per application. E.g., two Smoke Cultists that both use RITUAL_SMOKE in the same enemy phase = Blind 2. This is acceptable as a rare late-game spike but the encounter generator should be configured to avoid pairing blinding enemies (see Section 3.4). |
| Blind expires mid-enemy-phase (impossible by design) | Blind ticks at the START of the player's turn, not during the enemy phase. The enemy phase never modifies Blind stacks. This edge case cannot occur. |
| Player freezes the enemy before POCKET_SAND fires | Frozen enemy skips their action (including POCKET_SAND). Blind is not applied. Freeze works as a full action denial. |
| Clarity Lens relic + Blind applied anyway | Clarity Lens grants immunity. The apply_status call for "blind" is no-opped before any stacks are added. Stacks stay at 0 (or the status is never created). The intent icons remain visible throughout. |
| Cleanse consumable (future) removes Blind that has already caused a turn of blindness | The Blind is removed mid-turn if the consumable is used during the player's turn. The intent icons restore immediately. The player can respond to newly visible intents before scoring if the UI updates fast enough — this is intentional (spending a consumable slot to restore info mid-turn is a valid play). |
| Enemy's CONDITIONAL AI changes action after intent is set | In the existing enemy AI design, intents are set at the start of the player phase and do not change. Blind hiding the intent is accurate to what the enemy will actually do — the hidden information is stable. |
| Arch Demon DREAD_AURA blind fires in phase 1 (bug) | The Phase 2 flag should gate the action. If triggered in Phase 1 by a bug, behavior is identical (Blind 1 applied) but the design intent is violated. This should be caught by acceptance criteria test #11. |
6. Dependencies
Upstream (systems this depends on)
| System | Type | Interface |
|---|---|---|
| Status Effect System | Hard | Blind is registered as a new StatusData resource. Ticking, stacking, and removal follow the existing status lifecycle. Adds INFORMATION_DENY to StatusModifierType enum (or uses NONE if the hook is fully in the UI layer — see note below). |
| Enemy Data & AI | Hard | Blind-applying actions are defined as EnemyAction resources with action_type = DEBUFF, status_id = "blind", target = PLAYER (new target type needed — see note below). |
| Dice Combat Manager | Hard | Manages turn phase boundaries where Blind ticks. Emits signal to UI when Blind state changes. |
Implementation note — StatusModifierType: The existing StatusModifierType
enum covers damage and block math. INFORMATION_DENY is a new type that does not
modify combat math — it modifies UI rendering. The cleanest implementation is
to add INFORMATION_DENY to the enum and handle it as a special case in the
UI layer (the Combat UI queries whether the player has "blind" and hides intents
accordingly), rather than having the Status Effect System's query functions handle it.
Implementation note — EnemyTarget: Existing targets are ALL_PLAYERS,
RANDOM_PLAYER, SELF, ALL_ENEMIES. The blind action targets the player.
In solo, this is equivalent to ALL_PLAYERS or RANDOM_PLAYER (same result).
For implementation, use ALL_PLAYERS for DEBUFF actions targeting the player
to keep the schema consistent with any future multiplayer consideration.
Downstream (systems that must be aware of this)
| System | Type | Interface |
|---|---|---|
| Dice Combat UI | Hard | Must query Blind status before rendering intent displays. When player.has_status("blind"), replace intent icons with "?" and suppress hover tooltips. Listens for blind_expired signal to trigger reveal animation. |
| Shop Combat System | Soft | Merchant POCKET_SAND action already documented. No new interface needed — it's just an EnemyAction using status_id = "blind". |
| Relic Database | Soft | Clarity Lens, Smelling Salts, Oracle's Monocle must be added as new relic definitions. They read/modify Blind stacks through the existing status API. |
| Consumable Database | Soft | Eye Drops must be added as a new consumable. Uses remove_status(player, "blind"). |
| Enemy Database | Soft | Shadow Rogue, Smoke Cultist, Blind Oracle must be defined with Blind-applying actions. Arch Demon's Phase 2 must add DREAD_AURA action. |
| Audio Manager | Soft | POCKET_SAND sand-throw SFX on blind application, "blind cleared" tone on expiry. Uses existing SFX event system. |
7. Tuning Knobs
All values live in assets/data/status_effects/blind.tres and
assets/data/relics/ (per relic). None hardcoded.
| Knob | Default | Safe Range | Category | What It Affects |
|---|---|---|---|---|
BLIND_BASE_DURATION (Merchant POCKET_SAND) | 1 | 1-2 | Gate | Blind from the Merchant. 2 turns turns a boss fight level encounter into a punishing info blackout. |
BLIND_BASE_DURATION (Smoke Cultist) | 1 | 1-2 | Gate | Blind from basic-tier enemies. Should stay at 1 — basic enemies should not inflict 2-turn blindness. |
BLIND_BASE_DURATION (Blind Oracle) | 2 | 1-3 | Gate | Elite enemy, higher baseline acceptable. 3 is maximum before the effect becomes frustrating rather than challenging. |
BLIND_BASE_DURATION (Arch Demon DREAD_AURA) | 1 | 1-2 | Gate | Boss context. 1 keeps it fair — the boss already has a full multi-phase kit. |
SMELLING_SALTS_ABSORB | 1 stack | 1-2 | Feel | Stacks of Blind the Smelling Salts relic absorbs on application. 2 would make the relic too strong against 1-stack sources. |
ORACLES_MONOCLE_BONUS | 10% damage | 5-20% | Curve | Damage bonus while blind. Too high (>20%) encourages intentionally staying blinded, which trivializes the mechanic. |
PRICE_EYE_DROPS | 80g | 50-120g | Gate | Shop purchase price. Should be more expensive than a standard consumable (70g) but not so expensive it's never purchased. |
MAX_BLIND_ENCOUNTER_SOURCES | 1 per encounter | 1-2 | Gate | Number of enemies in a single encounter allowed to have Blind actions. 1 is the strong recommendation. Increase to 2 only if playtesting shows blind encounters are too easy to avoid. |
INTENT_REVEAL_ANIM_DURATION | 0.2s | 0.1-0.4s | Feel | Speed of the intent-reveal animation when blind expires. Shorter feels snappier; longer is more dramatic. |
INTENT_HIDE_ANIM_DURATION | 0.3s | 0.2-0.5s | Feel | Speed of the intent-hide animation when blind is applied. Slightly slower than reveal for dramatic weight. |
8. Acceptance Criteria
All criteria must pass before this feature ships. Each criterion maps to a specific, verifiable behavior.
| # | Criterion | Verification Method |
|---|---|---|
| 1 | Blind status applies correctly from POCKET_SAND | Trigger Merchant combat, let POCKET_SAND fire. Assert player.statuses["blind"].stacks == 1. |
| 2 | Intent icons are hidden while Blind is active | Functional: during a turn where player has blind stacks > 0, assert that intent icon nodes are set to the "?" placeholder and not the enemy's actual intent icon. |
| 3 | Intent hover tooltips are suppressed while Blind is active | Functional: hover over enemy intent badge while blinded, assert that no tooltip appears (tooltip node is not shown). |
| 4 | Enemy HP, shield, and status icons remain visible while Blind is active | Visual verification: enter a blinded turn, confirm HP bars, shield values, and status badges render normally. |
| 5 | Blind stack decreases by 1 at the start of the player's turn | Unit test: apply Blind 2, advance to player turn, assert stacks == 1. Advance again, assert stacks == 0 and status removed. |
| 6 | Intent icons restore when Blind expires | Functional: observe intent icons return to normal on the turn after Blind stacks reach 0. Assert reveal animation plays. |
| 7 | Blind stacks accumulate from multiple sources | Unit test: apply Blind 1, then Blind 1 again from a different source, assert stacks == 2. |
| 8 | Clarity Lens relic grants full immunity | Apply Clarity Lens relic. Trigger POCKET_SAND. Assert player.statuses does not contain "blind" after application. Intent icons never change. |
| 9 | Smelling Salts relic reduces applied stacks by 1 | Unit test: equip Smelling Salts, apply Blind 1 → stacks = 0 (not applied). Apply Blind 2 → stacks = 1. |
| 10 | Eye Drops consumable removes all Blind stacks immediately | Equip Eye Drops, apply Blind 2, use Eye Drops, assert player.statuses["blind"] is absent and intent icons restore. |
| 11 | Eye Drops consumed with no effect when player is not blinded | Use Eye Drops while not blinded, assert consumable is consumed and no error is thrown. |
| 12 | Oracle's Monocle deals +10% damage while blinded | Unit test: calculate hand damage with and without Blind active while Oracle's Monocle is equipped. Assert 10% increase is applied when blind. |
| 13 | Freezing a blinding enemy before it acts prevents Blind application | Set up combat: enemy queued to use POCKET_SAND, trigger Freeze on that enemy before their action fires, assert player never receives Blind. |
| 14 | Arch Demon DREAD_AURA only fires in Phase 2 | Boss encounter test: assert DREAD_AURA action does not appear in Phase 1 intent sequence. Assert it appears at most once in Phase 2. |
| 15 | Encounter generator does not place two blinding enemies in same encounter | Encounter generator test: run 1000 procedural encounter generations for floors 5-15, assert 0 encounters contain more than 1 enemy with a Blind-applying action (assuming MAX_BLIND_ENCOUNTER_SOURCES = 1). |
| 16 | Blind status icon and stack count appear on player HUD | Experiential: while blinded, assert the Blind debuff icon with correct stack count is visible on the player status bar (same row as other debuffs). |
| 17 | Blind application animation plays on POCKET_SAND fire | Experiential: trigger POCKET_SAND, observe intent badges animate to "?" within 0.3 seconds. No visual pop/flicker. |
| 18 | Blind expiry animation plays cleanly | Experiential: observe intent reveal animation at Blind expiry. Assert no frame where both "?" and real icon are simultaneously visible. |
| 19 | Blind does not affect the per-enemy turn counter | Functional: assert turn counter increments and decrements identically whether or not the player is blinded. |
| 20 | Playtest validation — "information denial feels fair, not arbitrary" | Playtest criterion: run 5 playtests where Blind fires at least once. Players should not describe the effect as "I had no way to respond" — they should describe it as "I didn't know what was coming but I made my best guess." If more than 2 of 5 sessions report arbitrary frustration, reduce default Blind duration or increase counterplay availability. |