Skip to content

Instantly share code, notes, and snippets.

@Pinacolada64
Last active November 14, 2021 05:00
Show Gist options
  • Save Pinacolada64/5beac3f73140883be6568bcce91a840e to your computer and use it in GitHub Desktop.
Save Pinacolada64/5beac3f73140883be6568bcce91a840e to your computer and use it in GitHub Desktop.
Reading map data from a file
class Exit(object):
def __init__(self, room_number: int, exit_list: list):
"""
Exits are contained in a list, exit_list
:param room_number: this Exit's room number
:param exit_list: list of 5 exits per room: north, east, south, west, room_connection, room_transport
"""
self.room_number = room_number
self.exits = exit_list
logging.info(f'Exit.__init__: created new exit: {room_number=} {exit_list=}')
def __str__(self):
"""
https://letstalkdata.com/2014/08/how-to-write-a-text-adventure-in-python-part-1-items-and-enemies/
Without a __str__ method, calling print() on an object will display something unhelpful like
<__main__.Item object at 0x101f7d978>.
whatever this returns is what happens if you convert a class to a str
which is what print does -- print(Exit(player_room))
"""
exit_list = []
if self.exits[0] != 0:
exit_list.append("North")
if self.exits[1] != 0:
exit_list.append("East")
if self.exits[2] != 0:
exit_list.append("South")
if self.exits[3] != 0:
exit_list.append("West")
room_connection = self.exits[4]
room_transport = self.exits[5]
if room_connection == 1 and room_transport == 0:
exit_list.append("Up to Shoppe")
if room_connection == 1 and room_transport != 0:
exit_list.append("Up")
if room_connection == 2 and room_transport == 0:
exit_list.append("Down to Shoppe")
if room_connection == 2 and room_transport != 0:
exit_list.append("Down")
logging.info(f'Exits: {" ".join(exit_list)}')
# return f"an exit '{self.exit_dir}' that goes to room '{self.destination_room}'"
return " ".join(exit_list)
class Room(object):
def __init__(self, number: int, name: str, monster: int, item: int, weapon: int, food: int, desc: str):
"""
Create Room object
Exits are handled by the Exit class
:param number: room number
:param name: room name
"""
self.number = number
self.name = name
self.monster = monster
# Adds alignment of 'neutral' without having to specify for each room:
# self.alignment = "neutral"
self.item = item
self.weapon = weapon
self.food = food
# Exit object should handle this:
# self.exits = exits
self.desc = desc
logging.info(f'Room.__init__: created new Room(): #{number}, {name}')
# this routine should return all this info so it can be added to the Map:
return
def __str__(self):
return f'#{self.number=} {self.name=}\n' \
f'{self.desc}\n'
"""
https://www.reddit.com/r/learnpython/comments/qo4y4b/beginner_introduction_to_classes_no_links_in_post/
Note that a method definition that is preceded by the command, @staticmethod
(a decorator) is really just a function that does not include the "self"
reference to the calling instance. It is included in a class definition
for convenience and can be called by reference to the class or the instance.
"""
@staticmethod
def create_room(self, number: int,
name: str, monster: int, item: int, weapon: int, food: int, desc: str):
"""
Pass info about room to create a Room object.
Then call Map.add_to_map to add the Room object to the Map.
Room.create_room:
<OOC> Raul says, "... If you run a deli, you don't necessarily know how to create bread and how to create meat.
In the same way, a Map doesn't necessarily know how to create a Room or an Exit"
<OOC> Raul says, "This is useful because sometimes you might need to make a Room outside of the Map.
It also keeps all your Room code in one place, easy to find and easy to read."
<OOC> Raul says, "It might be smarter to make add_room take a Room as a parameter, and then you would create
the room *first* then use add_room to put it on the map. It means that add_room won't have to have all the
same parameters as create_room"
Trying to figure out why there are Room.create_room and Map.add_room methods
I think what Raul is saying is:
Map.add_room(...) augh I don't even know
:return nothing:
"""
self.number = number
self.name = name
self.monster = monster
self.item = item
self.weapon = weapon
self.food = food
self.desc = desc
# self.db[new_room.alignment] = "neutral"
self.alignment = "neutral"
class Map(object):
def __init__(self):
"""
:param Room: {name: str, alignment: str, items: list, desc: str}"""
self.db = {} # dict
logging.info("Map.__init__: new Map object")
# new_room = 0
def __str__(self):
"""
TODO
sample output:
Num Name N E S W U D
xx1 Merchant Lobby + 13 Shoppe
:return: nothing
"""
# temp_map = []
print(game_map)
def add_to_map(self, number: int, name: str, monster: int, item: int, weapon: int, food: int,
desc: str):
"""
Add Room object to Map.
:param number: room number
:param name:
:param monster:
:param item:
:param weapon:
:param food:
:param desc:
:return: none
"""
# new_room is from read_map
# FIXME self.db[new_room.number] = ...
logging.info("Map.add_room:")
logging.info(f'# {number=} {name=}')
logging.info(f'{monster=} {item=} {weapon=} {food=}')
logging.info(f'{desc=}')
# logging.info(f'{alignment=}')
# TODO: until actual room alignment can be changed, this saves entering a data point:
# exits: n e s w rc rt
return new_room.number
def read_map(self, filename: str):
"""
Data format on C64:
* Room number (rm)
* Location name (lo$)
* items: monster, item, weapon, food
* exits: north, east, south, west,
RC (room command: 1=move up, 2=move down),
RT (Room exit transports you to: room #, or 0=Shoppe)
https://github.com/Pinacolada64/TADA-old/blob/master/text/s_t_level-1-data.txt
"""
with open(filename, "r") as f: # read-only
try:
# FIXME: this stops after reading the 1st room. put in a 'while <condition>' loop?
# read map file stanzas:
# line 1:
data = f.readline()
# logging.info(f'{data=}')
room_number = int(data.strip())
logging.info(f'{room_number=}')
# line 2:
data = f.readline()
# logging.info(f'{data=}')
room_name = data.strip().title()
logging.info(f'{room_name=}')
# line 3:
data = f.readline().split(",") # creates a list
monster = int(data[0])
logging.info(f'{monster=}')
item = int(data[1])
logging.info(f'{item=}')
weapon = int(data[2])
logging.info(f'{weapon=}')
food = int(data[3].strip())
logging.info(f'{food=}')
# line 4:
exits = f.readline().strip().split(",") # creates a list
logging.info(f'{exits=}') # equivalent to the print() statement below
map_exits.append(Exit(room_number, exits))
print(map_exits)
# print(Exit(room_number=1, exit_list=exits))
# lines 5-n:
room_list = []
temp = ""
while temp != "^": # end of description text block
temp = f.readline().strip()
logging.info(f'{temp=}')
if temp != "^":
room_list.append(temp) # append to list
room_desc = " ".join(room_list)
logging.info(f'{room_desc=}')
# FIXME: do 'create_room' and 'add_to_map' need all the params passed?
new_room = Room(room_number, room_name, monster, item, weapon, food,
room_desc)
# game_map.add_to_map(Room(room_number, room_name, monster, item, weapon, food, room_desc))
_ = input("Pause: ")
except EOFError:
logging.info("EOF reached")
f.close()
if __name__ == '__main__':
import logging
logging.basicConfig(level=logging.DEBUG, format='[%(levelname)s] | %(message)s')
debug = True
descriptions = True
game_map = Map() # instantiate new Map object
map_exits = [] # can .append(Exit(number, exit_list[])
game_map.read_map("map_data.txt")
# working code: https://gist.github.com/Pinacolada64/5e810e109f15cff2a459d7744900f829
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment