File size: 3,690 Bytes
4998893
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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),
    }