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

Math Behind Logic Gates

6502 - Part 2 Reset and Clock Circuit

Building a 6502 NOP Test