diff options
| author | Jeff Armstrong <jeff@approximatrix.com> | 2013-05-29 09:16:47 -0400 |
|---|---|---|
| committer | Jeff Armstrong <jeff@approximatrix.com> | 2013-05-29 09:16:47 -0400 |
| commit | bc9c79c6abcc3bb53a09147f2d66f7f36dbca28c (patch) | |
| tree | 31d739939b23f3fc287112a23f9e7861703c1315 /lib | |
| download | robotadventure-master.tar.gz robotadventure-master.zip | |
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/creategamecmd.py | 104 | ||||
| -rw-r--r-- | lib/creategamedb.py | 271 | ||||
| -rw-r--r-- | lib/curses_main.py | 69 | ||||
| -rw-r--r-- | lib/curses_main.pyc | bin | 0 -> 1768 bytes | |||
| -rw-r--r-- | lib/custom.py | 85 | ||||
| -rw-r--r-- | lib/custom.pyc | bin | 0 -> 1846 bytes | |||
| -rw-r--r-- | lib/data.py | 44 | ||||
| -rw-r--r-- | lib/data.pyc | bin | 0 -> 903 bytes | |||
| -rw-r--r-- | lib/editor.py | 30 | ||||
| -rw-r--r-- | lib/gamecmd.py | 275 | ||||
| -rw-r--r-- | lib/gamecmd.pyc | bin | 0 -> 9258 bytes | |||
| -rw-r--r-- | lib/gamedb.py | 457 | ||||
| -rw-r--r-- | lib/gamedb.pyc | bin | 0 -> 15894 bytes | |||
| -rw-r--r-- | lib/main.py | 48 | ||||
| -rw-r--r-- | lib/main.pyc | bin | 0 -> 825 bytes | |||
| -rw-r--r-- | lib/prep.py | 66 | ||||
| -rw-r--r-- | lib/prep.pyc | bin | 0 -> 1215 bytes | |||
| -rw-r--r-- | lib/simple_main.py | 47 | ||||
| -rw-r--r-- | lib/unsure.py | 29 | ||||
| -rw-r--r-- | lib/unsure.pyc | bin | 0 -> 459 bytes |
20 files changed, 1525 insertions, 0 deletions
diff --git a/lib/creategamecmd.py b/lib/creategamecmd.py new file mode 100644 index 0000000..508c56b --- /dev/null +++ b/lib/creategamecmd.py @@ -0,0 +1,104 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + + +from creategamedb import * +from gamecmd import * + +class CreateCmd(GameCmd): + def __init__(self): + GameCmd.__init__(self,CreateDB()) + + def do_where(self,args): + names = self.db.getNeighbors() + print 'n: '+names[0] + print 's: '+names[1] + print 'e: '+names[2] + print 'w: '+names[3] + print 'u: '+names[4] + print 'd: '+names[5] + + def do_quit(self,args): + self.db.end() + return -1 + + def do_name(self,args): + self.db.setRoomName(args) + + def do_desc(self,args): + self.db.setRoomDescription(args) + + def do_awaydesc(self,args): + self.db.setRoomAwayDescription(args) + + def do_start(self,args): + self.db.setStart() + + def do_block(self,args): + args = args.strip() + dir = args[0] + desc = args[2:].strip() + self.db.setBlock(dir,desc) + + def do_synonym(self,args): + elements = args.strip().split(' ',1) + self.db.synonym(elements[0],elements[1]) + + def do_verbonym(self,args): + elements = args.strip().split(' ',1) + self.db.verbonym(elements[0],elements[1]) + + def do_person(self,args): + """person name,desc,presence""" + elements = args.strip().split(',') + try: + self.db.person(elements[0],elements[1],elements[2]) + except IndexError: + print "Missing argument..." + + def do_object(self,args): + """object name,desc,presence,[0 or 1 for global]""" + elements = args.strip().split(',') + if len(elements)==3: + self.db.object(elements[0],elements[1],elements[2]) + elif len(elements)==4: + self.db.object(elements[0],elements[1],elements[2],int(elements[3])) + else: + print "Argument error..." + + def do_action(self,args): + """action name,verb,result,action,[state (0 is default)]""" + elements = args.strip().split(',') + if len(elements)==4: + self.db.action(elements[0],elements[1],elements[2],elements[3]) + elif len(elements) == 5: + self.db.action(elements[0],elements[1],elements[2],elements[3],int(elements[4])) + else: + print "Argument error..." + + def do_combine(self,args): + """combine name1,name2,verb,result,action,[state (0 is default)]""" + elements = args.strip().split(',') + if len(elements)==5: + self.db.actionCombine(elements[0],elements[1],elements[2],elements[3],elements[4]) + elif len(elements)==6: + self.db.actionCombine(elements[0],elements[1],elements[2],elements[3],elements[4],int(elements[5])) + else: + print "Argument error..." +
\ No newline at end of file diff --git a/lib/creategamedb.py b/lib/creategamedb.py new file mode 100644 index 0000000..ee3a8dd --- /dev/null +++ b/lib/creategamedb.py @@ -0,0 +1,271 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +from gamedb import * +import sqlite3 +import time + +class HoldRoom: + def __init__(self,id): + self.name = 'empty' + self.description = 'empty' + self.away_description = None + self.id = id + self.n = None + self.s = None + self.e = None + self.w = None + self.u = None + self.d = None + + def getTuple(self): + return (self.id,self.name,self.description,self.away_description,self.n,self.s,self.e,self.w,self.u,self.d) + +def conjugate(dir): + if dir=="north": + return "south" + elif dir=="south": + return "north" + elif dir=="east": + return "west" + elif dir=="west": + return "east" + elif dir=="up": + return "down" + elif dir=="down": + return "up" + +class CreateDB(GameDB): + + def __init__(self): + GameDB.__init__(self,inplace=True) + + self.con.row_factory = sqlite3.Row + + cur = self.con.cursor() + cur.execute('create table if not exists Rooms(id integer unique not null, name text not null, description text not null, away_description text, north integer, south integer, east integer, west integer, up integer, down integer)') + cur.execute('create table if not exists RoomContents(objectid integer not null, roomid integer not null)') + cur.execute('create table if not exists Objects(id integer unique not null, name text not null, description text not null, moveable integer, everywhere integer, person integer not null, presence text, explicit integer not null default 1)') + cur.execute('create table if not exists Combine(id1 integer not null, id2 integer, verb text, result text not null, action text, state integer not null default 0)') + cur.execute('create table if not exists NPC(id integer unique not null, state integer not null, max integer not null default 1)') + cur.execute('create table if not exists Talk(id integer not null, verb text, object integer, result text not null)') + cur.execute('create table if not exists Inventory(id integer unique not null)') + cur.execute('create table if not exists State(name text unique not null, value text)') + cur.execute('create table if not exists Block(id integer not null, room1 integer not null, room2 integer not null, description text not null, state integer not null default 1)') + cur.execute('create table if not exists Synonyms(spoken text not null,name text not null)') + cur.execute('create table if not exists Verbonyms(spoken text not null,name text not null)') + + self.lasttime = 0 + if self.getStart(): + self.getRoom(self.getStart()) + else: + self.newRoom() + + def getDirectionId(self,dir): + if dir=="north": + return self.template.n + elif dir=="south": + return self.template.s + elif dir=="east": + return self.template.e + elif dir=="west": + return self.template.w + elif dir=="up": + return self.template.u + elif dir=="down": + return self.template.d + + def move(self,dir): + self.saveRoom() + if self.getDirectionId(dir): + self.getRoom(self.getDirectionId(dir)) + else: + originaltemplate = self.template + self.newRoom() + self.setId(dir,self.template.id,originaltemplate) + self.setId(conjugate(dir),originaltemplate.id) + self.saveRoom(originaltemplate) + + self.room = self.template.id + + return MOVE_OK + + def setId(self,dir,id,template=None): + if template == None: + template = self.template + + if dir=="north": + template.n = id + elif dir=="south": + template.s = id + elif dir=="east": + template.e = id + elif dir=="west": + template.w = id + elif dir=="up": + template.u = id + elif dir=="down": + template.d = id + + def getRoomName(self): + return self.template.name + + def getRoomDescription(self): + return self.template.description + + def setRoomName(self,value): + self.template.name = value + + def setRoomDescription(self,value): + self.template.description = value + + def setRoomAwayDescription(self,value): + if value == 'none': + self.template.away_description = None + else: + self.template.away_description = value + + def getNewUID(self): + uid = int(time.mktime(time.gmtime())) + if uid == self.lasttime: + self.lasttime = self.lasttime + 1 + else: + self.lasttime = uid + + return self.lasttime + + def newRoom(self): + self.template = HoldRoom(self.getNewUID()) + + def saveRoom(self,room=None): + cur = self.con.cursor() + if not room: + room = self.template + cur.execute("insert or replace into Rooms(id,name,description,away_description,north,south,east,west,up,down) values(?,?,?,?,?,?,?,?,?,?)", + room.getTuple()) + self.con.commit() + + def getNeighbors(self): + descriptions = [] + cur = self.con.cursor() + for id in (self.template.n,self.template.s,self.template.e,self.template.w,self.template.u,self.template.d): + cur.execute("select name from Rooms where id=?",(id,)) + name = "None" + for value in cur: + name = value[0] + break + descriptions.append(name) + + return descriptions + + def object(self,name,desc,presence,glob=False): + everywhere = False + if glob: + everywhere=True + id = self.getNewUID() + cur = self.con.cursor() + cur.execute("insert into Objects(id,name,description,presence,moveable,person,everywhere) values(?,?,?,?,?,?,?)", + (id,name,desc,presence,1,0,everywhere)) + cur.execute("insert into RoomContents(objectid,roomid) values(?,?)",(id,self.template.id)) + + def person(self,name,desc,presence): + id = self.getNewUID() + cur = self.con.cursor() + cur.execute("insert into Objects(id,name,description,presence,moveable,person,everywhere) values(?,?,?,?,?,?,?)",(id,name,desc,presence,0,1,0)) + cur.execute("insert into NPC(id,state,max) values(?,?,?)",(id,0,0)) + cur.execute("insert into RoomContents(objectid,roomid) values(?,?)",(id,self.template.id)) + + def action(self,name,verb,result,action,state=0): + objid = self.getObjId(name,False) + if not objid: + print "Object not found..." + return + cur = self.con.cursor() + cur.execute("insert into Combine(id1,verb,result,action,state) values(?,?,?,?,?)", + (objid,verb,result,action,state)) + + def synonym(self,name,synonym): + cur = self.con.cursor() + cur.execute("insert into Synonyms(spoken,name) values(?,?)",(synonym,name)) + + def verbonym(self,name,synonym): + cur = self.con.cursor() + cur.execute("insert into Verbonyms(spoken,name) values(?,?)",(synonym,name)) + + def actionCombine(self,name1,name2,verb,result,action,state=0): + id1 = self.getObjId(name1) + id2 = self.getObjId(name2) + if not id1: + print "Object not found: "+name1 + return + if not id2: + print "Object not found: "+name2 + return + + cur = self.con.cursor() + cur.execute("insert into Combine(id1,id2,verb,result,action,state) values(?,?,?,?,?,?)", + (id1,id2,verb,result,action,state)) + + + def setBlock(self,dir,desc): + id2 = None + if dir=="n": + id2 = self.template.n + elif dir=="s": + id2 = self.template.s + elif dir=="e": + id2 = self.template.e + elif dir=="w": + id2 = self.template.w + elif dir=="u": + id2 = self.template.u + elif dir=="d": + id2 = self.template.d + if not id2: + return + + cur = self.con.cursor() + cur.execute("insert into Block(id,room1,room2,description) values(?,?,?,?)",(self.getNewUID(),self.template.id,id2,desc)) + + def getRoom(self,id): + cur = self.con.cursor() + cur.execute("select * from Rooms where id=?",(id,)) + self.template = None + for room in cur: + self.template = HoldRoom(id) + self.template.name = room["name"] + self.template.description = room["description"] + self.template.away_description = room["away_description"] + self.template.n = room["north"] + self.template.s = room["south"] + self.template.e = room["east"] + self.template.w = room["west"] + self.template.u = room["up"] + self.template.d = room["down"] + + def setStart(self): + cur = self.con.cursor() + cur.execute("insert or replace into State(name, value) values('Start',?)",(str(self.template.id),)) + + def end(self): + self.saveRoom() + self.con.commit() + self.con.close() + + diff --git a/lib/curses_main.py b/lib/curses_main.py new file mode 100644 index 0000000..f44d871 --- /dev/null +++ b/lib/curses_main.py @@ -0,0 +1,69 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +import sys +import curses +import textwrap +from gamecmd import * + +class FakeStdIO(object): + def __init__(self,stdscr): + self.stdscr = stdscr + + def write(self, str): + height,width = self.stdscr.getmaxyx() + if len(str) >= width: + for line in textwrap.wrap(str,width-2): + self.stdscr.addstr(line) + self.stdscr.addstr("\n") + else: + self.stdscr.addstr(str) + self.stdscr.refresh() + + def readline(self): + temp = self.stdscr.getstr() + if len(temp)==0: + temp = ' ' + return temp + +def launch(cmdparser): + + stdscr = curses.initscr() + curses.cbreak() + #curses.noecho() + curses.echo() + stdscr.keypad(1) + stdscr.scrollok(True) + stdscr.clear() + stdscr.refresh() + + try: + # Run your code here + io = FakeStdIO(stdscr) + sys.stdin = io + sys.stdout = io + cmdparser.stdout = io + cmdparser.stdin = io + cmdparser.cmdloop() + + finally: + curses.nocbreak() + stdscr.keypad(0) + curses.echo() + curses.endwin() diff --git a/lib/curses_main.pyc b/lib/curses_main.pyc Binary files differnew file mode 100644 index 0000000..ca3d70c --- /dev/null +++ b/lib/curses_main.pyc diff --git a/lib/custom.py b/lib/custom.py new file mode 100644 index 0000000..6787d9a --- /dev/null +++ b/lib/custom.py @@ -0,0 +1,85 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +import gamedb + +NPC_VERBS = ['ask', +'question', +'talk', +'tell', +'say', +'speak', +'show', +'hand', +'give'] + +DIRECTIONS = ['north','n', + 'west','w', + 'south','s', + 'east','e'] + +def isDirection(word): + try: + DIRECTIONS.index(word) + return True + except ValueError: + return False + +def handleVerbOnly(db,verb): + return None + +def parseAction(db,action): + if not action: + return + actions = action.split(';') + for each in actions: + each = each.strip() + components = each.split() + + if each.startswith('unblock'): + db.unblock(components[1]) + + elif each.startswith('increment'): + db.increment(components[1]) + + elif each.startswith('remove'): + db.remove(components[1]) + + elif each.startswith('create'): + db.to_inv(components[1]) + + elif each.startswith('state'): + try: + db.setState(components[1],int(components[2])) + except ValueError: + continue + + +def handle(db,verb,obj1=None,obj2=None): + + verb = db.checkVerb(verb) + + if not obj1 and not obj2: + return handleVerbOnly(db,verb) + + result = db.getResult(obj1,obj2,verb) + action = db.getAction(obj1,obj2,verb) + parseAction(db,action) + return result + diff --git a/lib/custom.pyc b/lib/custom.pyc Binary files differnew file mode 100644 index 0000000..364d291 --- /dev/null +++ b/lib/custom.pyc diff --git a/lib/data.py b/lib/data.py new file mode 100644 index 0000000..b17bb0c --- /dev/null +++ b/lib/data.py @@ -0,0 +1,44 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +'''Simple data loader module. + +Loads data files from the "data" directory shipped with a game. + +Enhancing this to handle caching etc. is left as an exercise for the reader. +''' + +import os + +#data_py = os.path.abspath(os.path.dirname(__file__)) +#data_dir = os.path.normpath(os.path.join(data_py, '..', 'data')) +data_dir = 'data' + +def filepath(filename): + '''Determine the path to a file in the data directory. + ''' + return os.path.join(data_dir, filename) + +def load(filename, mode='rb'): + '''Open a file in the data directory. + + "mode" is passed as the second arg to open(). + ''' + return open(os.path.join(data_dir, filename), mode) + diff --git a/lib/data.pyc b/lib/data.pyc Binary files differnew file mode 100644 index 0000000..b108fbf --- /dev/null +++ b/lib/data.pyc diff --git a/lib/editor.py b/lib/editor.py new file mode 100644 index 0000000..50c69d1 --- /dev/null +++ b/lib/editor.py @@ -0,0 +1,30 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +import data +from creategamecmd import * + +try: + import curses + from curses_main import * +except ImportError: + from simple_main import * + +def editor(): + launch(CreateCmd())
\ No newline at end of file diff --git a/lib/gamecmd.py b/lib/gamecmd.py new file mode 100644 index 0000000..4516a7c --- /dev/null +++ b/lib/gamecmd.py @@ -0,0 +1,275 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +import cmd +from gamedb import * +from prep import * +from unsure import * +from custom import * + +PROMPT = '>> ' + +class GameCmd(cmd.Cmd): + def __init__(self,db=None): + cmd.Cmd.__init__(self) + + if db: + self.db = db + else: + try: + self.db = GameDB() + except IOError: + print 'Error loading default game file...' + + self.prompt = PROMPT + + def do_n(self,args): + """Moves north...""" + success = self.db.moveNorth() + self.ackMove(success) + + def do_s(self,args): + """Moves south...""" + success = self.db.moveSouth() + self.ackMove(success) + + def do_e(self,args): + """Moves east...""" + success = self.db.moveEast() + self.ackMove(success) + + def do_w(self,args): + """Moves west...""" + success = self.db.moveWest() + self.ackMove(success) + + def do_u(self,args): + """Moves up...""" + success = self.db.moveUp() + self.ackMove(success) + + def do_d(self,args): + """Moves down...""" + success = self.db.moveDown() + self.ackMove(success) + + def do_north(self,args): + """Moves north...""" + success = self.db.moveNorth() + self.ackMove(success) + + def do_south(self,args): + """Moves south...""" + success = self.db.moveSouth() + self.ackMove(success) + + def do_east(self,args): + """Moves east...""" + success = self.db.moveEast() + self.ackMove(success) + + def do_west(self,args): + """Moves west...""" + success = self.db.moveWest() + self.ackMove(success) + + def do_up(self,args): + """Moves up...""" + success = self.db.moveUp() + self.ackMove(success) + + def do_down(self,args): + """Moves down...""" + success = self.db.moveDown() + self.ackMove(success) + + def do_look(self,args): + """Looks at an object or just around in general""" + if len(args.strip()) == 0: + self.outputRoom() + return + + cleaner = removePrep(args) + + if isDirection(cleaner.strip()): + self.outputLook(cleaner.strip()) + else: + #print cleaner.strip() + self.outputLookAt(self.db.lookAt(cleaner.strip())) + + def do_examine(self,args): + if len(args.strip())==0: + print "Examine what?" + + self.do_look('at '+args.strip()) + + def do_i(self,args): + """List inventory...""" + inv = self.db.getInventory() + if len(inv) == 0: + 'You currently have no items in your inventory' + return + print 'Current Inventory:' + for x in inv: + print ' '+x + + def do_inv(self,args): + """List inventory...""" + self.do_i(args) + + def do_inventory(self,args): + """List inventory...""" + self.do_i(args) + + def do_get(self,args): + """Picks up an item in the room...""" + success = self.db.pickUp(args) + if not success: + print "I don't see any %s to pick up" % args + elif success == True: + print 'Picked up %s' % args + else: + print success + + def do_drop(self,args): + """Drops an inventory item""" + success = self.db.drop(args) + if not success: + print "You're not carrying %s" % args + elif success == True: + print "Dropped %s" % args + + def do_exit(self,args): + """Quits the game...""" + return self.do_quit(args) + + def do_quit(self,args): + """Quits the game...""" + self.db.end() + return -1 + + def do_save(self,args): + """Saves the game to a specified file""" + if len(args.strip()) == 0: + print "Please include a filename - save <filename>" + else: + success = self.db.save(args.strip()) + if success: + print "Game saved successfully" + else: + print "Unknown error while saving..." + + def do_load(self,args): + """Loads the game from a specified file""" + if len(args.strip()) == 0: + print "Please include a filename - load <filename>" + else: + backupdb = self.db + try: + self.db = GameDB(args.strip()) + print "Loading successful!" + print + self.ackMove(MOVE_OK) + backupdb.end() + except: + self.db = backupdb + print "Loading failed for unknown reasons..." + + def do_xyzzy(self,args): + """...""" + print "The air shimmers with magic..." + print "Something big is about to happen..." + print "..." + print "You hear a distant sigh of disgust, but nothing else happens." + + def default(self,args): + """For unrecognized commands""" + + ret = False + + if len(args.strip()) > 0: + (verb,obj1,obj2) = parseSentence(args) + #print verb,obj1,obj2 + ret = handle(self.db,verb,obj1,obj2) + + if not ret: + print getUnkownCmd() + else: + print ret + + def outputRoom(self): + print '* '+self.db.getRoomName()+' *' + print self.db.getRoomDescription() + + for item in self.db.getRoomContents(): + print item + #print + + def outputLook(self,dir): + desc = self.db.getDirection(getSafeDirection(dir)) + if desc: + print desc + else: + print "It's a little foggy..." + + def outputLookAt(self,text): + if text: + print text + else: + print "Excuse me?" + + def precmd(self,line): + return self.db.clearSynonyms(line) + + def postcmd(self,stop,line): + if stop: + return stop + + if self.db.isEnd(): + for line in self.db.getEnding().splitlines(): + print line + print "Press ENTER to continue..." + self.stdin.readline() + self.db.end() + return True + return False + + def preloop(self): + for line in self.db.getIntro().splitlines(): + print line + print "Press ENTER to continue..." + self.stdin.readline() + + print + + for line in self.db.getTitle().splitlines(): + print line + + print + + self.outputRoom() + + def ackMove(self,success=MOVE_OK): + if success==MOVE_OK: + self.outputRoom() + elif success==MOVE_FAILED: + print 'That way is blocked...' + else: + print success + diff --git a/lib/gamecmd.pyc b/lib/gamecmd.pyc Binary files differnew file mode 100644 index 0000000..1a377a7 --- /dev/null +++ b/lib/gamecmd.pyc diff --git a/lib/gamedb.py b/lib/gamedb.py new file mode 100644 index 0000000..afbbb48 --- /dev/null +++ b/lib/gamedb.py @@ -0,0 +1,457 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +import sqlite3 +import tempfile +import shutil +import os +from data import * + +MOVE_OK = 'Ok' +MOVE_FAILED = 'Failed' + +DEFAULTFILE = 'game.db' + +CONTENTS_PREFIX = 'There is a ' +CONTENTS_SUFFIX = ' here.' + +def getSafeDirection(string): + if string=='n': + return 'north' + elif string=='s': + return 'south' + elif string=='e': + return 'east' + elif string=='w': + return 'west' + elif string=='u': + return 'up' + elif string=='d': + return 'down' + + +class GameDB: + def __init__(self,filename=None,inplace=False): + + if not filename: + filename = filepath(DEFAULTFILE) + + self.con = None + if not inplace: + self.tempname = tempfile.mktemp() + + shutil.copyfile(filename, self.tempname) + + self.con = sqlite3.connect(self.tempname) + else: + self.con = sqlite3.connect(filename) + + self.con.isolation_level = None + + self.room = self.getStart() + + def getRoomName(self): + cur = self.con.cursor() + cur.execute("select name from Rooms where id=?",(self.room,)) + for row in cur: + return row[0] + + def getRoomDescription(self): + cur = self.con.cursor() + cur.execute("select description from Rooms where id=?",(self.room,)) + for row in cur: + return row[0] + + def getNorthDescription(self): + return self.getDirection("north") + + def getSouthDescription(self): + return self.getDirection("south") + + def getEastDescription(self): + return self.getDirection("east") + + def getWestDescription(self): + return self.getDirection("west") + + def getUpDescription(self): + return self.getDirection("up") + + def getDownDescription(self): + return self.getDirection("down") + + def moveNorth(self): + return self.move("north") + + def moveSouth(self): + return self.move("south") + + def moveEast(self): + return self.move("east") + + def moveWest(self): + return self.move("west") + + def moveUp(self): + return self.move("up") + + def moveDown(self): + return self.move("down") + + def move(self,dir): + cur = self.con.cursor() + id = self.getDirectionId(dir) + if id: + + if self.getBlock(id): + return self.getBlock(id) + + self.room = id + return MOVE_OK + return MOVE_FAILED + + def clearSynonyms(self,string): + cur = self.con.cursor() + cur.execute('select name from Objects inner join RoomContents on id=objectid where roomid=?',(self.room,)) + for object in cur: + oc = self.con.cursor() + oc.execute('select spoken,length(spoken) from Synonyms where name=? order by length(spoken) desc',(object[0],)) + for item in oc: + #print item[0]+':'+object[0] + if string.find(' '+item[0]) >= 0: + string = string.replace(' '+item[0],' '+object[0]) + break + + cur.execute('select name from Objects inner join Inventory on Objects.id=Inventory.id') + for object in cur: + oc = self.con.cursor() + oc.execute('select spoken,length(spoken) from Synonyms where name=? order by length(spoken) desc',(object[0],)) + for item in oc: + #print item[0]+':'+object[0] + if string.find(' '+item[0]) >= 0: + string = string.replace(' '+item[0],' '+object[0]) + break + + return string + + def getDirectionId(self,dir): + cur = self.con.cursor() + cur.execute("select %s from Rooms where id=?" % dir,(self.room,)) + for row in cur: + return row[0] + return None + + def getDirection(self, dir): + id = self.getDirectionId(dir) + cur = self.con.cursor() + if id: + cur.execute("select away_description from Rooms where id=?",(id,)) + for row in cur: + return row[0] + + return None + + def getRoomContents(self): + rooms = [] + cur = self.con.cursor() + cur.execute("select objectid from RoomContents where roomid=?",(self.room,)) + for row in cur: + oc = self.con.cursor() + oc.execute("select name,presence,explicit from Objects where id=?",(row[0],)) + for row in oc: + if row[2]==0: + continue + if row[1]: + rooms.append(row[1]) + else: + rooms.append(CONTENTS_PREFIX+row[0]+CONTENTS_SUFFIX) + break + return rooms + + def getInventory(self): + inv = [] + cur = self.con.cursor() + cur.execute("select name from Objects outer join Inventory on Objects.id=Inventory.id") + for row in cur: + inv.append(row[0]) + return inv + + def lookAt(self,obj): + cur = self.con.cursor() + cur.execute("select name,description from RoomContents inner join Objects on Objects.id=RoomContents.objectid where roomid=? and name=?",(self.room,obj)) + for row in cur: + return row[1] + return None + + def pickUp(self,name): + cur = self.con.cursor() + cur.execute("select id,moveable,person from Objects outer join RoomContents on Objects.id = RoomContents.objectid where name=? and roomid=?",(name,self.room)) + id = None + for obj in cur: + id = obj[0] + if obj[2] == 1: + return "I don't think %s would appreciate that." % name + if obj[1] == 0: + return "%s can't be moved." % name.title() + break + + if id == None: + return None + + cur.execute("delete from RoomContents where objectid=?",(id,)) + cur.execute("insert into Inventory(id) values(?)",(id,)) + return True + + def drop(self,name): + id = None + cur = self.con.cursor() + cur.execute("select Objects.id from Objects outer join Inventory on Objects.id = Inventory.id where name=?",(name,)) + for obj in cur: + id = obj[0] + + if id == None: + return False + + cur.execute("delete from Inventory where id=?",(id,)) + cur.execute("insert into RoomContents(objectid,roomid) values(?,?)",(id,self.room)) + return True + + def getObjId(self,name,hereonly=False): + cur = self.con.cursor() + cur.execute("select Objects.id from Objects outer join Inventory on Objects.id = Inventory.id where name=?",(name,)) + for obj in cur: + return obj[0] + cur.execute("select id from Objects outer join RoomContents on Objects.id = RoomContents.objectid where name=? and roomid=?",(name,self.room)) + for obj in cur: + return obj[0] + + cur.execute("select id from Objects where name=? and everywhere=1",(name,)) + for obj in cur: + return obj[0] + + if hereonly: + return None + + cur.execute("select id from Objects where name=?",(name,)) + for obj in cur: + return obj[0] + + return None + + def getBlock(self,id2): + cur = self.con.cursor() + cur.execute('select state, description from Block where (room1=? and room2=?) or (room1=? and room2=?)',(self.room,id2,id2,self.room)) + for row in cur: + if row[0] == 1: + return row[1] + else: + return None + return None + + def unblock(self,blockid): + cur = self.con.cursor() + cur.execute('update Block set state=0 where id=?',(blockid,)) + + def getResult(self,obj1,obj2=None,verb=None): + id1 = self.getObjId(obj1,True) + id2 = None + if obj2: + id2 = self.getObjId(obj2,True) + #print obj2,id2 + + return self.fromCombine(id1,id2,verb,'result') + + def increment(self,incid): + cur = self.con.cursor() + + state = 0 + max = 1 + + try: + incid=int(incid) + except ValueError: + incid = self.getObjId(incid,False) + + cur.execute('select state,max from NPC where id=?',(incid,)) + for row in cur: + state = row[0] + max = row[1] + + state = state + 1 + if state <= max: + try: + cur.execute('update NPC set state=? where id=?',(state,incid)) + except: + pass + + def remove(self,incid): + try: + incid=int(incid) + except ValueError: + incid = self.getObjId(incid,False) + + cur = self.con.cursor() + cur.execute('delete from Inventory where id=?',(incid,)) + + def to_inv(self,incid): + try: + incid=int(incid) + except ValueError: + incid = self.getObjId(incid,False) + + cur = self.con.cursor() + cur.execute('insert into Inventory values(?)',(incid,)) + + def setState(self,incid,state): + maxstate = 1 + try: + incid=int(incid) + except ValueError: + incid = self.getObjId(incid,False) + + cur = self.con.cursor() + cur.execute('select state,max from NPC where id=?',(incid,)) + for row in cur: + state = max(row[0],state) + maxstate = row[1] + + if state <= maxstate: + try: + cur.execute('update NPC set state=? where id=?',(state,incid)) + except: + pass + + def getEnding(self): + cur = self.con.cursor() + cur.execute("select value from State where name='Ending'") + for row in cur: + return row[0] + return 'End Game' + + def isEnd(self): + cur = self.con.cursor() + cur.execute("select value from State where name='End'") + for row in cur: + try: + id = int(row[0]) + if self.room == id: + return True + except ValueError: + return False + return False + + def getIntro(self): + cur = self.con.cursor() + cur.execute('select value from State where name=?',('Intro',)) + for row in cur: + return row[0] + return ' ' + + def getTitle(self): + cur = self.con.cursor() + cur.execute('select value from State where name=?',('Title',)) + for row in cur: + return row[0] + return ' ' + + def getAction(self,obj1,obj2=None,verb=None): + id1 = self.getObjId(obj1,True) + id2 = None + if obj2: + id2 = self.getObjId(obj2,True) + + return self.fromCombine(id1,id2,verb,'action') + + def getState(self,obj): + cur = self.con.cursor() + cur.execute('select state from NPC where id=?',(obj,)) + for row in cur: + return row[0] + return 0; + + def fromCombine(self,obj1,obj2,verb,column): + cur = self.con.cursor() + + state1 = self.getState(obj1) + state2 = self.getState(obj2) + state = max(state1,state2) + + if obj1 and obj2 and verb: + cur.execute("select %s from Combine where ((id1=? and id2=?) or (id1=? and id2=?)) and verb=? and state<=? order by state desc" % column,(obj1,obj2,obj2,obj1,verb,state)) + + elif obj1 and obj2: + cur.execute("select %s from Combine where (id1=? and id2=?) or (id1=? and id2=?) and state<=? order by state desc" % column,(obj1,obj2,obj2,obj1,state)) + + elif obj1 and verb: + cur.execute("select %s from Combine where id1=? and verb=? and state<=? order by state desc " % column,(obj1,verb,state)) + + for row in cur: + return row[0] + return None + + def checkVerb(self,spoken): + if not spoken: + return None + + cur = self.con.cursor() + cur.execute("select name from Verbonyms where spoken=?",(spoken,)) + for row in cur: + return row[0] + return spoken + + def use(self,obj1,obj2): + id2 = getObjId(obj2,True) + if not id1 or not id2: + return None + return None + + def getStart(self): + cur = self.con.cursor() + cur.execute("select value from State where name='Start'") + for row in cur: + try: + return int(row[0]) + except ValueError: + pass + + return None + + def setStart(self): + cur = self.con.cursor() + cur.execute("update State set value=? where name='Start'",(self.room,)) + + + def save(self,filename): + self.setStart() + self.con.commit() + try: + shutil.copyfile(self.tempname, filename) + except: + print "WARN: an error may have occured saving to "+filename + return False + return True + + def end(self): + self.con.close() + + try: + os.delete(self.tempname) + except: + pass + diff --git a/lib/gamedb.pyc b/lib/gamedb.pyc Binary files differnew file mode 100644 index 0000000..9e2caf4 --- /dev/null +++ b/lib/gamedb.pyc diff --git a/lib/main.py b/lib/main.py new file mode 100644 index 0000000..f7708f3 --- /dev/null +++ b/lib/main.py @@ -0,0 +1,48 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +'''Game main module. + +Contains the entry point used by the run_game.py script. + +Feel free to put all your game code here, or in other modules in this "lib" +directory. +''' +import data +import sys +from gamecmd import * + +use_curses = True + +for arg in sys.argv: + if arg=='--nocurses': + use_curses = False + +try: + if use_curses: + import curses + from curses_main import * + else: + from simple_main import * +except ImportError: + from simple_main import * + +def main(): + launch(GameCmd()) + diff --git a/lib/main.pyc b/lib/main.pyc Binary files differnew file mode 100644 index 0000000..011398e --- /dev/null +++ b/lib/main.pyc diff --git a/lib/prep.py b/lib/prep.py new file mode 100644 index 0000000..2f72d56 --- /dev/null +++ b/lib/prep.py @@ -0,0 +1,66 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +PREPOSITIONS = ['at', +'with', +'in', +'to', +'on', +'inside', +'into', +'onto', +'about', +'the', +'a', +'an', +'out'] + +def removePrep(args): + words = args.split() + astr = '' + for word in words: + try: + PREPOSITIONS.index(word) + except ValueError: + astr = astr + word + ' ' + + return astr.strip() + +def parseSentence(sentence): + """Parses the sentence and returns a verb and the two objects (if applicable)""" + elements = sentence.split() + verb = elements[0] + obj1 = None + obj2 = None + elements = elements[1:] + + for value in elements: + try: + ind = PREPOSITIONS.index(value) + elements.remove(value) + except ValueError: + continue + + if len(elements) >= 1: + obj1 = elements[0] + + if len(elements) >= 2: + obj2 = elements[1] + + return (verb,obj1,obj2) diff --git a/lib/prep.pyc b/lib/prep.pyc Binary files differnew file mode 100644 index 0000000..7bdee8d --- /dev/null +++ b/lib/prep.pyc diff --git a/lib/simple_main.py b/lib/simple_main.py new file mode 100644 index 0000000..db8f73e --- /dev/null +++ b/lib/simple_main.py @@ -0,0 +1,47 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +import sys +import textwrap +from gamecmd import * + +TERMWIDTH=80 + +class FakeStdIO(object): + def __init__(self): + self.stdin = sys.stdin + self.stdout = sys.stdout + + def write(self, str): + if len(str) >= TERMWIDTH: + for line in textwrap.wrap(str,TERMWIDTH-2): + self.stdout.write(line) + self.stdout.write("\n") + else: + self.stdout.write(str) + + def readline(self): + return self.stdin.readline() + +def launch(cmdparser): + io = FakeStdIO() + sys.stdin = io + sys.stdout = io + cmdparser.stdout = io + cmdparser.cmdloop()
\ No newline at end of file diff --git a/lib/unsure.py b/lib/unsure.py new file mode 100644 index 0000000..03f3083 --- /dev/null +++ b/lib/unsure.py @@ -0,0 +1,29 @@ +# Murder in the Park - A Robotic Mystery +# Copyright (C) 2008 Jeffrey Armstrong (a.k.a. PrintStar) +# http://jeff.rainbow-100.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# A full version of the license terms is available in LICENSE. + +import random + +UNKNOWN_CMD_REPSONSE = ["I'm not sure I understand...", +"Hmmm...", +"What?", +"I don't get it...", +"Come again?"] + +def getUnkownCmd(): + return random.choice(UNKNOWN_CMD_REPSONSE) diff --git a/lib/unsure.pyc b/lib/unsure.pyc Binary files differnew file mode 100644 index 0000000..016682e --- /dev/null +++ b/lib/unsure.pyc |
