game_ncm

GameGirl Color – NCM-as-game-variables engine.

OMORI-inspired emotion system + RPG game variables implemented as a parallel NCM vector space. NOT the real limbic system – this is a game mechanic layer that uses NCM-style math for battle stats, currency, health, and an emotion interaction matrix. # 🎮💀🌀 EMOTION ENGINE POSSESSED

class game_ncm.BattleModifiers(attack_mult=1.0, defense_mult=1.0, speed_mult=1.0, crit_rate=0.05, evasion=0.05, accuracy=1.0, status_resist=1.0, description='')[source]

Bases: object

Derived combat stat multipliers computed from a game’s emotion vector.

Bundles the battle-relevant outputs of the OMORI-style emotion engine – attack/defense/speed multipliers, crit and evasion rates, accuracy, status resistance, and a human-readable description of the dominant emotion and any active combo states. It is a pure value object with no I/O; the numbers are clamped to playable ranges by the function that builds it.

Produced by get_battle_modifiers() from a vector and consumed by format_hud() to render the HUD’s ATK/DEF/SPD/CRIT/EVA line. The to_dict() helper exists for external/HUD-API consumers; no in-repo callers of it were found.

Parameters:
attack_mult: float = 1.0
defense_mult: float = 1.0
speed_mult: float = 1.0
crit_rate: float = 0.05
evasion: float = 0.05
accuracy: float = 1.0
status_resist: float = 1.0
description: str = ''
to_dict()[source]

Serialize the computed battle modifiers to a plain dict.

Delegates to dataclasses.asdict() to flatten every field (attack_mult, defense_mult, speed_mult, crit_rate, evasion, accuracy, status_resist, description) into a JSON-safe dict. Intended for surfacing the derived combat stats to callers (e.g. game tools or HUD/API payloads) without exposing the dataclass. No side effects.

No internal callers were found; provided for parity with the other game dataclasses and external consumers.

Returns:

A shallow dict of all modifier fields.

Return type:

dict[str, Any]

async game_ncm.initialize_game_ncm(game_id, redis=None)[source]

Create and persist the default NCM vector for a new game.

Copies _DEFAULT_GAME_NCM – the starting emotion levels and game stats (HP, MP, XP, gold, glitch, karma, level) – and, when Redis is available, writes it as JSON to the game:ncm:{game_id} Redis string so the game’s emotion/stat state survives across turns and restarts. A Redis failure is caught and logged; the fresh vector is still returned so the caller can use it in-memory regardless.

No in-repo callers were found; invoked from the game subsystem at runtime when a new game is booted.

Parameters:
  • game_id (str) – Identifier of the game whose NCM state is initialized.

  • redis (Any) – Async Redis client; when None the vector is returned without being persisted.

Returns:

A fresh copy of the default NCM/stat vector.

Return type:

dict[str, float]

async game_ncm.get_vector(game_id, redis=None)[source]

Load the current game NCM/stat vector from Redis.

Reads the JSON vector stored under the game:ncm:{game_id} Redis string. If Redis is absent, the key is missing, or a read/JSON error occurs (the error is logged), it falls back to a fresh copy of _DEFAULT_GAME_NCM so callers always receive a usable vector. Read-only.

Called by apply_delta() and format_hud_from_redis(); no other in-repo callers were found.

Parameters:
  • game_id (str) – Identifier of the game whose NCM vector is read.

  • redis (Any) – Async Redis client; when None the default vector is returned.

Returns:

The stored vector, or a copy of the defaults when unavailable.

Return type:

dict[str, float]

async game_ncm.apply_delta(game_id, deltas, redis=None)[source]

Apply signed changes to a game’s NCM vector and persist the result.

Loads the current vector via get_vector(), adds each supplied delta to the matching node (defaulting unknown nodes to their starting value), and rounds to three decimals. Most nodes are clamped to the [0, 3] range used for emotions and stats, while G_XP and G_LEVEL are only floored at zero so they can grow without bound. Combo emotions are then recomputed via _recalculate_combos(), and the updated vector is written back to the game:ncm:{game_id} Redis string (a write failure is caught and logged).

