Help (I can't think of a better title)

L

Lanny

The answer may be right infront of me but I really can't figure this
out.
I'm trying to build a interactive fiction kind of game, silly I know
but I
am a fan of the genre. I'm trying to build up an index of all the
rooms in
the game from an outside file called roomlist.txt. The only problem is
that
every room ends up having four exits. Here's the code.


class room() :
room_id = 'room_id'
name = 'room'
description = 'description'
item_list =
exits = {}
visits = 0
def leave(self, direction)
global roomlist
global player_current_room
if direction not in player_current_room.exitskeys() :
print 'There is no exit in that direction.'
return 1
roomlist[self.room_id] = self
player_current_room =
roomlist[player_current_room.exits[direction]]
print player_current_room.name
if player_current_room.visits < 1 :
print player_current_room.description
if player_current_room.item_list != [] :
stdout.write('You can see ')
for item in player_current_room.item_list :
stdout.write('a')
if item.display_name[0] in ['a','e','i','o','u'] :
stdout.write('n ' + item.display_name
+
',')
else :
stdout.write(item.display_name + ',')
pass

print
print 'Exits:',
for way in player_current_room.exits :
print way.capitalize(),
print
player_current_room.visits += 1
pass
else :
player_current_room.visits += 1
pass
pass

def build_rooms(room_file) :
global roomlist
rfile = open(room_file)
tmp_builder = ''
for line in rfile :
tmp_builder = tmp_builder + line[:-1]
pass
for location in tmp_builder.rsplit('::') :
if location.rsplit(';')[-1] == '' :
location = location[:-1]
if len(location.rsplit(';')) != 5 :
if '-dev' or '-v' in argv :
print location.rsplit(';')[0], 'had',
len(location.rsplit(';')), 'values in it, 5 expected'
for value in location.rsplit(';') :
print; print value
foobar.append(value)
print 'A room failed to initalize due to either too
much or
not enough values being present in the build file'
pass
pass
else :
roomlist[location.rsplit(';')[0]] = room()
roomlist[location.rsplit(';')[0]].room_id =
location.rsplit(';')[0]
roomlist[location.rsplit(';')[0]].name =
location.rsplit(';')[1]
roomlist[location.rsplit(';')[0]].description =
location.rsplit(';')[2]
if location.rsplit(';')[3] != 'none' :
pass
tmp_var = location.rsplit(';')[4]
print location.rsplit(';')[0],
roomlist[location.rsplit(';')[0]].exits, 'before'
for way in tmp_var.rsplit(',') :
roomlist[location.rsplit(';')[0]].exits[way.rsplit(':')
[0]]
= way.rsplit(':')[1]

roomlist = {}
build_rooms('room_list.txt')

And here is the roomlist.txt file :

start_room;
Starting Room;
This is the starting room, if you can read this text it means that at
least
one part of this beta is working.;
none;
north:second_room,west:aux_room;
::
second_room;
Second Room;
Yo, Yo! This is the second room, if you can see this text a
substantitally
greater amount of the game is running than would have been if you
didn't see
this text.;
apple;
south:start_room;
::
aux_room;
Auxillary Room;
No, there aren't any barbarian conscripts here, but there is a table!;
none;
east:start_room;

Ideally roomlist['start_room'].exits would equal {'aux_room' :
'west',
'second_room' : 'north'} but it doesn't. Sorry if this is unclear or
too
long, but I'm really stumped why it is giving bad output
 
M

MRAB

Lanny said:
The answer may be right infront of me but I really can't figure this
out.
I'm trying to build a interactive fiction kind of game, silly I know
but I
am a fan of the genre. I'm trying to build up an index of all the
rooms in
the game from an outside file called roomlist.txt. The only problem is
that
every room ends up having four exits. Here's the code.


class room() :
room_id = 'room_id'
name = 'room'
description = 'description'
item_list =
exits = {}
> visits = 0

These attributes are being defined as belonging to the class, so they
will be shared by all the instances of the class. This isn't a problem
for immutable items such as strings, but is for mutable items such as
dicts. In short, all the rooms share the same 'exits' dict.

You should really define the instance attributes (variables) in the
'__init__' method.
def leave(self, direction)
global roomlist
global player_current_room
if direction not in player_current_room.exitskeys() :
print 'There is no exit in that direction.'
return 1
roomlist[self.room_id] = self
player_current_room =
roomlist[player_current_room.exits[direction]]
print player_current_room.name
if player_current_room.visits < 1 :
print player_current_room.description
if player_current_room.item_list != [] :
stdout.write('You can see ')
for item in player_current_room.item_list :
stdout.write('a')
if item.display_name[0] in ['a','e','i','o','u'] :
stdout.write('n ' + item.display_name
+
',')
else :
stdout.write(item.display_name + ',')
pass

print
print 'Exits:',
for way in player_current_room.exits :
print way.capitalize(),
print
player_current_room.visits += 1
pass
else :
player_current_room.visits += 1
pass
pass

def build_rooms(room_file) :
global roomlist
rfile = open(room_file)
tmp_builder = ''
for line in rfile :
tmp_builder = tmp_builder + line[:-1]
pass
for location in tmp_builder.rsplit('::') :
if location.rsplit(';')[-1] == '' :
location = location[:-1]
if len(location.rsplit(';')) != 5 :
if '-dev' or '-v' in argv :
print location.rsplit(';')[0], 'had',
len(location.rsplit(';')), 'values in it, 5 expected'
for value in location.rsplit(';') :
print; print value
foobar.append(value)
print 'A room failed to initalize due to either too
much or
not enough values being present in the build file'
pass
pass
else :
roomlist[location.rsplit(';')[0]] = room()
roomlist[location.rsplit(';')[0]].room_id =
location.rsplit(';')[0]
roomlist[location.rsplit(';')[0]].name =
location.rsplit(';')[1]
roomlist[location.rsplit(';')[0]].description =
location.rsplit(';')[2]
if location.rsplit(';')[3] != 'none' :
pass
tmp_var = location.rsplit(';')[4]
print location.rsplit(';')[0],
roomlist[location.rsplit(';')[0]].exits, 'before'
for way in tmp_var.rsplit(',') :
roomlist[location.rsplit(';')[0]].exits[way.rsplit(':')
[0]]
= way.rsplit(':')[1]

roomlist = {}
build_rooms('room_list.txt')

And here is the roomlist.txt file :

start_room;
Starting Room;
This is the starting room, if you can read this text it means that at
least
one part of this beta is working.;
none;
north:second_room,west:aux_room;
::
second_room;
Second Room;
Yo, Yo! This is the second room, if you can see this text a
substantitally
greater amount of the game is running than would have been if you
didn't see
this text.;
apple;
south:start_room;
::
aux_room;
Auxillary Room;
No, there aren't any barbarian conscripts here, but there is a table!;
none;
east:start_room;

Ideally roomlist['start_room'].exits would equal {'aux_room' :
'west',
'second_room' : 'north'} but it doesn't. Sorry if this is unclear or
too
long, but I'm really stumped why it is giving bad output
 
A

Alex Hall

These attributes are being defined as belonging to the class, so they
will be shared by all the instances of the class. This isn't a problem
for immutable items such as strings, but is for mutable items such as
dicts. In short, all the rooms share the same 'exits' dict.

You should really define the instance attributes (variables) in the
'__init__' method.

I just ran into something similar to this in my Battleship game. I had
a Craft class, which defined attributes for any craft (a recon plane,
a submarine, a battleship, and so on). One such attribute was a
weapons list, much like your exits dictionary; I would assign a couple
weapons to a battleship, but suddenly all my ships and airplanes had
those same weapons. What the great people on this list said to do was
something like this:

class Room():
def __init__(self, exits):
if exits==None:
self.exits={}
else:
self.exits=exits

In this way, you can create a new Room object with exits,
r=Room(exits_dict)
or you can create a Room with no exits, and add them later:
r2=Room()
r2.exits["exit1"]="doorway"

but the code in the __init__ method, which will get called as soon as
you create a new Room object, ensures that passing an exits dictionary
will set that instance's exits to what was passed in, while passing
nothing will create a room with an empty dictionary (the if
statement). I hope this made some sense!
def leave(self, direction)
global roomlist
global player_current_room
if direction not in player_current_room.exitskeys() :
print 'There is no exit in that direction.'
return 1
roomlist[self.room_id] = self
player_current_room =
roomlist[player_current_room.exits[direction]]
print player_current_room.name
if player_current_room.visits < 1 :
print player_current_room.description
if player_current_room.item_list != [] :
stdout.write('You can see ')
for item in player_current_room.item_list :
stdout.write('a')
if item.display_name[0] in ['a','e','i','o','u'] :
stdout.write('n ' + item.display_name
+
',')
else :
stdout.write(item.display_name + ',')
pass

print
print 'Exits:',
for way in player_current_room.exits :
print way.capitalize(),
print
player_current_room.visits += 1
pass
else :
player_current_room.visits += 1
pass
pass

def build_rooms(room_file) :
global roomlist
rfile = open(room_file)
tmp_builder = ''
for line in rfile :
tmp_builder = tmp_builder + line[:-1]
pass
for location in tmp_builder.rsplit('::') :
if location.rsplit(';')[-1] == '' :
location = location[:-1]
if len(location.rsplit(';')) != 5 :
if '-dev' or '-v' in argv :
print location.rsplit(';')[0], 'had',
len(location.rsplit(';')), 'values in it, 5 expected'
for value in location.rsplit(';') :
print; print value
foobar.append(value)
print 'A room failed to initalize due to either too
much or
not enough values being present in the build file'
pass
pass
else :
roomlist[location.rsplit(';')[0]] = room()
roomlist[location.rsplit(';')[0]].room_id =
location.rsplit(';')[0]
roomlist[location.rsplit(';')[0]].name =
location.rsplit(';')[1]
roomlist[location.rsplit(';')[0]].description =
location.rsplit(';')[2]
if location.rsplit(';')[3] != 'none' :
pass
tmp_var = location.rsplit(';')[4]
print location.rsplit(';')[0],
roomlist[location.rsplit(';')[0]].exits, 'before'
for way in tmp_var.rsplit(',') :
roomlist[location.rsplit(';')[0]].exits[way.rsplit(':')
[0]]
= way.rsplit(':')[1]

roomlist = {}
build_rooms('room_list.txt')

And here is the roomlist.txt file :

start_room;
Starting Room;
This is the starting room, if you can read this text it means that at
least
one part of this beta is working.;
none;
north:second_room,west:aux_room;
::
second_room;
Second Room;
Yo, Yo! This is the second room, if you can see this text a
substantitally
greater amount of the game is running than would have been if you
didn't see
this text.;
apple;
south:start_room;
::
aux_room;
Auxillary Room;
No, there aren't any barbarian conscripts here, but there is a table!;
none;
east:start_room;

Ideally roomlist['start_room'].exits would equal {'aux_room' :
'west',
'second_room' : 'north'} but it doesn't. Sorry if this is unclear or
too
long, but I'm really stumped why it is giving bad output
 
N

Nobody

Ideally roomlist['start_room'].exits would equal {'aux_room' : 'west',
'second_room' : 'north'} but it doesn't. Sorry if this is unclear or too
long, but I'm really stumped why it is giving bad output

Just to condense a point which the other responses don't (IMHO) make
particularly clear:

Unlike most other OO languages, Python doesn't make instance members
appear as variables within methods; you have to explicitly access them as
members of "self", i.e. "self.exits" for the "exits" member of the current
instance ("self").
 
D

duncan smith

Alex said:
These attributes are being defined as belonging to the class, so they
will be shared by all the instances of the class. This isn't a problem
for immutable items such as strings, but is for mutable items such as
dicts. In short, all the rooms share the same 'exits' dict.

You should really define the instance attributes (variables) in the
'__init__' method.

I just ran into something similar to this in my Battleship game. I had
a Craft class, which defined attributes for any craft (a recon plane,
a submarine, a battleship, and so on). One such attribute was a
weapons list, much like your exits dictionary; I would assign a couple
weapons to a battleship, but suddenly all my ships and airplanes had
those same weapons. What the great people on this list said to do was
something like this:

class Room():
def __init__(self, exits):
if exits==None:
self.exits={}
else:
self.exits=exits

In this way, you can create a new Room object with exits,
r=Room(exits_dict)
or you can create a Room with no exits, and add them later:
r2=Room()
r2.exits["exit1"]="doorway"

but the code in the __init__ method, which will get called as soon as
you create a new Room object, ensures that passing an exits dictionary
will set that instance's exits to what was passed in, while passing
nothing will create a room with an empty dictionary (the if
statement). I hope this made some sense!

[snip]

It does when when you want 'exits' to take a default value which is a
mutable type (and you don't want it shared by all instances).

class Room:
def __init__(self, exits=None):
if exits is None:
self.exits = {}
else:
self.exits = exits

Otherwise, you're fine without the if ... else.

Duncan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top