0% found this document useful (0 votes)
65 views12 pages

Dungeon Crawler Game Mechanics

The document outlines a text-based dungeon crawler game, featuring classes for Player, Enemy, Merchant, Tile, Dungeon, and Game mechanics. Players navigate a procedurally generated dungeon, battling enemies, collecting items, and interacting with various tiles such as shrines and merchants. The game includes mechanics for saving and loading progress, as well as player statistics and inventory management.

Uploaded by

ballerzachery8
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
65 views12 pages

Dungeon Crawler Game Mechanics

The document outlines a text-based dungeon crawler game, featuring classes for Player, Enemy, Merchant, Tile, Dungeon, and Game mechanics. Players navigate a procedurally generated dungeon, battling enemies, collecting items, and interacting with various tiles such as shrines and merchants. The game includes mechanics for saving and loading progress, as well as player statistics and inventory management.

Uploaded by

ballerzachery8
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

import random

import json
from textwrap import dedent

# =========================
# Core data structures
# =========================

class Player:
def __init__(self, name="Delver"):
[Link] = name
[Link] = 100
self.max_hp = 100
[Link] = 0
[Link] = 1
[Link] = 50
[Link] = {"Potion": 2}
[Link] = {"Weapon": None, "Armor": None}
[Link] = []
[Link] = (0, 0)
[Link] = 0

def is_alive(self):
return [Link] > 0

def heal(self, amount):


[Link] = min(self.max_hp, [Link] + amount)

def take_damage(self, amount):


[Link] = max(0, [Link] - amount)

def add_item(self, item, qty=1):


[Link][item] = [Link](item, 0) + qty

def remove_item(self, item, qty=1):


if [Link](item, 0) >= qty:
[Link][item] -= qty
if [Link][item] == 0:
del [Link][item]
return True
return False

def gain_xp(self, amount):


