mud/src/mudlib/prompt.py

113 lines
3.1 KiB
Python

"""Pure functions for prompt rendering."""
from __future__ import annotations
from typing import TYPE_CHECKING
from mudlib.render.colors import colorize
if TYPE_CHECKING:
from mudlib.player import Player
# Default prompt templates by mode
DEFAULT_TEMPLATES: dict[str, str] = {
"normal": "{stamina_gauge} {pl} > ",
"combat": "{stamina_gauge} {pl} vs {opponent} > ",
"editor": "editor> ",
"if": "> ",
}
def render_prompt(player: Player) -> str:
"""Render the prompt string based on player state and mode.
Args:
player: The player whose prompt to render
Returns:
Formatted prompt string with ANSI codes based on player color support
"""
# Get template from player override or mode default
template = player.prompt_template or DEFAULT_TEMPLATES.get(
player.mode, "{stamina_gauge} {pl} > "
)
# Build variable dictionary
stamina_pct = (
int((player.stamina / player.max_stamina) * 100)
if player.max_stamina > 0
else 0
)
# Compute stamina gauge with conditional coloring
if stamina_pct >= 60:
stamina_gauge = f"{{green}}<{stamina_pct}%>{{/}}"
elif stamina_pct >= 30:
stamina_gauge = f"{{yellow}}<{stamina_pct}%>{{/}}"
else:
stamina_gauge = f"{{red}}<{stamina_pct}%>{{/}}"
variables = {
"stamina_pct": str(stamina_pct),
"stamina": str(round(player.stamina)),
"max_stamina": str(round(player.max_stamina)),
"stamina_gauge": stamina_gauge,
"pl": str(round(player.pl)),
"max_pl": str(round(player.max_pl)),
"opponent": _get_opponent_name(player),
"move": "", # TODO: current attack/defense move name
"name": player.name,
"mode": player.mode,
"x": str(player.x),
"y": str(player.y),
"combat_state": _get_combat_state(player),
}
# Substitute variables in template
result = template
for key, value in variables.items():
result = result.replace(f"{{{key}}}", value)
# Process color tags based on player's color support
result = colorize(result, player.color_depth)
return result
def _get_opponent_name(player: Player) -> str:
"""Get the name of the player's combat opponent if any.
Args:
player: The player to check
Returns:
Opponent name if in combat, empty string otherwise
"""
from mudlib.combat.engine import get_encounter
encounter = get_encounter(player)
if encounter is None:
return ""
# Determine who the opponent is (the other entity in the encounter)
if encounter.attacker is player:
return encounter.defender.name
return encounter.attacker.name
def _get_combat_state(player: Player) -> str:
"""Get the current combat state for the player.
Args:
player: The player to check
Returns:
Combat state string: "idle", "telegraph", "window", or "resolve"
"""
from mudlib.combat.engine import get_encounter
encounter = get_encounter(player)
if encounter is None:
return "idle"
return encounter.state.value