Загрузка данных


"""
ПОДЗЕМЕЛЬЕ ТЁМНОГО МАГА
Текстовая RPG · Чистый Python · 0 библиотек
"""

# ═══════ Генератор случайных чисел (LCG) ═══════
_seed = 1

def srand(v):
    global _seed
    _seed = v & 0x7FFFFFFF

def rand(a, b):
    global _seed
    _seed = (_seed * 1103515245 + 12345) & 0x7FFFFFFF
    if a > b:
        a, b = b, a
    return a + (_seed % (b - a + 1))

# ═══════ Утилиты ═══════
def cls():
    print("\n" * 40)

def pause():
    input("\n  Нажмите Enter...")

def bar(cur, mx, w=10):
    f = max(0, min(w, cur * w // mx)) if mx else 0
    return "█" * f + "░" * (w - f)

# ═══════ Данные игры ═══════
MOBS = [
    ("Слайм",            12,  3, 10,  5),
    ("Гигантская крыса", 14,  4,  8,  4),
    ("Летучая мышь",     10,  5,  6,  3),
    ("Гоблин",           18,  6, 14, 10),
    ("Скелет",           22,  7, 18, 12),
    ("Паук-гигант",      16,  5, 10,  7),
    ("Зомби",            28,  8, 22, 15),
    ("Призрак",          20,  9, 25, 18),
    ("Тролль",           35, 10, 30, 22),
]

BOSSES = [
    ("Огненный элементаль",  60, 12, 100,  50),
    ("Некромант",            85, 15, 150,  80),
    ("Тёмный маг",          130, 20, 300, 200),
]

SZ = 5
_EMPTY, _MOB, _POT, _GOLD = 0, 1, 2, 3
_TRAP, _BOSS, _START, _SEEN = 4, 5, 6, 7

SYM = {
    _EMPTY: "·", _MOB: "!", _POT: "+", _GOLD: "$",
    _TRAP:  "^", _BOSS: "*", _START: "·", _SEEN: "·",
}

# ═══════ Класс героя ═══════
class Hero:
    def __init__(self, name):
        self.name = name
        self.hp = 50;   self.mhp = 50
        self.atk = 8;   self.df = 3
        self.gold = 0;  self.pot = 2
        self.xp = 0;    self.lv = 1
        self.x = 0;     self.y = 0

    def need(self):
        return self.lv * 50

    def alive(self):
        return self.hp > 0

    def try_levelup(self):
        ok = False
        while self.xp >= self.need():
            self.xp -= self.need()
            self.lv += 1
            self.mhp += 10
            self.hp = self.mhp
            self.atk += 3
            self.df += 1
            ok = True
        return ok

# ═══════ Генерация подземелья ═══════
def gen_dungeon(floor):
    m = [[_EMPTY] * SZ for _ in range(SZ)]
    m[0][0] = _START
    m[SZ - 1][SZ - 1] = _BOSS

    free = [(x, y) for y in range(SZ) for x in range(SZ)
            if (x, y) not in ((0, 0), (SZ - 1, SZ - 1))]

    for i in range(len(free) - 1, 0, -1):
        j = rand(0, i)
        free[i], free[j] = free[j], free[i]

    k = 0
    for _ in range(2):
        m[free[k][1]][free[k][0]] = _POT;  k += 1
    for _ in range(2):
        m[free[k][1]][free[k][0]] = _GOLD; k += 1
    for _ in range(1 + floor):
        if k < len(free):
            m[free[k][1]][free[k][0]] = _TRAP; k += 1
    while k < len(free):
        m[free[k][1]][free[k][0]] = _MOB; k += 1
    return m

# ═══════ Отображение ═══════
def show_map(m, h, vis):
    line = "  +" + "---+" * SZ
    print(line)
    for y in range(SZ):
        row = "  |"
        for x in range(SZ):
            if x == h.x and y == h.y:
                ch = "@"
            elif vis[y][x]:
                ch = SYM.get(m[y][x], "?")
            else:
                ch = "?"
            row += f" {ch} |"
        print(row)
        print(line)

def show_stats(h, fl):
    hb = bar(h.hp, h.mhp)
    print("  ┌────────────────────────────────┐")
    print(f"  │ {h.name:<14}  Ур.{h.lv:<2} Этаж {fl}  │")
    print(f"  │ HP [{hb}] {h.hp:>3}/{h.mhp:<3}        │")
    print(f"  │ ATK:{h.atk:<3} DEF:{h.df:<3}"
          f"  Gold:{h.gold:<4} Pot:{h.pot} │")
    print(f"  │ XP: {h.xp}/{h.need():<24} │")
    print("  └────────────────────────────────┘")

# ═══════ Боевая система ═══════
def combat(hero, mob, boss=False):
    name, m_hp, m_atk, m_xp, m_gold = mob
    e_hp = m_hp
    tag = "БОСС" if boss else "БОЙ"

    print(f"\n  {'=' * 36}")
    print(f"  {tag}: {name}")
    print(f"  HP: {e_hp}  Атака: {m_atk}")
    print(f"  {'=' * 36}")

    while hero.alive() and e_hp > 0:
        print(f"\n  Вы: {hero.hp}/{hero.mhp}"
              f"  |  {name}: {e_hp}/{m_hp}")
        print(f"  [1] Атака   [2] Зелье(x{hero.pot})", end="")
        if not boss:
            print("   [3] Бегство", end="")
        print()

        c = input("  > ").strip()

        if c == "1":
            d = max(1, rand(hero.atk - 2, hero.atk + 3))
            e_hp -= d
            print(f"  Вы наносите {d} урона!")
            if e_hp <= 0:
                print(f"\n  {name} повержен!")
                print(f"  +{m_xp} XP  +{m_gold} золота")
                hero.xp += m_xp
                hero.gold += m_gold
                if hero.try_levelup():
                    print(f"  >>> УРОВЕНЬ {hero.lv}! "
                          f"HP восстановлено! <<<")
                return True

        elif c == "2":
            if hero.pot > 0:
                hero.pot -= 1
                heal = rand(18, 25)
                old = hero.hp
                hero.hp = min(hero.mhp, hero.hp + heal)
                print(f"  Зелье: +{hero.hp - old} HP")
            else:
                print("  Зельев нет!")
                continue

        elif c == "3" and not boss:
            if rand(1, 100) <= 40:
                print("  Вы сбежали!")
                return False
            print("  Побег не удался!")

        else:
            continue

        # Ход врага
        if e_hp > 0:
            ed = max(1, rand(m_atk - 2, m_atk + 3) - hero.df)
            hero.hp -= ed
            print(f"  {name} наносит {ed} урона!")
            if hero.hp <= 0:
                hero.hp = 0
    return False

# ═══════ Основной цикл ═══════
def main():
    cls()
    print("""
  ╔══════════════════════════════════════╗
  ║      ПОДЗЕМЕЛЬЕ ТЁМНОГО МАГА        ║
  ║          ~ Текстовая RPG ~          ║
  ╚══════════════════════════════════════╝

  Вы — искатель приключений.
  Пройдите 3 этажа подземелья
  и победите Тёмного мага!

  Управление:  W вверх   A влево
               S вниз    D вправо
    """)

    name = input("  Имя героя: ").strip() or "Герой"

    # seed от имени — одинаковое имя = одна карта
    h = 0
    for ch in name:
        h = (h * 131 + ord(ch)) & 0x7FFFFFFF
    srand(h)

    hero = Hero(name)
    print(f"\n  Добро пожаловать, {hero.name}!")
    print(f"  HP:{hero.hp}  ATK:{hero.atk}  "
          f"DEF:{hero.df}  Зелья:{hero.pot}")
    pause()

    floor = 1
    while floor <= 3 and hero.alive():
        dungeon = gen_dungeon(floor)
        vis = [[False] * SZ for _ in range(SZ)]
        hero.x, hero.y = 0, 0
        vis[0][0] = True
        cleared = False

        cls()
        print(f"\n  {'=' * 36}")
        print(f"        ЭТАЖ {floor}")
        print(f"  {'=' * 36}")
        pause()

        # ——— Цикл исследования ———
        while hero.alive() and not cleared:
            cls()
            show_stats(hero, floor)
            print()
            show_map(dungeon, hero, vis)

            rt = dungeon[hero.y][hero.x]
            if rt == _START:
                print("\n  Вы у входа. Путь назад отрезан.")
            elif rt == _SEEN:
                print("\n  Здесь уже ничего нет.")

            print("\n  [W] вверх  [A] влево  "
                  "[S] вниз  [D] вправо  [Q] выход")

            c = input("  > ").strip().upper()
            dx = dy = 0
            if   c == "W": dy = -1
            elif c == "S": dy = 1
            elif c == "A": dx = -1
            elif c == "D": dx = 1
            elif c == "Q":
                print("\n  До встречи, герой!")
                return
            else:
                continue

            nx, ny = hero.x + dx, hero.y + dy
            if not (0 <= nx < SZ and 0 <= ny < SZ):
                print("  Стена! Туда нельзя.")
                pause()
                continue

            hero.x, hero.y = nx, ny
            vis[ny][nx] = True
            rt = dungeon[ny][nx]

            # ——— Обработка комнаты ———

            if rt == _MOB:
                base = list(MOBS[rand(0, len(MOBS) - 1)])
                base[1] += (floor - 1) * 8    # HP
                base[2] += (floor - 1) * 2    # ATK
                base[3] += (floor - 1) * 5    # XP
                base[4] += (floor - 1) * 5    # Gold
                combat(hero, tuple(base))
                if hero.alive():
                    dungeon[ny][nx] = _SEEN

            elif rt == _POT:
                n = rand(1, 2)
                hero.pot += n
                cls(); show_stats(hero, floor)
                print(f"\n  Найдено {n} зелье(й)!")
                dungeon[ny][nx] = _SEEN
                pause()

            elif rt == _GOLD:
                g = rand(15, 30) + floor * 10
                hero.gold += g
                cls(); show_stats(hero, floor)
                print(f"\n  Сундук: +{g} золота!")
                dungeon[ny][nx] = _SEEN
                pause()

            elif rt == _TRAP:
                d = rand(8, 15) + floor * 3
                hero.hp = max(0, hero.hp - d)
                cls(); show_stats(hero, floor)
                print(f"\n  ЛОВУШКА! -{d} HP!")
                dungeon[ny][nx] = _SEEN
                pause()

            elif rt == _BOSS:
                cls()
                print("\n  Тёмная энергия сгущается вокруг...")
                pause()
                boss = BOSSES[floor - 1]
                won = combat(hero, boss, boss=True)
                if won:
                    cleared = True
                    dungeon[ny][nx] = _SEEN
                elif hero.alive():
                    print("  Вы отступаете к входу...")
                    hero.x, hero.y = 0, 0
                    pause()

        # ——— Конец этажа ———
        if hero.alive() and floor < 3:
            cls()
            print(f"\n  {'=' * 36}")
            print(f"  Этаж {floor} пройден!")
            heal = 15
            hero.hp = min(hero.mhp, hero.hp + heal)
            print(f"  Отдых: +{heal} HP")
            print(f"  Спуск на этаж {floor + 1}...")
            print(f"  {'=' * 36}")
            pause()

        floor += 1

    # ═══════ Финал ═══════
    cls()
    if hero.alive():
        print(f"""
  ╔══════════════════════════════════════╗
  ║          П О Б Е Д А !              ║
  ║                                      ║
  ║   Вы победили Тёмного мага и         ║
  ║   очистили подземелье от тьмы!       ║
  ║                                      ║
  ║   Счёт:  {hero.gold + hero.lv * 100:<6}                      ║
  ║   Уровень: {hero.lv:<3}  Золото: {hero.gold:<5}        ║
  ╚══════════════════════════════════════╝""")
    else:
        print(f"""
  ╔══════════════════════════════════════╗
  ║          КОНЕЦ ИГРЫ                 ║
  ║                                      ║
  ║   Вы пали на этаже {floor}...          ║
  ║                                      ║
  ║   Уровень: {hero.lv:<3}  Золото: {hero.gold:<5}        ║
  ╚══════════════════════════════════════╝""")

    print("\n  Спасибо за игру!\n")

if __name__ == "__main__":
    main()