from __future__ import annotations import random from typing import Any MONSTER_DB: dict[str, dict[str, int]] = { "哥布林": {"hp": 20, "attack": 5, "defense": 2, "difficulty": 1}, "森林狼": {"hp": 40, "attack": 15, "defense": 5, "difficulty": 2}, "远古巨龙": {"hp": 500, "attack": 100, "defense": 80, "difficulty": 10}, "default": {"hp": 30, "attack": 10, "defense": 5, "difficulty": 1}, } def _difficulty_scale(game_state: Any | None) -> float: if game_state is None: return 1.0 diff_name = str(getattr(game_state, "difficulty", "normal")).lower() return {"easy": 0.9, "normal": 1.0, "hard": 1.2}.get(diff_name, 1.0) def _current_location_danger(game_state: Any | None) -> int: if game_state is None: return 1 player = getattr(game_state, "player", None) world = getattr(game_state, "world", None) if player is None or world is None: return 1 location_name = str(getattr(player, "location", "")) location = getattr(world, "locations", {}).get(location_name) if location is None: return 1 try: return max(1, int(getattr(location, "danger_level", 1))) except Exception: return 1 def get_monster_profile(monster_name: str, game_state: Any | None = None) -> dict[str, int]: normalized_name = str(monster_name or "").strip() profile = MONSTER_DB.get(normalized_name) if profile is not None: return dict(profile) base = dict(MONSTER_DB["default"]) location_danger = _current_location_danger(game_state) diff_scale = _difficulty_scale(game_state) generated_difficulty = max(1, int(round(base["difficulty"] + (location_danger - 1) * 0.6))) generated_attack = max(1, int(round(base["attack"] * diff_scale + location_danger * 2))) generated_defense = max(1, int(round(base["defense"] * diff_scale + location_danger))) generated_hp = max(1, int(round(base["hp"] * diff_scale + location_danger * 10))) return { "hp": generated_hp, "attack": generated_attack, "defense": generated_defense, "difficulty": generated_difficulty, } def resolve_combat( player_state: Any, monster_name: str, *, game_state: Any | None = None, rng: random.Random | None = None, ) -> dict[str, Any]: active_rng = rng or random monster = get_monster_profile(monster_name, game_state=game_state) player_level = max(1, int(getattr(player_state, "level", 1))) player_attack = max(1, int(getattr(player_state, "attack_power", getattr(player_state, "attack", 1)))) player_defense = max(0, int(getattr(player_state, "defense_power", getattr(player_state, "defense", 0)))) player_power = player_attack + player_level * 2 monster_power = int(monster["defense"]) + int(monster["difficulty"]) * 3 outcome = "win" if player_power >= monster_power else "lose" random_float = float(active_rng.uniform(0.0, 3.0)) base_hp_loss = max(1, int(round(int(monster["attack"]) - player_defense - random_float))) if outcome == "lose": base_hp_loss = max(base_hp_loss + int(monster["difficulty"]) * 2, int(round(base_hp_loss * 1.4))) if outcome == "win": message = f"你击败了{monster_name},但仍受了些伤。" else: message = f"你不敌{monster_name},被迫败退。" return { "outcome": outcome, "player_hp_loss": int(base_hp_loss), "monster_name": str(monster_name), "message": message, "player_power": int(player_power), "monster_power": int(monster_power), }