Python Text Adventure: Part 1
Last modified
Preamble
Use the files at /usr/share/txtadventure/
on the ece2524 VM and the
copies you have been working on as a reference, but create new files
in a new repository for this project to avoid complicated merge
conflicts when you work with a partner.
Avoid copying and pasting the commands and code snippets I list here. Type them in and think about what each one does. Think about the steps each user completes and how they generalize to other collaborative projects. You will be following a similar procedure when collaborating for your final project.
Initialization
Pick someone to be user1
and someone to be user2
. The
initilization steps will vary depending on your role:
-
user1
will initialize a repository and push it to a remote location -
user2
will fork the repo thatuser1
pushed and clone a local copy
User 1
-
Initialize a new repository
$ git init ~/ece2524/pytxt $ cd ~/ece2524/pytxt
-
Add initial files
world.py:
class Room: """A single room""" def __init__(self, data): self.description = data['desc'] self.items = data['items'] def __str__(self): return self.description + "\nitems: " + ", ".join(self.items) class World: """A world contains one or more rooms""" def __init__(self, data, current_name): self.rooms = {} for key,value in data.items(): self.rooms[key] = Room(data[key]) self.current = self.rooms[current_name] def __str__(self): return "World:\n{0}".format( "\n%%\n".join( [ name + ": " + str(room) for name,room in self.rooms.items() ] ) )
And a file
game.py
that-
imports the
world
andyaml
modules -
loads yaml file
rooms.yaml
data = yaml.load( open('rooms.yaml', 'r') )
-
creates a World object with the loaded data
myworld = world.World( data, 'SURGE 104C' )
The fact that we have to initialize the current room this way is not ideal, why not? What are some possible solutons? Let’s discuss them on Wednesday.
-
prints the World object
Ensure that
game.py
has an appropriate shebang line and has execute permission. -
-
Add a remote
$ git remote add origin git@ece2524.ece.vt.edu:user1/pytxt.git
-
Make initial push
$ git push -u origin master
-
Give read access to
user2
$ ssh git@ece2524.ece.vt.edu perms user1/pytxt + READERS user2
User 2
-
Fork
user1/pytxt
$ ssh git@ece2524.ece.vt.edu fork user1/pytxt user2/forks/pytxt
-
Give
user1
read access to your fork$ ssh git@ece2524.ece.vt.edu perms user2/forks/pytxt + READERS user1
-
Clone your forked copy
$ git clone git@ece2524.ece.vt.edu:user2/forks/pytxt.git ~/ece2524/pytxt
-
Modify
world.py
-
Define a new
Item
class. This should be a very simple class with a single instance variable containing the name of the item. Something likeclass Item: def __init__(self, name): self.name = name def __str__(self): return self.name
-
Update the
Room.__init__
method to populate an instance variable with a list of items wrapped in theItem
class. Use the code inWorld
that generates adict
ofRoom
as a reference, though note that you will be creating a list, not a dict.data['items']
is a list of strings, sofor item in data['items']: # do something with item, which is a string
would iterate over that list. For each thing in that list, create an
Item
object and append it to a list. Setself.items
to that list. This an be done in a single line using list comprehension -
You will also have to modify the
Room.__str__
method since items is now a list ofItem
objects and not a list of strings.str.join
expects a list of strings, butself.items
is now a list ofItem
objects. You will need to transform the list of Items into a list of strings. This can be done with a single list comprehension:... list_of_strings = [ str(item) for item in self.items ] ...
-
-
Create a Python program in a file named
test.py
that confirms that items are wrapped in theItem
class:- initialize a
World
object following the same procedure used ingame.py
- loop through each room in your created world object
- loop through each item in the room and check that it
is an instance
of
Item
.1 - don’t print any output, but raise a
RuntimeError
if any of the items are not instances ofworld.Item
- initialize a
-
Add and commit your changes and push to your own remote. Notify
user1
so that they can pull and merge your additions. -
Add a remote named
upstream
for easy merges fromuser1
in the future$ git remote add upstream git@ece2524.ece.vt.edu:user1/pytxt.git
User 1
-
Add a remote named as
user2
’s username for easy merges:$ git remote add user2 git@ece2524.ece.vt.edu:user2/forks/pytxt.git
-
When you receive notification from
user2
, pull and merge their changes.$ git pull user2 master
Testing
I am in the process of writing up automated tests for this assignment. You should always conduct your own tests to confirm your program works according to the specifications. This will provide helpful context and understanding if your program does pass some of the automated tests once they get posted!
Update: I’ve spent more time than anticipated addressing questions and adding to the write-up and I won’t be able to get tests posted before the deadline. Just do the best you can with the specs as is and your own testing.
-
Note that except in very specific cases such as this one, you should avoid using Python’s isinstance() method. Once we clarify what the
Item
class should provide, a better check would be to use hasattr to check for interface support, regardless of type. ↩