Skip to content

Instantly share code, notes, and snippets.

@KGZM
Last active December 11, 2015 20:19
Show Gist options
  • Save KGZM/4654649 to your computer and use it in GitHub Desktop.
Save KGZM/4654649 to your computer and use it in GitHub Desktop.
Sequel to textgame.py: Intrigued by python I decided to take the text game idea a little further. Added server things and multiuser mode. Just experimenting. (I have no idea how to rename a multifile gist or reorder it, so the files are in alphabetical order not in a semantic order.)
class Message(object):
def __init__(self, string):
self.breakdown = []
self.tokens = {}
for part in string.split('{'):
self.breakdown.extend(part.split('}'))
for i, part in enumerate(self.breakdown):
if i % 2 == 1:
self.tokens[part] = self.breakdown[i] = Token(name=part)
else:
self.breakdown[i] = Token(string=part, evaluated=True)
def format(self, **kwargs):
for key, value in kwargs.iteritems():
if key in self.tokens:
self.tokens[key].sub(value)
return self
def __str__(self):
return ''.join(str(token) for token in self.breakdown)
def __repr__(self):
return '"' + ''.join(repr(token) for token in self.breakdown) + '"'
class Token(object):
def __init__(self, name=None, string=None, evaluated=False):
self.name = name
self.string = string
self.evaluated = evaluated
def sub(self,value):
self.string = str(value)
self.evaluated = True
def __repr__(self):
if self.name is not None:
return "{%s: %s}" % (self.name,self.string)
else:
return self.string
def __str__(self):
if self.evaluated:
return self.string
else:
return ''
def new(*args):
return Message(*args)
import SocketServer
import space
import traceback
class UserHandler(SocketServer.StreamRequestHandler):
def setup(self):
SocketServer.StreamRequestHandler.setup(self)
print self.client_address, 'connected!'
self.request.send('hi ' + str(self.client_address) + '\n')
self.player = space.Player(conn=self.wfile)
def handle(self):
while 1:
data = self.rfile.readline().strip()
try:
self.player.parse_line(data)
except Exception as e:
self.player.hear("An error has occured: " + str(e))
self.player.hear(traceback.format_exc())
print traceback.format_exc()
if data == 'bye':
return
def finish(self):
print self.client_address, 'disconnected!'
self.request.send('bye ' + str(self.client_address) + '\n')
#server host is a tuple ('host', port)
SocketServer.TCPServer.allow_reuse_address = True
server = SocketServer.ThreadingTCPServer(('localhost', 5000), UserHandler)
server.serve_forever()
from collections import defaultdict
from compiler import compile
from message import Message
import operator
class Room(object):
def __init__(self, name="Nowhere",desc="Nothing to see here.", coords=(0,0)):
self.name = name
self.desc = desc
self.coords = Point(coords)
self.contents = set()
def display(self):
msg = Message("{name} {coords}\n{desc}\nContents: {contents}")
contents = ', '.join(str(thing) for thing in self.contents)
msg.format(name=self.name,coords=str(self.coords),desc=self.desc,contents=contents)
return msg
def emit(self, text, exclude=None):
for thing in self.contents:
if exclude is None or thing not in exclude:
thing.hear(text)
def get(self,thing):
self.contents.add(thing)
def drop(self,thing):
self.contents.discard(thing)
def __repr__(self):
return "(Room {0} at {1})".format(self.name,str(self.coords))
class Player(object):
def __init__(self, name="John Doe", conn=None):
self.conn = conn
self.name = name
self.coords = Point(0,0)
self.local_context = {}
self.move_to(Point(0,0))
def __str__(self):
return self.name
def command_look(self, arguments):
self.hear(self.location.display())
def hear(self, msg):
self.conn.write(str(msg) + "\n")
def command_say(self, line):
msg = Message("{name} says, \"{line}\"")
msg.format(name=self.name,line=line)
self.location.emit(msg)
def command_quit(self, arguments):
msg = Message("*{name} quits.")
msg.format(name=self.name)
self.location.emit(msg)
self.hear("Bye")
exit()
def command_eval(self, arguments):
global_context = dict(me=self, here=self.location, space=space)
try:
result = eval(arguments, global_context, self.local_context)
except Exception as e:
result = e
self.hear("=> {0}".format(result))
def command_exec(self, arguments):
global_context = dict(me=self, here=self.location, space=space)
try:
exec compile(arguments, "", "single") in global_context, self.local_context
except Exception as e:
self.hear("=> {0}".format(e))
def move_to(self, new_coords):
space[self.coords].drop(self)
place = space[new_coords]
self.coords = new_coords
self.location = place
place.get(self)
self.hear(place.display())
def run_command(self, command, arguments):
method = getattr(self, "command_" + command, None)
if method is not None:
method(arguments)
return True
else:
return False
def walk(self,direction):
outmsg = Message("{name} walks {direction}.")
inmsg = Message("{name} walks in.")
outmsg.format(name=self.name,direction=direction)
inmsg.format(name=self.name)
self.location.emit(outmsg, exclude=[self])
self.move_to(self.coords + directions[direction])
self.location.emit(inmsg, exclude=[self])
def parse_line(self, line):
command, _, arguments = line.partition(' ')
if command in directions:
self.walk(command)
elif self.run_command(command, arguments):
pass
else:
self.hear("I don't get it.")
# Utility classes.
class keyinitdict(defaultdict):
"""dictionary that passes key to its factory function,"""
def __init__(self, *args):
defaultdict.__init__(self, *args)
def __missing__(self, key):
if self.default_factory is None:
raise KeyError((key,))
self[key] = value = self.default_factory(key)
return value
class Point(tuple):
"""Point class with vector addition"""
def __new__(cls, *tup):
if tup[0].__class__ is not Point:
return super(Point, cls).__new__(cls, tup)
else:
return tup[0]
def __add__(self, other):
return self.__class__(*map(operator.add, self, other))
space = keyinitdict(lambda coords: Room(coords=coords))
directions = dict(
north=Point(0,1),
south=Point(0,-1),
east=Point(1,0),
west=Point(-1,0)
)
if __name__ == "__main__":
player = Player()
player.move_to(Point(0,0))
while True:
line = raw_input("> ")
player.parse_line(line)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment