Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Dungeon Game

Hello Kenneth Love !

Let me thank you for all the great effort you are doing by teaching us about how awesome is Python :) I can't wait to see when the new courses you're working on are ready!

I've finished coding the Dungeon Game, now you can:

  • Tell the size you want for the dungeon.
  • Shows a '.' for every cell the player has been in.
  • Shows the Monster.
  • The Monster moves randomly.

The code is right below (I've documented almost everything):

# Copyright (c) 2014 Juan Martin
# Licensed under the MIT license.
# http://www.opensource.org/licenses/mit-license.php

import random

def dungeonsize(idx): # function to set the dungeon's size
  dcells = [] # to save dungeon cells
  limits = [] # to establish the walls located at the right

  for i in range(idx): 
    for j in range(idx):
      dcells.append((i,j))
    limits.append(idx*(i+1)-1)

  return dcells,limits

def welcome(): # function for the beginning of the program :)
  print("Welcome to the dungeon game!")
  didx = input("In order to get started, please select the size of the dungeon (e.g: 3 for a 3x3 dungeon; 4 for a 4x4 and so on...)"
             "\nNote: It has to be 2 or bigger..."
            "\nSize:")

  return didx


def get_locations(): # function to get the starting locations 
  monster = random.choice(cells)
  door = random.choice(cells)
  start = random.choice(cells)

  if monster == door or monster == start or door == start:
    return get_locations()

  return monster,door,start

def move_player_monster(player,monster,move,moves_m): # function to move player and monster
  prev_position_list = []  # to save the previous position of player and monster
  x, y = player['now']
  u, v = monster

  prev_position_list.append(player['now']) # position 0 is player
  prev_position_list.append(monster) # position 1 is monster

  #player
  if move == 'LEFT':
    y -= 1
  elif move =='RIGHT':
    y += 1
  elif move == 'UP':
    x -= 1
  elif move == 'DOWN':
    x +=1

  #monster
  monster_movement = random.choice(moves_m) # monster makes a random choice based on his available movements

  if monster_movement == 'LEFT':
    v -= 1
  elif monster_movement =='RIGHT':
    v += 1
  elif monster_movement == 'UP':
    u -= 1
  elif monster_movement == 'DOWN':
    u +=1

  monster = u,v
  player= x,y

  return player,monster, prev_position_list

def get_moves(player,monster,door,idxm): # function to get the list of available movements of player and monster
  moves = ['LEFT','RIGHT','UP','DOWN'] # player's list of moves
  moves_m = ['LEFT','RIGHT','UP','DOWN']# monster's list of moves

  #player's wall limits
  if player['now'][1] == 0:
    moves.remove('LEFT')
  if player['now'][1] == idxm-1:
    moves.remove('RIGHT')
  if player['now'][0] == 0:
    moves.remove('UP')
  if player['now'][0] == idxm-1:
    moves.remove('DOWN')

  # monster's walls and doors limits (the monster can't enter the door, it's considered a wall)
  if monster[1] == 0: # wall
    moves_m.remove('LEFT')
  elif monster[1]-1 == door[1] and monster[0] == door[0]: # door
    moves_m.remove('LEFT')
  if monster[1] == idxm-1: # wall
    moves_m.remove('RIGHT')
  elif monster[1]+1 == door[1] and monster[0] == door[0]: # door
    moves_m.remove('RIGHT')
  if monster[0] == 0: # wall
    moves_m.remove('UP')
  elif monster[0]-1 == door[0] and monster[1] == door[1]: # door
    moves_m.remove('UP')
  if monster[0] == idxm-1: # wall
    moves_m.remove('DOWN')
  elif monster[0]+1 == door[0] and monster[1] == door[1]: # door
    moves_m.remove('DOWN')

  return moves, moves_m

def draw_map(didx): # function to draw the entire dungeon :)

  for roof in range(didx):
    print(" _", end='') # to show the roof
  print("") #to give a space 

  tile = '|{}'

  for idx, cell in enumerate(cells):
    if idx not in limits:
      if cell == player['now']:
        print(tile.format('X'), end='')  # show player
      elif cell == monster:
        print(tile.format('M'), end='') # show monster
      #elif cell == door:
       # print(tile.format('D'), end='') # show door, (Note: remove the "#" at the beginning of the line and in the previous line  if you want to see it :P)
      elif cell in player['later']:
        print(tile.format('.'), end='') # show previous location of player
      else:
        print(tile.format('_'), end='')

    else:
      if cell == player['now']:
        print(tile.format('X|')) # show player
      elif cell == monster:
        print(tile.format('M|'))  # show monster
      #elif cell == door:
       # print(tile.format('D|')) # show door (Note: remove the "#" at the beginning of the line and in the previous line  if you want to see it :P)
      elif cell in player['later']:
        print(tile.format('.|')) # show previous location of player 
      else:
        print(tile.format('_|'))


didx = welcome() # gets the dungeon's size

# ------ THIS PART IS FOR THE PROGRAM TO NOT BE TROLLED BY USER :P (VALIDATIONS) ------ #
try:
  didx = int(didx)  
except:
  print("That's not an int :( please try again")
  input("Press ENTER to continue and please LOAD the program again ...")
  exit()

if didx < 2:
  print("That's less than 2 :( please try again")
  input("Press ENTER to continue and please LOAD the program again ...")
  exit()
# ------ END OF VALIDATIONS ------ #

cells,limits = dungeonsize(didx) # create a dungeon based on the size given
player = {'now':'','later':[]} # player dictionary with current position = 'now' with 1 value and a list of previous positions = 'later' 
monster, door, player['now'] = get_locations()

while True:
    moves,moves_m = get_moves(player,monster,door,didx)
    print("You're currently in room {}".format(player['now']))
    print("You can move {}".format(moves))
    print ("Enter QUIT to quit")

    draw_map(didx) # send the dungeon's index to make the roof

    move = input("> ")
    move = move.upper()
    if move == 'QUIT':
      break

    if move in moves:
      player['now'],monster,prev_position_list = move_player_monster(player,monster,move,moves_m)
      if prev_position_list[0] not in player['later']: # to not repeat the moves in the 'later' key in order to print the . later on
        player['later'].append(prev_position_list[0]) 
    else:
      print("++ Wallls are hard, stop walking into them! ++")
      continue
    if player['now'] == door:
      print("You escaped!")
      break
    elif player['now'] == monster or (player['now'] == prev_position_list[1] and monster == prev_position_list[0]): # 1st conditional: if the player and monster are at the same position # 2nd conditional(or): if monster and player encounter 
      print("You were eaten by the grue!")
      break

5 Answers

Kenneth Love
STAFF
Kenneth Love
Treehouse Guest Teacher

@Juan Martin: Excellent work! You definitely get a gold star! gold star

A few comments about the code:

  • You use a lot of single letter variables. While that's great for making lines short, it's horribly hard to debug and trace through code. Python is meant to be verbose, so use longer variable names.
  • PEP 8 suggests you should have a space after a comma, so clean that up if you want to blend in with the rest of the Python community's code (hint: you do want this)
  • It'd be neat to have the monster try to track down the player. Not sure exactly how to go about this with what's been taught so far, but I bet you could figure it out. Maybe have a weighted chance of the move being toward the user.

All-in-all, truly excellent work!

Awesome work. I'm definitely looking forward to the upcoming Python courses too. I'm sure you will get a virtual gold star from Kenneth Love :)

Thank you my friend! Python is an awesome programming language :)

Wow! Well done :)

Thanks :)

Very impressive work, Juan! Also, very well commented.

Thanks! I tried my best to make a story of what I did :)

Thank you so much guys! I really appreciate your comments! And thanks for all the great tools that teamtreehouse.com offers to students!