[Link] += amount
while [Link] >= [Link] * 100:
[Link] -= [Link] * 100
[Link] += 1
self.max_hp += 10
[Link] = self.max_hp
print(f"Level up! You are now level {[Link]} with {self.max_hp}
HP.")

def damage_output(self):
base = 6 + [Link]
weapon_bonus = 0
w = [Link]["Weapon"]
if w == "Short Sword":
weapon_bonus = 4
elif w == "War Axe":
weapon_bonus = 8
elif w == "Arcane Wand":
weapon_bonus = 5
focus = 3 if "Battle Focus" in [Link] else 0
return base + weapon_bonus + focus

def defense(self):
base = 2 + [Link] // 2
armor_bonus = 0
a = [Link]["Armor"]
if a == "Leather Armor":
armor_bonus = 2
elif a == "Iron Armor":
armor_bonus = 5
elif a == "Runed Plate":
armor_bonus = 9
return base + armor_bonus

class Enemy:
def __init__(self, name, hp, damage, xp_reward, gold=0, loot=None):
[Link] = name
[Link] = hp
[Link] = damage
self.xp_reward = xp_reward
[Link] = gold
[Link] = loot or {}

def is_alive(self):
return [Link] > 0

class Merchant:
def __init__(self, stock):
[Link] = stock # item -> price

class Tile:
def __init__(self, kind="floor", revealed=False, enemy=None, merchant=None,
item=None, locked=False):
[Link] = kind # floor, wall, exit, shrine, vault
[Link] = revealed
[Link] = enemy
[Link] = merchant
[Link] = item
[Link] = locked

# =========================
# Dungeon generation
# =========================

class Dungeon:
def __init__(self, width=10, height=10, seed=None):
[Link] = width
[Link] = height
[Link] = [[Tile(kind="wall") for _ in range(width)] for _ in
range(height)]
[Link] = seed or [Link](1, 10_000)
[Link]([Link])
self._generate()

def _generate(self):
# Carve a simple maze using randomized DFS
stack = [(0, 0)]
[Link][0][0].kind = "floor"
visited = set([(0, 0)])

def neighbors(x, y):


dirs = [(1,0),(-1,0),(0,1),(0,-1)]
[Link](dirs)
for dx, dy in dirs:
nx, ny = x + dx*2, y + dy*2
if 0 <= nx < [Link] and 0 <= ny < [Link] and (nx, ny) not
in visited:
yield (dx, dy, nx, ny)

while stack:
x, y = stack[-1]
choices = list(neighbors(x, y))
if choices:
dx, dy, nx, ny = [Link](choices)
[Link][y + dy][x + dx].kind = "floor"
[Link][ny][nx].kind = "floor"
[Link]((nx, ny))
[Link]((nx, ny))
else:
[Link]()

# Sprinkle special tiles, merchants, enemies, items


floors = [(x, y) for y in range([Link]) for x in range([Link]) if
[Link][y][x].kind == "floor"]
# Exit
ex_x, ex_y = [Link](floors)
[Link][ex_y][ex_x].kind = "exit"

# Shrine (free heal)


sh_x, sh_y = [Link](floors)
[Link][sh_y][sh_x].kind = "shrine"

# Vault (locked)
v_x, v_y = [Link](floors)
[Link][v_y][v_x].kind = "vault"
[Link][v_y][v_x].locked = True

# Merchant
m_x, m_y = [Link](floors)
[Link][m_y][m_x].merchant = Merchant({
"Potion": 12,
"Elixir": 40,
"Short Sword": 30,
"War Axe": 65,
"Leather Armor": 25,
"Iron Armor": 55,
"Focus Tonic": 28
})

# Place random enemies and items


enemy_names = ["Goblin", "Skeleton", "Cultist", "Orc Brute", "Shade"]
for _ in range(int(len(floors)*0.25)):
x, y = [Link](floors)
if [Link][y][x].enemy or [Link][y][x].merchant or [Link][y]
[x].kind in ("exit","shrine","vault"):
continue
hp = [Link](25, 60)
dmg = [Link](6, 12)
xp = [Link](25, 60)
gold = [Link](5, 20)
[Link][y][x].enemy = Enemy([Link](enemy_names), hp, dmg, xp,
gold, loot={"Key": 1} if [Link]() < 0.15 else {})

for _ in range(int(len(floors)*0.15)):
x, y = [Link](floors)
if [Link][y][x].item or [Link][y][x].enemy or [Link][y]
[x].kind in ("exit","vault","shrine"):
continue
[Link][y][x].item = [Link](["Potion","Elixir","Leather
Armor","Short Sword","Focus Tonic","Gold Pouch"])

def in_bounds(self, x, y):


return 0 <= x < [Link] and 0 <= y < [Link]

# =========================
# Game mechanics
# =========================

class Game:
def __init__(self):
[Link] = Player()
[Link] = Dungeon(width=13, height=11)
[Link] = 0
[Link] = False
# Find a starting floor tile
for y in range([Link]):
for x in range([Link]):
if [Link][y][x].kind == "floor":
[Link] = (x, y)
return

def save(self, filename="crawler_save.json"):


data = {
"player": {
"name": [Link],
"hp": [Link],
"max_hp": [Link].max_hp,
"xp": [Link],
"level": [Link],
"gold": [Link],
"inventory": [Link],
"equipped": [Link],
"effects": [Link],
"position": [Link],
"keys": [Link]
},
"turn": [Link],
"win": [Link],
"dungeon": {
"width": [Link],
"height": [Link],
"seed": [Link],
"grid": [[{
"kind": [Link],
"revealed": [Link],
"locked": [Link],
"enemy": None if not [Link] else {
"name": [Link],
"hp": [Link],
"damage": [Link],
"xp_reward": [Link].xp_reward,
"gold": [Link],
"loot": [Link]
},
"merchant": None if not [Link] else {"stock":
[Link]},
"item": [Link]
} for t in row] for row in [Link]]
}
}
with open(filename, "w", encoding="utf-8") as f:
[Link](data, f, indent=2)
print("Game saved.")

def load(self, filename="crawler_save.json"):


try:
with open(filename, "r", encoding="utf-8") as f:
data = [Link](f)
except Exception as e:
print(f"Failed to load: {e}")
return
p = data["player"]
[Link] = p["name"]
[Link] = p["hp"]
[Link].max_hp = p["max_hp"]
[Link] = p["xp"]
[Link] = p["level"]
[Link] = p["gold"]
[Link] = p["inventory"]
[Link] = p["equipped"]
[Link] = p["effects"]
[Link] = tuple(p["position"])
[Link] = p["keys"]
[Link] = data["turn"]
[Link] = data["win"]
# Rebuild dungeon
d = data["dungeon"]
[Link] = Dungeon(width=d["width"], height=d["height"],
seed=d["seed"])
for y in range([Link]):
for x in range([Link]):
meta = d["grid"][y][x]
tile = [Link][y][x]
[Link] = meta["kind"]
[Link] = meta["revealed"]
[Link] = meta["locked"]
[Link] = meta["item"]
[Link] = None
if meta["enemy"]:
em = meta["enemy"]
[Link] = Enemy(em["name"], em["hp"], em["damage"],
em["xp_reward"], em["gold"], em["loot"])
[Link] = None
if meta["merchant"]:
[Link] = Merchant(meta["merchant"]["stock"])
print("Game loaded.")

def draw(self):
px, py = [Link]
# Reveal current tile
[Link][py][px].revealed = True
print(f"\nTurn {[Link]} | {[Link]} HP
{[Link]}/{[Link].max_hp} | Lvl {[Link]} | Gold
{[Link]} | Keys {[Link]}")
for y in range([Link]):
row = ""
for x in range([Link]):
t = [Link][y][x]
if (x, y) == (px, py):
row += "@"
elif not [Link]:
row += "?"
elif [Link] == "wall":
row += "#"
elif [Link] == "floor":
row += "."
elif [Link] == "exit":
row += "E"
elif [Link] == "shrine":
row += "S"
elif [Link] == "vault":
row += "V"
else:
row += "."
print(row)

def look(self):
x, y = [Link]
t = [Link][y][x]
[Link] = True
print("\nYou look around:")
desc = {
"wall": "A solid wall blocks your way.",
"floor": "A dusty stone floor stretches onward.",
"exit": "A staircase leading out of the dungeon!",
"shrine": "A quiet shrine glows softly. You feel peace here.",
"vault": "A heavy vault door with intricate runes. It appears locked."
}
print([Link]([Link], ""))
if [Link]:
print(f"You see an item on the ground: {[Link]}")
if [Link] and [Link].is_alive():
print(f"An enemy lurks here: {[Link]} (HP {[Link]})")
if [Link]:
print("A robed merchant hums a tune, ready to trade.")
if [Link]:
print("The mechanism is locked. Perhaps a key would help.")

def move(self, direction):


dx, dy = {"north": (0, -1), "south": (0, 1), "west": (-1, 0), "east": (1,
0)}.get(direction, (0, 0))
x, y = [Link]
nx, ny = x + dx, y + dy
if not [Link].in_bounds(nx, ny):
print("You bump into the edge of the world.")
return
if [Link][ny][nx].kind == "wall":
print("A wall bars your path.")
return
[Link] = (nx, ny)
[Link] += 1
self.enter_tile()

def enter_tile(self):
x, y = [Link]
t = [Link][y][x]
[Link] = True
if [Link] == "exit":
[Link] = True
print("You found the exit. Climbing the stairs, you breathe fresh air.
Victory!")
return
if [Link] == "shrine":
heal = min([Link].max_hp - [Link], 50)
[Link](heal)
print(f"At the shrine, serenity mends your wounds. Restored {heal}
HP.")
if [Link] == "vault":
if [Link]:
print("The vault is locked. You need a key to open it.")
else:
print("The vault yawns open. A trove of gold lies within!")
reward = [Link](100, 200)
[Link] += reward
print(f"You scoop up {reward} gold.")
[Link] = "floor"
if [Link]:
print(f"You spot something: {[Link]}. Use 'take {[Link]}' to pick it
up.")
if [Link] and [Link].is_alive():
print(f"A {[Link]} steps from the shadows!")

def take(self, item):


x, y = [Link]
t = [Link][y][x]
if [Link] == item:
[Link] = None
if item == "Gold Pouch":
g = [Link](20, 50)
[Link] += g
print(f"You found a pouch with {g} gold.")
elif item == "Elixir":
[Link].add_item("Elixir")
print("You pick up an Elixir.")
elif item in ("Potion","Leather Armor","Short Sword","Focus Tonic"):
[Link].add_item(item)
print(f"You pick up {item}.")
else:
print(f"You take {item}.")
else:
print("No such item here.")

def use_item(self, item):


if item not in [Link]:
print("You don't have that.")
return
if item == "Potion":
if [Link].remove_item("Potion"):
[Link](30)
print("You drink a Potion and restore 30 HP.")
elif item == "Elixir":
if [Link].remove_item("Elixir"):
[Link] = [Link].max_hp
print("Elixir restores you fully.")
elif item == "Focus Tonic":
if [Link].remove_item("Focus Tonic"):
[Link]("Battle Focus")
print("Your mind sharpens: Battle Focus for the next fight.")
else:
print("You can't use that right now.")

def equip_item(self, item):


if item in ("Short Sword","War Axe","Arcane Wand"):
if item in [Link]:
[Link]["Weapon"] = item
print(f"You equip {item}.")
else:
print("You don't own that.")
elif item in ("Leather Armor","Iron Armor","Runed Plate"):
if item in [Link]:
bonus = {"Leather Armor": 0, "Iron Armor": 15, "Runed Plate": 30}
[item] if item in ("Iron Armor","Runed Plate") else 0
[Link].max_hp = 100 + bonus
[Link] = min([Link], [Link].max_hp)
[Link]["Armor"] = item
print(f"You don {item}. Max HP may change.")
else:
print("You don't own that.")
else:
print("Not equippable.")

def talk(self):
x, y = [Link]
t = [Link][y][x]
if not [Link]:
print("No one to trade with here.")
return
print("Merchant offers:")
for item, price in [Link]():
print(f"- {item} for {price} gold")

def buy(self, item):


x, y = [Link]
t = [Link][y][x]
if not [Link]:
print("No merchant here.")
return
if item not in [Link]:
print("They don't sell that.")
return
price = [Link][item]
if [Link] < price:
print("Not enough gold.")
return
[Link] -= price
[Link].add_item(item)
print(f"Purchased {item} for {price} gold.")

def sell(self, item):


x, y = [Link]
t = [Link][y][x]
if not [Link]:
print("No merchant here.")
return
if item not in [Link]:
print("You don't own that.")
return
base_price = [Link](item, 10)
sell_price = max(1, base_price // 2)
[Link].remove_item(item)
[Link] += sell_price
print(f"Sold {item} for {sell_price} gold.")

def unlock(self):
x, y = [Link]
t = [Link][y][x]
if [Link] != "vault":
print("Nothing to unlock here.")
return
if not [Link]:
print("Already unlocked.")
return
if [Link] > 0:
[Link] = False
[Link] -= 1
print("You turn the key. The vault unlocks.")
else:
print("You need a key.")

def fight(self):
x, y = [Link]
t = [Link][y][x]
if not [Link] or not [Link].is_alive():
print("No enemy to fight here.")
return
enemy = [Link]
print(f"You engage the {[Link]}!")
focus_used = ("Battle Focus" in [Link])
while [Link].is_alive() and enemy.is_alive():
dmg = max(0, [Link].damage_output() - [Link](0, 2))
[Link] -= dmg
print(f"You strike for {dmg}. Enemy HP: {max(0, [Link])}")
if not enemy.is_alive():
break
incoming = max(0, [Link] - [Link]() +
[Link](0, 2))
[Link].take_damage(incoming)
print(f"{[Link]} hits for {incoming}. Your HP: {[Link]}")
if not [Link].is_alive():
break
if focus_used and "Battle Focus" in [Link]:
[Link]("Battle Focus")
if enemy.is_alive():
print("You were defeated...")
return
print(f"You defeated the {[Link]}!")
[Link].gain_xp(enemy.xp_reward)
[Link] += [Link]
if [Link]:
print(f"You gain {[Link]} gold.")
for k, v in [Link]():
if k == "Key":
[Link] += v
print(f"You obtain a key (x{v}).")
else:
[Link].add_item(k, v)
print(f"You obtain: {k} x{v}")
[Link] = None

def help(self):
print(dedent("""
Commands:
- map: draw the dungeon map
- look: describe current tile
- go <north|south|east|west>: move
- fight: battle if an enemy is present
- take <item>: pick up an item
- use <item>: Potion, Elixir, Focus Tonic
- equip <item>: weapons/armor
- talk: see merchant stock if present
- buy <item>, sell <item>: trade
- unlock: unlock the vault using a key
- stats: show HP, level, gear
- inv: show inventory and gold
- save, load: persist your progress
- quit: exit the game
"""))

def stats(self):
print(f"{[Link]} | HP {[Link]}/{[Link].max_hp} | Lvl
{[Link]} | XP {[Link]} | Gold {[Link]}")
w = [Link]["Weapon"] or "None"
a = [Link]["Armor"] or "None"
print(f"Weapon: {w} | Armor: {a} | Effects: {', '.join([Link])
if [Link] else 'None'}")

def inventory(self):
print("Inventory:")
for item, qty in [Link]():
print(f"- {item} x{qty}")
print(f"Keys: {[Link]} | Gold: {[Link]}")

def run(self):
print(dedent(f"""
Welcome, {[Link]}, to the Procedural Dungeon!
Escape via the 'E' exit, or unlock treasures in vaults.
Beware monsters, trade with merchants, and manage your resources.
Type 'help' for commands.
"""))
[Link]()
while True:
if [Link]:
print("Thanks for playing!")
break
if not [Link].is_alive():
print("You fall. The dungeon claims another soul.")
break
cmd = input("\n> ").strip()
if not cmd:
continue
parts = [Link]()
action = parts[0].lower()
arg = " ".join(parts[1:]) if len(parts) > 1 else ""

if action == "help":
[Link]()
elif action == "map":
[Link]()
elif action == "look":
[Link]()
elif action == "go":
[Link](arg)
elif action == "fight":
[Link]()
elif action == "take":
[Link](arg)
elif action == "use":
self.use_item(arg)
elif action == "equip":
self.equip_item(arg)
elif action == "talk":
[Link]()
elif action == "buy":
[Link](arg)
elif action == "sell":
[Link](arg)
elif action == "unlock":
[Link]()
elif action == "stats":
[Link]()
elif action == "inv":
[Link]()
elif action == "save":
[Link]()
elif action == "load":
[Link]()
elif action == "quit":
print("Farewell, delver.")
break
else:
print("Unknown command. Type 'help' for guidance.")

if __name__ == "__main__":
name = input("Enter your delver's name (or press Enter for 'Delver'):
").strip() or "Delver"
g = Game()
[Link] = name
[Link]()

You might also like