"""
This is a Twitter bot that lets you play Zork.
Props to @jenesaisdiq for inspiration and @redroselet for moral support.
To play, just twitter @zorker with a Zork move. For example:
'@zorker attack troll with sword'
Be cautioned, though, this bot takes it's time playing, and if everyone tries
to move at once it'll all fall apart.
"""
__author__ = 'Scott Torborg (scotttorborg.com)'
from twitter import Twitter
from pprint import pprint
import pexpect, re, time
username = 'zorker'
password = 'REDACTED'
twitter = Twitter(username, password)
class dfrotz(object):
def __init__(self):
self.dfrotz = pexpect.spawn('dfrotz zork1.z5')
self.re = re.compile('\n((?P<location>.*)Score\:\ '
'(?P<score>\d+)\s*Moves\:\ '
'(?P<moves>\d+))?\s*(?P<text>.+)\>',
re.DOTALL)
def tell(self, line):
self.dfrotz.sendline(line.strip())
def listen(self):
resp = self._response()
raw = self.re.search(resp).groupdict()
for k in ['score', 'location', 'moves']:
if k in raw and raw[k]:
setattr(self, k, raw[k].strip())
return raw['text'].strip().replace('\n', ' ')
def _response(self):
res = []
c = None
while c != '>':
try:
c = self.dfrotz.read_nonblocking(1, 0.1)
res.append(c)
except Exception, msg:
break
return ''.join(res).replace('\r\n', '\n')
def parse_twitter(text):
r = re.match('^(\@\S+\s)*(?P<msg>.+)$', text)
if r:
return r.group('msg')
else:
return None
def twitter_short(s):
print "twittering '%s'" % s
twitter.statuses.update(status=s)
def twitter_long(s):
msg = ''
for word in s.strip().split(' '):
if len(msg) + len(word) > 139:
twitter_short(msg)
msg = word
else:
if msg == '':
msg = word
else:
msg += ' ' + word
twitter_short(msg)
time.sleep(3)
replies = twitter.statuses.replies()
if len(replies) > 0:
last_id = replies[0]['id']
else:
last_id = None
df = dfrotz()
intro = df.listen()
df._response()
twitter_long('West of House You are standing in an open field west of a '
'white house, with a boarded front door. There is a small '
'mailbox here.')
count = 0
while True:
print "getting moves from twitter"
if last_id:
moves = twitter.statuses.replies(since_id=last_id)
else:
moves = twitter.statuses.replies()
for move in moves:
last_id = move['id']
reply = parse_twitter(move['text'])
print "move is [%s]" % reply
if reply and reply != '':
df.tell(reply)
twitter_long(df.listen())
if (count % 15) == 0:
tweet = ('Location: %s, Score: %s, Moves: %s'
% (df.location, df.score, df.moves))
twitter_long(tweet)
count += 1
else:
print "ignoring empty reply"
time.sleep(120)