Learn Python in 30 Days — Day 14: Week 2 Review

Learn Python in 30 Days — Day 14: Week 2 Review

Project: Tiny Dungeon — Tactics & Monsters

Welcome to Day 14 of the Learn Python in 30 Days series!

Today, you’ll bring together everything from Weeks 1 and 2 to create a playable Tiny Dungeon right inside your terminal.

We’ll build this step-by-step, adding a concept from each day along the way.

You’ll Use (Days 1–13)

  • Days 1–4: print(), input(), variables, arithmetic & comparison operators

  • Days 5–6: if / elif / else, chained conditions, clean indentation

  • Days 8–9: loops (for, while)

  • Day 10: lists (battle log, attacks, room order)

  • Day 11: tuples (fixed configs), sets (weakness tags, inventory)

  • Day 12: dictionaries (player, monsters, rooms)

  • Day 13: nested structures (lists + dicts + sets) and looping through them

How to Play

Move: go north, south, east, west
Battle: attack <name>, heal, guard, info, bag, log

Explore to find items (set-based inventory) and exploit monster weaknesses (set intersection bonus).
There’s no randomness victory depends on your planning, stamina management, and timing.

Building the Dungeon — One Day at a Time

🗓 Day 1 — Print & Say Hello

print("=== Tiny Dungeon — Week 2 Review ===")

💡 Every program starts with output.
Try adding a welcome tip line under it.

🗓 Day 2 — Variables & Simple Data

player = { "hp": 20, "max_hp": 20, "stamina": 8, "max_stamina": 8, "location": "hall", "inventory": set(), "guarding": False }

💡 Keeps state tidy and readable.
Try lowering starting HP to 15 to see how it changes difficulty.

🗓 Day 3 — Input (Your Command Loop)

while True: cmd = input("\n> ").strip().lower() if not cmd: continue if cmd in ("quit", "exit"): print("Goodbye.") break

💡 Your event loop — the heart of every terminal game.
Try adding a help command listing available actions.

🗓 Day 4 — Operators & Expressions

def clamp(val, lo, hi): return lo if val < lo else hi if val > hi else val player["hp"] = clamp(player["hp"] + 5, 0, player["max_hp"])

💡 Math controls healing and damage.
Try subtracting 1 stamina per turn using clamp.

🗓 Day 5 — Conditionals (if / elif / else)

parts = cmd.split() verb = parts[0] if verb == "look": ... elif verb == "heal": ... else: print("Commands: go, take, attack, heal, guard, look, quit")

💡 Branching logic turns input into behaviour.
Add a bag command to display HP & inventory.

🗓 Day 6 — Chaining Conditions

def action_guard(): player["guarding"] = True if "shield" in player["inventory"] and player["stamina"] < player["max_stamina"]: player["stamina"] += 1 print("Shield steady — regain 1 stamina.") else: print("You raise your guard.")

💡 Combines multiple tests for layered effects.
Try allowing the stamina bonus only every other turn.

🗓 Day 8 — For Loops (Listing Things)

ROOMS = { "hall": {"desc": "A dim hall…", "exits": {"east": "armory", "south": "library"}, "item": "bandage"}, } def show_room(): room = ROOMS[player["location"]] print(room["desc"]) exits = ", ".join(room["exits"].keys()) print(f"Exits: {exits}")

💡 No hard-coding — update the map, game UI updates automatically.

🗓 Day 9 — While Loops (Turn Engine)

def check_end(): if player["hp"] <= 0: print("💀 Game over.") return True if not any(m["alive"] for m in MONSTERS) and player["location"] == "hall": print("🎉 Victory!") return True return False while True: if check_end(): break # read and process input...

💡 Controls the full game lifecycle.

🗓 Day 10 — Lists (Attacks, Monsters, Logs)

