Загрузка данных
"""
ПОДЗЕМЕЛЬЕ ТЁМНОГО МАГА
Текстовая 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()