diff --git a/gamebase.py b/gamebase.py index d6477af..ff57ee7 100644 --- a/gamebase.py +++ b/gamebase.py @@ -19,6 +19,7 @@ class GameBase(object): self.outstream = _sys.stdout self.__useFuncs = {} self.__gameEvents = {} + self.__IOCalls = {} # {str : function} self.customVals = {} # for setting flags and such self.level = None self.persist = {} # {level : {thingName : thing}} @@ -37,7 +38,7 @@ class GameBase(object): # function deligates self.onLevelLoad = None # str : level name? -> None - self.onContainer = None # list : contents -> list : newContents, float : timeOpen + #self.onContainer = None # list : contents -> list : newContents, float : timeOpen # default events and useFuncs self.registerEvent('noop', self.handleNoOp) @@ -49,6 +50,7 @@ class GameBase(object): self.registerEvent('drop', self.handleDrop) self.registerUseFunc('examine', self.examine) self.registerUseFunc('key', self.key) + self.registerUseFunc('container', self.container) # Helper functions @@ -608,8 +610,8 @@ Object can be the name of the object, or its coordinates.""" def container(self, thing): """Acts as a container. Items can be traded between the container and the player's inventory.""" - items = thing.customValues['items'] - thing.customValues['items'], timeOpen = self.onContainer(items) + items = list(thing.customValues['items']) + self.playerInv, thing.customValues['items'], timeOpen = self.getIO('container')(self.playerInv, items) return timeOpen def key(self, item, thing): @@ -636,3 +638,11 @@ callable by the player.""" They should take the event as an argument, and return True if it should always give the player a turn, False otherwise.""" self.__gameEvents[name] = func + + def registerIO(self, name, func): + """Registers a function for useFuncs and such to use.""" + self.__IOCalls[name] = func + + def getIO(self, name): + """This is so derived classes can access their IOCalls.""" + return self.__IOCalls[name] diff --git a/gamegui.py b/gamegui.py index 016b5f0..8915ed3 100644 --- a/gamegui.py +++ b/gamegui.py @@ -25,10 +25,11 @@ class App(ttk.Frame): self.invTuple = tuple(self.gameBase.playerInv.keys()) self.invNames = StringVar(value=self.invTuple) #self.project = Project() - self.tool = StringVar() - self.brush = StringVar() - self.history = [] - self.redos = [] + #self.tool = StringVar() + #self.brush = StringVar() + #self.history = [] + #self.redos = [] + self.useOnCont = None # useOn continued #self.selectedArea = (0, 0, self.project.x-1, self.project.y-1) self.parent.clipboard_clear() self.parent.clipboard_append('') @@ -144,7 +145,7 @@ class App(ttk.Frame): #print('Making the display work...') # level display self.context = Menu(self.levelDisplay) - self.context.add_command(label = 'Load Map', command = lambda: self.loadLevel('maps/apartment.xml')) + self.context.add_command(label = 'Load Map', command = lambda: self.loadLevel('maps/apartment.yml')) self.context.add_command(label = 'Go', command = lambda: self.go(self.selected[0], self.selected[1])) self.context.add_command(label = 'Run', command = lambda: self.go(self.selected[0], self.selected[1], True)) self.context.add_command(label = 'Look', command = lambda: self.look(self.selected[0], self.selected[1])) @@ -164,6 +165,7 @@ class App(ttk.Frame): self.invContext = Menu(self.invDisplay) self.invContext.add_command(label = 'Look', command = lambda: self.look(self.invTuple[self.invDisplay.curselection()[0]])) self.invContext.add_command(label = 'Use', command = lambda: self.use(self.invTuple[self.invDisplay.curselection()[0]])) + self.invContext.add_command(label = 'Use on...', command = lambda: self.useOn(self.invTuple[self.invDisplay.curselection()[0]])) self.invContext.add_command(label = 'Drop', command = lambda: self.drop(self.invTuple[self.invDisplay.curselection()[0]])) self.invDisplay.bind('<>', lambda e: self.look(self.invTuple[self.invDisplay.curselection()[0]])) self.invDisplay.bind('<3>', lambda e: self.invContext.post(e.x_root, e.y_root)) @@ -211,9 +213,12 @@ class App(ttk.Frame): def handleClick(self, event): x = int(self.levelDisplay.canvasx(event.x) / 32) y = int(self.levelDisplay.canvasy(event.y) / 32) - if (x, y) != self.selected: - self.selected = (x, y) - self.look(x, y) + if self.useOnCont == None: + if (x, y) != self.selected: + self.selected = (x, y) + self.look(x, y) + else: + self.useOn(x, y) def handleDoubleClick(self, event): x = int(self.levelDisplay.canvasx(event.x) / 32) @@ -303,6 +308,17 @@ class App(ttk.Frame): self.gameBase.gameEventLoop() self.refreshDisplay() #inefficient, but will work for now. + def useOn(self, x, y = 1): + if isinstance(x, int): + self.gameBase.use([self.useOnCont, 'on', str(x), str(y)]) + self.useOnCont = None + self.gameBase.gameEventLoop() + self.refreshDisplay() + else: # x is a string + self.useOnCont = x + print("Click on something to use {0} on.".format(x), file = self.gameBase.outstream) + self.refreshDisplay() + def take(self, x, y): self.gameBase.take([str(x), str(y)]) self.gameBase.gameEventLoop() diff --git a/gameshell.py b/gameshell.py index dfd3dc9..3d286d8 100644 --- a/gameshell.py +++ b/gameshell.py @@ -49,6 +49,7 @@ class GameShell(Shell): self.registerCommand('options', self.options) self.registerCommand('colorTest', self.colorTest) self.registerAlias('run', ['go', '-r']) + self.gameBase.registerIO('container', self.container) # Helper functions @@ -205,6 +206,62 @@ If -l is given, a map legend will be printed under the map.""" def inv(self, args): print('\n'.join([i for i in self.gameBase.playerInv])) + def container(self, inv, cont): + """container IO""" + # Pretty print: get length of the longest inventory item's name + longestLen = 0 + longestStr = "" + for i in inv: + if len(i) > longestLen: + longestLen = len(i) + longestStr = i + if longestLen > 0: + print('{{0:<{0}}}{1}'.format(longestLen+2, "Container:").format("Inv:")) + i = 0 + invKeys = tuple(inv.keys()) + while i < len(invKeys) and i < len(cont): + print('{{0:<{0}}}{1}'.format(longestLen+2, cont[i].name).format(invKeys[i])) + i += 1 + while i < len(invKeys): + print(invKeys[i]) + i += 1 + while i < len(cont): + print(' '*(longestLen+2) + cont[i].name) + i += 1 + else: + print('Container:') + for i in cont: + print(i.name) + # Now, actually interacting with the container + timeSpent = 0.5 # using a container always takes at least 1/2 second, even just opening and closing it again. + instr = input("Take, store, or exit: ") + while instr != "exit": + instr = instr.split() + if instr[0] == "take": + # take something out of the container + if instr[1] == "the": + del instr[1] + thing = ' '.join(instr[1:]) + for i in range(len(cont)): + if thing == cont[i].name: + inv[cont[i].name] = cont[i] + del cont[i] + timeSpent += 0.5 + print("{0} taken.".format(thing)) + break + elif instr[0] == "store": + # store something in the container + if instr[1] == "the": + del instr[1] + thing = ' '.join(instr[1:]) + if thing in inv: + cont.append(inv[thing]) + del inv[thing] + print("{0} stored.".format(thing)) + timeSpent += 0.5 + instr = input("Take, store, or exit: ") + return inv, cont, timeSpent + def update(self): self.gameBase.gameEventLoop()