No in-repo callers were found; invoked from the game subsystem at runtime as gameplay events adjust the player’s emotions and stats.

Parameters:
  • game_id (str) – Identifier of the game whose vector is mutated.

  • deltas (dict[str, float]) – Mapping of NCM node name to the signed amount to add.

  • redis (Any) – Async Redis client; when None the new vector is computed and returned but not persisted.

Returns:

The updated, clamped, combo-recalculated vector.

Return type:

dict[str, float]

game_ncm.get_battle_modifiers(vector)[source]

Compute clamped battle stat modifiers from a game’s emotion vector.

Translates the primary and combo emotions into the multipliers and rates a battle uses, then clamps each to a playable range. The mapping is, broadly: HAPPY raises crit and speed, SAD raises defense but lowers speed, ANGRY raises attack but lowers accuracy, AFRAID raises evasion but lowers attack, and the combo emotions (manic, miserable, furious, stressed) stack further effects. It also calls _get_dominant_emotion() to build a description and appends flavor notes when a combo crosses 0.5. Pure computation – no Redis or other I/O.

Called by format_hud() to populate the HUD’s combat line; no other in-repo callers were found.

Parameters:

vector (dict[str, float]) – The NCM/emotion vector to read stat inputs from.

Returns:

The rounded, range-clamped combat modifiers plus a descriptive status string.

Return type:

BattleModifiers

game_ncm.get_emotion_advantage(attacker_emotion, defender_emotion)[source]

Look up the damage multiplier for an attacker/defender emotion matchup.

Reads the static _EMOTION_ADVANTAGE matrix encoding the OMORI-style rock-paper-scissors of emotions (happy beats sad, angry beats happy, sad beats angry, afraid amplifies all). Unknown or unlisted pairings fall back to a neutral 1.0 rather than raising. Pure lookup with no I/O.

No in-repo callers were found; invoked from the game subsystem’s battle logic at runtime when resolving an attack.

Parameters:
  • attacker_emotion (str) – NCM node name of the attacking side’s emotion.

  • defender_emotion (str) – NCM node name of the defending side’s emotion.

Returns:

1.5 for advantage, 0.7 for disadvantage, 1.2 for the AFRAID amplifier, and 1.0 for neutral or unknown matchups.

Return type:

float

game_ncm.format_hud(vector)[source]

Render a GAMEGIRL COLOR HUD status block from a game’s NCM vector.

Formats the game’s stats and emotions into a multi-line, ASCII status display meant to be injected into the system/context prompt so the LLM (and player) can see live state. It pulls HP/MP/XP/gold/level/glitch/karma and the four primary emotions from the vector, draws bracketed bars with the nested _bar() helper, names the dominant emotion via _get_dominant_emotion(), and renders the combat line plus any status flavor from get_battle_modifiers(). Pure string assembly – no I/O.

Called by format_hud_from_redis(); no other in-repo callers were found, so it is otherwise driven by the game subsystem’s prompt assembly.

Parameters:

vector (dict[str, float]) – The NCM/stat vector to visualize.

Returns:

A multi-line HUD status block.

Return type:

str

async game_ncm.format_hud_from_redis(game_id, redis=None)[source]

Load a game’s NCM vector from Redis and render its HUD in one call.

Thin async convenience wrapper that fetches the current vector via get_vector() (reading the game:ncm:{game_id} Redis string, falling back to defaults when unavailable) and hands it to the synchronous format_hud() to produce the status block. Read-only with respect to Redis.

No in-repo callers were found; invoked from the game subsystem at runtime when the HUD needs to be rendered straight from persisted state.

Parameters:
  • game_id (str) – Identifier of the game whose HUD is rendered.

  • redis (Any) – Async Redis client passed through to get_vector(); when None the default vector is used.

Returns:

A multi-line HUD status block for the game’s current state.

Return type:

str