ATTACKS = [ {"name": "strike", "cost": 2, "tags": {"slash"}, "base": 4}, {"name": "bash", "cost": 3, "tags": {"blunt"}, "base": 6}, {"name": "pierce", "cost": 2, "tags": {"pierce"}, "base": 5}, ] log = [] def add_log(msg): log.append(msg) if len(log) > 50: del log[:10]

💡 Lists manage multiple objects and history.

🗓 Day 11 — Tuples & Sets

HEAL_RANGE = (5, 5) GUARD_REDUCTION = (3,) player["inventory"] = set() # attack tags & monster weaknesses are sets

💡 Tuples = constants, Sets = unique membership + intersection logic.

🗓 Day 12 — Dictionaries (Structured Data)

MONSTERS = [ {"name": "Ratling", "hp": 10, "attack": 3, "weakness": {"slash", "pierce"}, "room": "hall", "alive": True}, ] def current_monster(): for m in MONSTERS: if m.get("room") == player["location"] and m.get("alive"): return m

💡 Dictionaries are your in-memory database.

🗓 Day 13 — Nested Structures (World + Combat)

def compute_damage(attack_dict, monster): bonus = 2 if (attack_dict["tags"] & monster["weakness"]) else 0 return attack_dict["base"] + bonus

💡 Set intersection makes weakness logic one line.

Core Gameplay Pieces

Movement

def cmd_go(direction): room = ROOMS[player["location"]] if direction in room["exits"]: player["location"] = room["exits"][direction] print(f"Moved to {player['location']}.") show_room() else: print("🚪 You can’t go that way.")

Items

def cmd_take(item_name): room = ROOMS[player["location"]] if room["item"] == item_name: player["inventory"].add(item_name) room["item"] = None print(f"Picked up {item_name}.")

Combat

def action_attack(parts): if len(parts) < 2: print("Usage: attack <strike|bash|pierce>") return m = current_monster() if not m: print("No monster here."); return attack = next((a for a in ATTACKS if a["name"] == parts[1]), None) if not attack: print("Unknown attack."); return if player["stamina"] < attack["cost"]: print("Too tired."); return dmg = compute_damage(attack, m) m["hp"] -= dmg; player["stamina"] -= attack["cost"] print(f"You used {attack['name']} for {dmg} damage.")

Heal & Guard

def action_heal(): amount = HEAL_RANGE[0] + (2 if "bandage" in player["inventory"] else 0) \ + (1 if "tome" in player["inventory"] else 0) player["hp"] = clamp(player["hp"] + amount, 0, player["max_hp"]) print(f"You heal {amount} HP.") def action_guard(): player["guarding"] = True if "shield" in player["inventory"] and player["stamina"] < player["max_stamina"]: player["stamina"] += 1 print("Shield steady — regain 1 stamina.") else: print("You raise your guard.")

💾 Full Code

Download the complete example on GitHub:
👉 Learn-Python-in-30-Days → Day 14 Tiny Dungeon

🧠 Challenges

ChallengeHint
Hard ModeReduce passive stamina regen to every other turn (use a turn counter).
Lock & KeyRequire the tome to unlock the crypt.
Multi-Foe RoomAdd two monsters to the crypt and loop their attacks.
Combo AttacksParse attack strike+bash and sum costs / damage.
ASCII MapUse a nested list grid and redraw each turn.

🏁 What You’ve Achieved

You’ve now combined:

  • Loops, logic, and data structures into a working text game

  • Deterministic combat and inventory systems

  • Reusable patterns for functions and refactoring (next week)

Next time, we’ll move into Week 3 which will cover Functions & Files:
During this time you’ll refactor this dungeon into smaller, cleaner functions and learn how to save / load your game data.

All example files for this series are available on my GitHub: Learn-Python-in-30-Days

You can see the full series here Learn Python in 30 Days series!

Hope you have enjoyed this post, thanks Matty

Comments

Popular posts from this blog

6502 - Part 2 Reset and Clock Circuit

Math Behind Logic Gates

BBC Model B + MMFS: Command Guide