# HG changeset patch # User KarstenBock@gmx.net # Date 1317312912 -7200 # Node ID ccf4d6cffcf169558e25eeb4da24eed73357f361 # Parent 0ffebdca7ba377dffb4257cabc8bb12ab0564f44 Removed old objects code. diff -r 0ffebdca7ba3 -r ccf4d6cffcf1 src/parpg/objects/__init__.py --- a/src/parpg/objects/__init__.py Thu Sep 29 18:09:56 2011 +0200 +++ b/src/parpg/objects/__init__.py Thu Sep 29 18:15:12 2011 +0200 @@ -12,43 +12,3 @@ # You should have received a copy of the GNU General Public License # along with PARPG. If not, see . - -import containers -import doors -import actors -import items -import sys - -OBJECT_MODULES = [containers, actors, doors, items] - -def getAllObjects (): - """Returns a dictionary with the names of the concrete game object classes - mapped to the classes themselves""" - result = {} - for module in OBJECT_MODULES: - for class_name in module.__all__: - result[class_name] = getattr (module, class_name) - return result - -def createObject(info, extra = None): - """Called when we need to get an actual object. - @type info: dict - @param info: stores information about the object we want to create - @type extra: dict - @param extra: stores additionally required attributes - @return: the object""" - # First, we try to get the type and ID, which every game_obj needs. - extra = extra or {} - try: - obj_type = info.pop('type') - ID = info.pop('id') - except KeyError: - sys.stderr.write("Error: Game object missing type or id.") - sys.exit(False) - - # add the extra info - for key, val in extra.items(): - info[key] = val - - # this is for testing purposes - return getAllObjects()[obj_type](ID, **info) diff -r 0ffebdca7ba3 -r ccf4d6cffcf1 src/parpg/objects/actors.py --- a/src/parpg/objects/actors.py Thu Sep 29 18:09:56 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ -# This file is part of PARPG. - -# PARPG 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. - -# PARPG 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 PARPG. If not, see . - -from random import randrange - - -from fife import fife - -from base import GameObject, Living, Scriptable, CharStats -from composed import CarryableItem -from parpg.inventory import Inventory - -"""All actors go here. Concrete classes only.""" - -__all__ = ["PlayerCharacter", "NonPlayerCharacter", ] - -_AGENT_STATE_NONE, _AGENT_STATE_IDLE, _AGENT_STATE_APPROACH, _AGENT_STATE_RUN, _AGENT_STATE_WANDER, _AGENT_STATE_TALK = xrange(6) - -class ActorBehaviour (fife.InstanceActionListener): - """Fife agent listener""" - def __init__(self, layer): - fife.InstanceActionListener.__init__(self) - self.layer = layer - self.agent = None - self.state = None - self.speed = 0 - self.idle_counter = 1 - - def attachToLayer(self, agent_ID): - """Attaches to a certain layer - @type agent_ID: String - @param agent_ID: ID of the layer to attach to. - @return: None""" - self.agent = self.layer.getInstance(agent_ID) - self.agent.addActionListener(self) - self.state = _AGENT_STATE_NONE - - def getX(self): - """Get the NPC's x position on the map. - @rtype: integer" - @return: the x coordinate of the NPC's location""" - return self.agent.getLocation().getLayerCoordinates().x - - def getY(self): - """Get the NPC's y position on the map. - @rtype: integer - @return: the y coordinate of the NPC's location""" - return self.agent.getLocation().getLayerCoordinates().y - - def onNewMap(self, layer): - """Sets the agent onto the new layer.""" - if self.agent is not None: - self.agent.removeActionListener(self) - - self.agent = layer.getInstance(self.parent.ID) - self.agent.addActionListener(self) - self.state = _AGENT_STATE_NONE - self.idle_counter = 1 - - def idle(self): - """@return: None""" - self.state = _AGENT_STATE_IDLE - self.agent.act('stand', self.agent.getFacingLocation()) - - def onInstanceActionFinished(self, instance, action): - pass - -class PCBehaviour (ActorBehaviour): - def __init__(self, parent=None, layer=None): - super(PCBehaviour, self).__init__(layer) - self.parent = parent - self.idle_counter = 1 - self.speed = 0 - self.nextAction = None - self.agent = None - - def onInstanceActionFinished(self, instance, action): - """@type instance: ??? - @param instance: ??? - @type action: ??? - @param action: ??? - @return: None""" - # First we reset the next behavior - act = self.nextAction - self.nextAction = None - self.idle() - - if act: - act.execute() - - if(action.getId() != 'stand'): - self.idle_counter = 1 - else: - self.idle_counter += 1 - - -class NPCBehaviour(ActorBehaviour): - def __init__(self, Parent=None, Layer=None): - super(NPCBehaviour, self).__init__(Layer) - - self.parent = Parent - self.state = _AGENT_STATE_NONE - self.pc = None - self.target_loc = None - self.nextAction = None - - # hard code these for now - self.distRange = (2, 4) - # these are parameters to lower the rate of wandering - # wander rate is the number of "IDLEs" before a wander step - # this could be set for individual NPCs at load time - # or thrown out altogether. - self.wanderCounter = 0 - self.wanderRate = 9 - - def getTargetLocation(self): - """@rtype: fife.Location - @return: NPC's position""" - x = self.getX() - y = self.getY() - if self.state == _AGENT_STATE_WANDER: - """ Random Target Location """ - l = [0, 0] - for i in range(len(l)): - sign = randrange(0, 2) - dist = randrange(self.distRange[0], self.distRange[1]) - if sign == 0: - dist *= -1 - l[i] = dist - x += l[0] - y += l[1] - # Random walk is - # rl = randint(-1, 1);ud = randint(-1, 1);x += rl;y += ud - l = fife.Location(self.agent.getLocation()) - l.setLayerCoordinates(fife.ModelCoordinate(x, y)) - return l - - def onInstanceActionFinished(self, instance, action): - """What the NPC does when it has finished an action. - Called by the engine and required for InstanceActionListeners. - @type instance: fife.Instance - @param instance: self.agent (the NPC listener is listening for this - instance) - @type action: ??? - @param action: ??? - @return: None""" - if self.state == _AGENT_STATE_WANDER: - self.target_loc = self.getTargetLocation() - self.idle() - - - def idle(self): - """Controls the NPC when it is idling. Different actions - based on the NPC's state. - @return: None""" - if self.state == _AGENT_STATE_NONE: - self.state = _AGENT_STATE_IDLE - self.agent.act('stand', self.agent.getFacingLocation()) - elif self.state == _AGENT_STATE_IDLE: - if self.wanderCounter > self.wanderRate: - self.wanderCounter = 0 - self.state = _AGENT_STATE_WANDER - else: - self.wanderCounter += 1 - self.state = _AGENT_STATE_NONE - - self.target_loc = self.getTargetLocation() - self.agent.act('stand', self.agent.getFacingLocation()) - elif self.state == _AGENT_STATE_WANDER: - self.parent.wander(self.target_loc) - self.state = _AGENT_STATE_NONE - elif self.state == _AGENT_STATE_TALK: - self.agent.act('stand', self.pc.getLocation()) - -class CharacterBase(GameObject, CharStats, Living): - """Base class for Characters""" - def __init__(self, ID, agent_layer=None, inventory=None, text="", - primary_stats=None, secondary_stats=None, **kwargs): - GameObject.__init__(self, ID, text=text, **kwargs) - CharStats.__init__(self, **kwargs) - Living.__init__(self, **kwargs) - self.statistics = {} - if primary_stats is not None: - for primary_stat in primary_stats: - name = primary_stat.name - self.statistics[name] = primary_stat - if secondary_stats is not None: - for secondary_stat in primary_stats: - long_name = secondary_stat.long_name - self.statistics[long_name] = secondary_stat - short_name = secondary_stat.short_name - self.statistics[short_name] = secondary_stat - secondary_stat.attach(self) - self.behaviour = None - if inventory == None: - self.inventory = Inventory() - else: - self.inventory = inventory - self.state = _AGENT_STATE_NONE - self.layer_id = agent_layer.getId() - self.createBehaviour(agent_layer) - - def createBehaviour(self, layer): - """Creates the behaviour for this actor. - @return: None""" - pass - - def setup(self): - """@return: None""" - self.behaviour.attachToLayer(self.ID) - - def start(self): - """@return: None""" - self.behaviour.idle() - - def teleport(self, location): - """Teleports a Character instantly to the given location. - @type location: fife.Location - @param location: Target coordinates for Character. - @return: None""" - self.state = _AGENT_STATE_IDLE - self.behaviour.nextAction = None - self.behaviour.agent.setLocation(location) - - def give (self, item, actor): - """Gives the specified item to the different actor. Raises an exception if the item was invalid or not found - @type item: Carryable - @param item: The item object to give - @param actor: Person to give item to""" - if item == None: - raise ValueError("I don't have %s" % item.name) - self.inventory.takeItem(item) - actor.inventory.placeItem(item) - - def hasItem(self, item_type): - """Returns wether an item is present in the players inventory or not - @param item_type: ID of the item - @type item_type: str - @return: True when the item is present, False when not""" - return self.inventory.findItem(item_type=item_type) - - def itemCount(self, item_type=""): - """Returns number of all items or items specified by item_type - the player has. - @param item_type: ID of the item, can be empty - @type item_type: str - @return: Number of items""" - return self.inventory.count(item_type) - - def getLocation(self): - """Get the NPC's position as a fife.Location object. Basically a - wrapper. - @rtype: fife.Location - @return: the location of the NPC""" - return self.behaviour.agent.getLocation() - - def run(self, location): - """Makes the PC run to a certain location - @type location: fife.ScreenPoint - @param location: Screen position to run to. - @return: None""" - self.state = _AGENT_STATE_RUN - self.behaviour.nextAction = None - self.behaviour.agent.move('run', location, self.behaviour.speed + 1) - - def walk(self, location): - """Makes the PC walk to a certain location. - @type location: fife.ScreenPoint - @param location: Screen position to walk to. - @return: None""" - self.state = _AGENT_STATE_RUN - self.behaviour.nextAction = None - self.behaviour.agent.move('walk', location, self.behaviour.speed - 1) - - def getStateForSaving(self): - """Returns state for saving - """ - ret_dict = GameObject.getStateForSaving(self) - ret_dict["Inventory"] = self.inventory.serializeInventory() - return ret_dict - - def _getCoords(self): - """Get-er property function""" - return (self.getLocation().getMapCoordinates().x, - self.getLocation().getMapCoordinates().y) - - def _setCoords(self, coords): - """Set-er property function""" - map_coords = self.getLocation().getMapCoordinates() - map_coords.X, map_coords.Y = float(coords[0]), float (coords[1]) - self.teleport(map_coords) - - coords = property (_getCoords, _setCoords, - doc="Property allowing you to get and set the object's \ - coordinates via tuples") - -class PlayerCharacter (CharacterBase): - """PC class""" - def __init__ (self, ID, agent_layer=None, inventory=None, - text="Its you. Who would've thought that?", **kwargs): - if inventory == None: - inventory = Inventory() - inventory.placeItem(CarryableItem(ID=456, name="Dagger123")) - inventory.placeItem(CarryableItem(ID=555, name="Beer")) - inventory.placeItem(CarryableItem(ID=616, - name="Pamphlet", - image="/gui/inv_images/inv_pamphlet.png")) - CharacterBase.__init__(self, ID, agent_layer, inventory, text, **kwargs) - self.people_i_know = set() - self.attributes.append("PC") - - def getStateForSaving(self): - """Returns state for saving - """ - ret_dict = super(PlayerCharacter, self).getStateForSaving() - ret_dict["PeopleKnown"] = self.people_i_know - return ret_dict - - def meet(self, npc): - """Record that the PC has met a certain NPC - @type npc: str - @param npc: The NPC's name or id""" - if npc in self.people_i_know: - # we could raise an error here, but should probably be a warn - # raise RuntimeError("I already know %s" % npc) - return - self.people_i_know.add(npc) - - def met(self, npc): - """Indicate whether the PC has met this npc before - @type npc: str - @param npc: The NPC's name or id - @return: None""" - return npc in self.people_i_know - - def createBehaviour(self, layer): - """Creates the behaviour for this actor. - @return: None""" - self.behaviour = PCBehaviour(self, layer) - - def approach(self, location, action=None): - """Approaches a location and then perform an action (if set). - @type loc: fife.Location - @param loc: the location to approach - @type action: Action - @param action: The action to schedule for execution after the approach. - @return: None""" - self.state = _AGENT_STATE_APPROACH - self.behaviour.nextAction = action - boxLocation = tuple([int(float(i)) for i in location]) - l = fife.Location(self.behaviour.agent.getLocation()) - l.setLayerCoordinates(fife.ModelCoordinate(*boxLocation)) - self.behaviour.agent.move('run', l, self.behaviour.speed + 1) - -class NonPlayerCharacter(CharacterBase, Scriptable): - """NPC class""" - def __init__(self, ID, agent_layer=None, name='NPC', \ - text='A nonplayer character', inventory=None, - real_name='NPC', dialogue=None, **kwargs): - # init game object - CharacterBase.__init__(self, ID, agent_layer=agent_layer, - inventory=inventory, name=name, - real_name=real_name, text=text, **kwargs) - Scriptable.__init__(self, **kwargs) - - self.attributes.append("NPC") - self.dialogue = dialogue - - def prepareStateForSaving(self, state): - """Prepares state for saving - @type state: dictionary - @param state: State of the object - """ - CharacterBase.prepareStateForSaving(self, state) - del state["behaviour"] - - def getStateForSaving(self): - """Returns state for saving - """ - ret_dict = CharacterBase.getStateForSaving(self) - ret_dict["Lives"] = self.lives - ret_dict["State"] = self.behaviour.state - return ret_dict - - def createBehaviour(self, layer): - """Creates the behaviour for this actor. - @return None """ - self.behaviour = NPCBehaviour(self, layer) - - def wander(self, location): - """Nice slow movement for random walking. - @type location: fife.Location - @param location: Where the NPC will walk to. - @return: None""" - self.behaviour.agent.move('walk', location, self.behaviour.speed - 1) - - def talk(self, pc): - """Makes the NPC ready to talk to the PC - @return: None""" - self.behaviour.state = _AGENT_STATE_TALK - self.behaviour.pc = pc.behaviour.agent - self.behaviour.idle() diff -r 0ffebdca7ba3 -r ccf4d6cffcf1 src/parpg/objects/base.py --- a/src/parpg/objects/base.py Thu Sep 29 18:09:56 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,508 +0,0 @@ -# This file is part of PARPG. - -# PARPG 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. - -# PARPG 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 PARPG. If not, see . - -"""Containes classes defining the base properties of all interactable in-game - objects (such as Carryable, Openable, etc. These are generally independent - classes, which can be combined in almost any way and order. - - Some rules that should be followed when CREATING base property classes: - - 1. If you want to support some custom initialization arguments, - always define them as keyword ones. Only GameObject would use - positional arguments. - 2. In __init__() **ALWAYS** call the parent's __init__(**kwargs), preferably - *at the end* of your __init__() (makes it easier to follow) - 3. There should always be an attributes.append(x) call on __init__ - (where X is the name of the class) - - EXAMPLE: - - class Openable(object): - def __init__ (self, is_open = True, **kwargs): - self.attribbutes.append("openable") - self.is_open = is_open - super(Openable,self).__init__ (**kwargs) - - - Some rules are to be followed when USING the base classes to make composed - ones: - - 1. The first parent should always be the base GameObject class - 2. Base classes other than GameObject can be inherited in any order - 3. The __init__ functoin of the composed class should always invoke the - parent's __init__() *before* it starts customizing any variables. - - EXAMPLE: - - class TinCan (GameObject, Container, Scriptable, Destructable, Carryable): - def __init__ (self, *args, **kwargs): - super(TinCan,self).__init__ (*args, **kwargs) - self.name = 'Tin Can'""" - -class BaseObject(object): - """A base class that supports dynamic attributes functionality""" - def __init__ (self): - if not self.__dict__.has_key("attributes"): - self.attributes = [] - - def trueAttr(self, attr): - """Method that checks if the instance has an attribute""" - return attr in self.attributes - - def getStateForSaving(self): - """Returns state for saving - """ - state = {} - state["attributes"] = self.attributes - return state - -class DynamicObject (BaseObject): - """Class with basic attributes""" - def __init__ (self, name="Dynamic object", real_name=None, image=None, **kwargs): - """Initialise minimalistic set of data - @type name: String - @param name: Object display name - @type image: String or None - @param name: Filename of image to use in inventory""" - BaseObject.__init__(self) - self.name = name - self.real_name = real_name or name - self.image = image - - def prepareStateForSaving(self, state): - """Prepares state for saving - @type state: dictionary - @param state: State of the object - """ - pass - - def restoreState(self, state): - """Restores a state from a saved state - @type state: dictionary - @param state: Saved state - """ - self.__dict__.update(state) - - def __getstate__(self): - odict = self.__dict__.copy() - self.prepareStateForSaving(odict) - return odict - - def __setstate__(self, state): - self.restoreState(state) - - def getStateForSaving(self): - """Returns state for saving - """ - state = BaseObject.getStateForSaving(self) - state["Name"] = self.name - state["RealName"] = self.real_name - state["Image"] = self.image - return state - -class GameObject (DynamicObject): - """A base class to be inherited by all game objects. This must be the - first class (left to right) inherited by any game object.""" - def __init__ (self, ID, gfx = None, xpos = 0.0, ypos = 0.0, map_id = None, - blocking=True, name="Generic object", real_name="Generic object", text="Item description", - desc="Detailed description", **kwargs): - """Set the basic values that are shared by all game objects. - @type ID: String - @param ID: Unique object identifier. Must be present. - @type gfx: Dictionary - @param gfx: Dictionary with graphics for the different contexts - @type coords 2-item tuple - @param coords: Initial coordinates of the object. - @type map_id: String - @param map_id: Identifier of the map where the object is located - @type blocking: Boolean - @param blocking: Whether the object blocks character movement - @type name: String - @param name: The display name of this object (e.g. 'Dirty crate') - @type text: String - @param text: A longer description of the item - @type desc: String - @param desc: A long description of the item that is displayed when it is examined - """ - DynamicObject.__init__(self, name, real_name, **kwargs) - self.ID = ID - self.gfx = gfx or {} - self.X = xpos - self.Y = ypos - self.map_id = map_id - self.blocking = True - self.text = text - self.desc = desc - - def _getCoords(self): - """Get-er property function""" - return (self.X, self.Y) - - def _setCoords(self, coords): - """Set-er property function""" - self.X, self.Y = float(coords[0]), float (coords[1]) - - coords = property (_getCoords, _setCoords, - doc = "Property allowing you to get and set the object's \ - coordinates via tuples") - - def __repr__(self): - """A debugging string representation of the object""" - return "<%s:%s>" % (self.name, self.ID) - - def getStateForSaving(self): - """Returns state for saving - """ - state = super(GameObject, self).getStateForSaving() - state["ObjectModel"] = self.gfx - state["Text"] = self.text - state["Desc"] = self.desc - state["Position"] = list(self.coords) - return state - - -class Scriptable (BaseObject): - """Allows objects to have predefined parpg executed on certain events""" - def __init__ (self, parpg = None, **kwargs): - """Init operation for scriptable objects - @type parpg: Dictionary - @param parpg: Dictionary where the event strings are keys. The - values are 3-item tuples (function, positional_args, keyword_args)""" - BaseObject.__init__(self) - self.attributes.append("scriptable") - self.parpg = parpg or {} - - def runScript (self, event): - """Runs the script for the given event""" - if event in self.parpg and self.parpg[event]: - func, args, kwargs = self.parpg[event] - func (*args, **kwargs) - - def setScript (self, event, func, args = None , kwargs = None): - """Sets a script to be executed for the given event.""" - args = args or {} - kwargs = kwargs or {} - self.parpg[event] = (func, args, kwargs) - -class Openable(DynamicObject, Scriptable): - """Adds open() and .close() capabilities to game objects - The current state is tracked by the .is_open variable""" - def __init__(self, is_open = True, **kwargs): - """Init operation for openable objects - @type is_open: Boolean - @param is_open: Keyword boolean argument sets the initial state.""" - DynamicObject.__init__(self, **kwargs) - Scriptable.__init__(self, **kwargs) - self.attributes.append("openable") - self.is_open = is_open - - def open(self): - """Opens the object, and runs an 'onOpen' script, if present""" - self.is_open = True - try: - if self.trueAttr ('scriptable'): - self.runScript('onOpen') - except AttributeError : - pass - - def close(self): - """Opens the object, and runs an 'onClose' script, if present""" - self.is_open = False - try: - if self.trueAttr ('scriptable'): - self.runScript('onClose') - except AttributeError : - pass - -class Lockable (Openable): - """Allows objects to be locked""" - def __init__ (self, locked = False, is_open = True, **kwargs): - """Init operation for lockable objects - @type locked: Boolean - @param locked: Keyword boolen argument sets the initial locked state. - @type is_open: Boolean - @param is_open: Keyword boolean argument sets the initial open state. - It is ignored if locked is True -- locked objects - are always closed.""" - self.attributes.append("lockable") - self.locked = locked - if locked : - is_open = False - Openable.__init__( self, is_open, **kwargs ) - - def unlock (self): - """Handles unlocking functionality""" - self.locked = False - - def lock (self): - """Handles locking functionality""" - self.close() - self.locked = True - - def open (self, *args, **kwargs): - """Adds a check to see if the object is unlocked before running the - .open() function of the parent class""" - if self.locked: - raise ValueError ("Open failed: object locked") - super (Lockable, self).open(*args, **kwargs) - -class Carryable (DynamicObject): - """Allows objects to be stored in containers""" - def __init__ (self, weight=0.0, bulk=0.0, **kwargs): - DynamicObject.__init__(self, **kwargs) - self.attributes.append("carryable") - self.in_container = None - self.on_map = None - self.agent = None - self.weight = weight - self.bulk = bulk - - def getInventoryThumbnail(self): - """Returns the inventory thumbnail of the object""" - # TODO: Implement properly after the objects database is in place - if self.image == None: - return "gui/inv_images/inv_litem.png" - else: - return self.image - -class Container (DynamicObject, Scriptable): - """Gives objects the capability to hold other objects""" - class TooBig(Exception): - """Exception to be raised when the object is too big - to fit into container""" - pass - - class SlotBusy(Exception): - """Exception to be raised when the requested slot is occupied""" - pass - - class ItemSelf(Exception): - """Exception to be raised when trying to add the container as an item""" - pass - - def __init__ (self, capacity = 0, items = None, **kwargs): - DynamicObject.__init__(self, **kwargs) - Scriptable.__init__(self, **kwargs) - self.attributes.append("container") - self.items = {} - self.capacity = capacity - if items: - for item in items: - self.placeItem(item) - - def placeItem (self, item, index=None): - """Adds the provided carryable item to the inventory. - Runs an 'onStoreItem' script, if present""" - if item is self: - raise self.ItemSelf("Paradox: Can't contain myself") - if not item.trueAttr ('carryable'): - raise TypeError ('%s is not carryable!' % item) - if self.capacity and self.getContentsBulk()+item.bulk > self.capacity: - raise self.TooBig ('%s is too big to fit into %s' % (item, self)) - item.in_container = self - if index == None: - self._placeAtVacant(item) - else: - if index in self.items : - raise self.SlotBusy('Slot %d is busy in %s' % (index, - self.name)) - self.items[index] = item - - # Run any parpg associated with storing an item in the container - try: - if self.trueAttr ('scriptable'): - self.runScript('onPlaceItem') - except AttributeError : - pass - - def _placeAtVacant(self, item): - """Places an item at a vacant slot""" - vacant = None - for i in range(len(self.items)): - if i not in self.items : - vacant = i - if vacant == None : - vacant = len(self.items) - self.items[vacant] = item - - def takeItem (self, item): - """Takes the listed item out of the inventory. - Runs an 'onTakeItem' script""" - if not item in self.items.values(): - raise ValueError ('I do not contain this item: %s' % item) - del self.items[self.items.keys()[self.items.values().index(item)]] - - # Run any parpg associated with popping an item out of the container - try: - if self.trueAttr ('scriptable'): - self.runScript('onTakeItem') - except AttributeError : - pass - - def replaceItem(self, old_item, new_item): - """Replaces the old item with the new one - @param old_item: Old item which is removed - @type old_item: Carryable - @param new_item: New item which is added - @type new_item: Carryable - """ - old_index = self.indexOf(old_item.ID) - self.removeItem(old_item) - self.placeItem(new_item, old_index) - - def removeItem(self, item): - """Removes an item from the container, basically the same as 'takeItem' - but does run a different script. This should be used when an item is - destroyed rather than moved out. - Runs 'onRemoveItem' script - """ - if not item in self.items.values(): - raise ValueError ('I do not contain this item: %s' % item) - del self.items[self.items.keys()[self.items.values().index(item)]] - - # Run any parpg associated with popping an item out of the container - try: - if self.trueAttr ('scriptable'): - self.runScript('onRemoveItem') - except AttributeError : - pass - - def count (self, item_type = ""): - """Returns the number of items""" - if item_type: - ret_count = 0 - for index in self.items : - if self.items[index].item_type == item_type: - ret_count += 1 - return ret_count - return len(self.items) - - def getContentsBulk(self): - """Bulk of the container contents""" - return sum((item.bulk for item in self.items.values())) - - def getItemAt(self, index): - return self.items[index] - - def indexOf(self, ID): - """Returns the index of the item with the passed ID""" - for index in self.items : - if self.items[index].ID == ID: - return index - return None - - def findItemByID(self, ID): - """Returns the item with the passed ID""" - for i in self.items : - if self.items[i].ID == ID: - return self.items[i] - return None - - def findItemByItemType(self, item_type): - """Returns the item with the passed item_type""" - for index in self.items : - if self.items[index].item_type == item_type: - return self.items[index] - return None - - def findItem(self, **kwargs): - """Find an item in container by attributes. All params are optional. - @type name: String - @param name: If the name is non-unique, return first matching object - @type kind: String - @param kind: One of the possible object types - @return: The item matching criteria or None if none was found""" - for index in self.items : - if "name" in kwargs and self.items[index].name != kwargs["name"]: - continue - if "ID" in kwargs and self.items[index].ID != kwargs["ID"]: - continue - if "kind" in kwargs and not self.items[index].trueAttr(kwargs["kind"]): - continue - if "item_type" in kwargs and self.items[index].item_type != kwargs["item_type"]: - continue - return self.items[index] - return None - - def serializeItems(self): - """Returns the items as a list""" - items = [] - for index, item in self.items.iteritems(): - item_dict = item.getStateForSaving() - item_dict["index"] = index - item_dict["type"] = item.item_type - items.append(item_dict) - return items - - def getStateForSaving(self): - """Returns state for saving - """ - ret_state = DynamicObject.getStateForSaving(self) - ret_state["Items"] = self.serializeItems() - return ret_state - -class Living (BaseObject): - """Objects that 'live'""" - def __init__ (self, **kwargs): - BaseObject.__init__(self) - self.attributes.append("living") - self.lives = True - - def die(self): - """Kills the object""" - self.lives = False - -class CharStats (BaseObject): - """Provides the object with character statistics""" - def __init__ (self, **kwargs): - BaseObject.__init__(self) - self.attributes.append("charstats") - -class Wearable (BaseObject): - """Objects than can be weared""" - def __init__ (self, slots, **kwargs): - """Allows the object to be worn somewhere on the body (e.g. pants)""" - BaseObject.__init__(self) - self.attributes.append("wearable") - if isinstance(slots, tuple) : - self.slots = slots - else : - self.slots = (slots,) - -class Usable (BaseObject): - """Allows the object to be used in some way (e.g. a Zippo lighter - to make a fire)""" - def __init__ (self, actions = None, **kwargs): - BaseObject.__init__(self) - self.attributes.append("usable") - self.actions = actions or {} - -class Weapon (BaseObject): - """Allows the object to be used as a weapon""" - def __init__ (self, **kwargs): - BaseObject.__init__(self) - self.attributes.append("weapon") - -class Destructable (BaseObject): - """Allows the object to be destroyed""" - def __init__ (self, **kwargs): - BaseObject.__init__(self) - self.attributes.append("destructable") - -class Trapable (BaseObject): - """Provides trap slots to the object""" - def __init__ (self, **kwargs): - BaseObject.__init__(self) - self.attributes.append("trapable") diff -r 0ffebdca7ba3 -r ccf4d6cffcf1 src/parpg/objects/composed.py --- a/src/parpg/objects/composed.py Thu Sep 29 18:09:56 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -# This file is part of PARPG. - -# PARPG 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. - -# PARPG 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 PARPG. If not, see . - -"""Composite game object classes are kept here""" - -from base import GameObject, Container, Lockable, \ - Scriptable, Trapable, Destructable, Carryable, \ - Usable - -class ImmovableContainer(GameObject, Container, Lockable, Scriptable, - Trapable, Destructable): - """Composite class that can be used for crates, chests, etc.""" - def __init__ (self, **kwargs): - GameObject .__init__(self, **kwargs) - Container .__init__(self, **kwargs) - Lockable .__init__(self, **kwargs) - Scriptable .__init__(self, **kwargs) - Trapable .__init__(self, **kwargs) - Destructable .__init__(self, **kwargs) - self.blocking = True - -class SingleItemContainer (Container) : - """Container that can only store a single item. - This class can represent single-item inventory slots""" - def __init__ (self, **kwargs): - Container.__init__(self, **kwargs) - - def placeItem(self,item, index=None): - if len(self.items) > 0 : - raise self.SlotBusy ('%s is already busy' % self) - Container.placeItem(self, item) - -class CarryableItem (GameObject, Carryable, Usable): - """Composite class that will be used for all carryable items""" - def __init__(self, item_type, **kwargs): - GameObject.__init__(self, **kwargs) - Carryable.__init__(self, **kwargs) - Usable.__init__(self, **kwargs) - self.item_type = item_type - - def prepareStateForSaving(self, state): - """Prepares state for saving - @type state: dictionary - @param state: State of the object - """ - super(CarryableItem, self).prepareStateForSaving(state) - if state.has_key("in_container"): - del state["in_container"] - if state.has_key("on_map"): - del state["on_map"] - if state.has_key("agent"): - del state["agent"] - - def getStateForSaving(self): - """Returns state for saving - @type state: dictionary - @param state: State of the object - """ - ret_dict = self.__dict__.copy() - self.prepareStateForSaving(ret_dict) - return ret_dict - -class CarryableContainer(Container, CarryableItem): - """Composite class that will be used for backpack, pouches, etc.""" - def __init__ (self, item_type, **kwargs): - Container.__init__(self, **kwargs) - CarryableItem.__init__(self, item_type, **kwargs) - self.own_bulk = 0 - self.own_weight = 0 - - def getWeight(self): - """Resulting weight of a container""" - return sum((item.weight for item in self.items.values()), - self.own_weight) - - def setWeight(self, weight): - """Set container's own weight. - For compatibility with inherited methods""" - self.own_weight = weight - - weight = property(getWeight, setWeight, "Total weight of container") - - def getBulk(self): - """Resulting bulk of container""" - return self.getContentsBulk()+self.own_bulk - - def setBulk(self, bulk): - """Set container's own bulk. For compatibility with inherited methods""" - self.own_bulk = bulk - - bulk = property(getBulk, setBulk, "Total bulk of container") - - def __repr__(self): - return "[%s" % self.name + str(reduce((lambda a, b: a + ', ' + \ - str(self.items[b])), self.items, "")) + " ]" - - def getStateForSaving(self): - """Returns state for saving - @type state: dictionary - @param state: State of the object - """ - state = Container.getStateForSaving(self) - if not state.has_key("attributes"): - state["attributes"] = [] - state["attributes"].append("Container") - state.update(CarryableItem.getStateForSaving(self)) - return state - -class CarryableSingleItemContainer (SingleItemContainer, CarryableContainer) : - """Container that can only store a single item. - This class can represent single-item inventory slots""" - def __init__ (self, item_type, **kwargs): - SingleItemContainer.__init__(self, **kwargs) - CarryableContainer.__init__(self, item_type, **kwargs) - -class Door(GameObject, Lockable, Scriptable, Trapable): - """Composite class that can be used to create doors on a map.""" - def __init__ (self, target_map_name = 'my-map', - target_x = 0.0, target_y = 0.0, **kwargs): - GameObject.__init__(self, **kwargs) - Lockable.__init__(self, **kwargs) - Scriptable.__init__(self, **kwargs) - Trapable.__init__(self, **kwargs) - self.attributes.append("door") - self.target_map_name = target_map_name - self.target_pos = (target_x, target_y) - self.blocking = True - - def getStateForSaving(self): - """Returns state for saving - """ - ret_dict = super(Door, self).getStateForSaving() - return ret_dict diff -r 0ffebdca7ba3 -r ccf4d6cffcf1 src/parpg/objects/containers.py --- a/src/parpg/objects/containers.py Thu Sep 29 18:09:56 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -# This file is part of PARPG. - -# PARPG 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. - -# PARPG 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 PARPG. If not, see . - -"""Containes classes defining concrete container game objects like crates, - barrels, chests, etc.""" - -__all__ = ["WoodenCrate", "Footlocker"] - -_AGENT_STATE_NONE, _AGENT_STATE_OPENED, _AGENT_STATE_CLOSED, \ -_AGENT_STATE_OPENING, _AGENT_STATE_CLOSING = xrange(5) - -from composed import ImmovableContainer -from fife import fife - -class WoodenCrate (ImmovableContainer): - def __init__(self, object_id, name = 'Wooden Crate', - text = 'A battered crate', gfx = 'crate', **kwargs): - ImmovableContainer.__init__(self, ID = object_id, name = name, - gfx = gfx, text = text, **kwargs) - -class ContainerBehaviour(fife.InstanceActionListener): - def __init__(self, parent = None, agent_layer = None): - fife.InstanceActionListener.__init__(self) - self.parent = parent - self.layer = agent_layer - self.state = _AGENT_STATE_CLOSED - self.agent = None - - def attachToLayer(self, agent_id): - """ Attaches to a certain layer - @type agent_id: String - @param agent_id: ID of the layer to attach to. - @return: None""" - self.agent = self.layer.getInstance(agent_id) - self.agent.addActionListener(self) - self.state = _AGENT_STATE_CLOSED - self.agent.act('closed', self.agent.getLocation()) - - def onInstanceActionFinished(self, instance, action): - """What the Actor does when it has finished an action. - Called by the engine and required for InstanceActionListeners. - @type instance: fife.Instance - @param instance: self.agent (the Actor listener is listening for this - instance) - @type action: ??? - @param action: ??? - @return: None""" - if self.state == _AGENT_STATE_OPENING: - self.agent.act('opened', self.agent.getFacingLocation(), True) - self.state = _AGENT_STATE_OPENED - if self.state == _AGENT_STATE_CLOSING: - self.agent.act('closed', self.agent.getFacingLocation(), True) - self.state = _AGENT_STATE_CLOSED - - def open (self): - if self.state != _AGENT_STATE_OPENED and self.state != \ - _AGENT_STATE_OPENING: - self.agent.act('open', self.agent.getLocation()) - self.state = _AGENT_STATE_OPENING - - def close(self): - if self.state != _AGENT_STATE_CLOSED and self.state != \ - _AGENT_STATE_CLOSING: - self.agent.act('close', self.agent.getLocation()) - self.state = _AGENT_STATE_CLOSING - -class Footlocker(ImmovableContainer): - def __init__ (self, object_id, agent_layer=None, name = 'Footlocker', - text = 'A Footlocker', gfx = 'lock_box_metal01', **kwargs): - ImmovableContainer.__init__(self, ID = object_id, name = name, - gfx = gfx, text = text, **kwargs) - self.behaviour = None - - self.attributes.append("AnimatedContainer") - self.createBehaviour(agent_layer) - - def prepareStateForSaving(self, state): - """Prepares state for saving - @type state: dictionary - @param state: State of the object - """ - ImmovableContainer.prepareStateForSaving(self, state) - del state["behaviour"] - - def createBehaviour(self, layer): - self.behaviour = ContainerBehaviour(self, layer) - - def setup(self): - """@return: None""" - self.behaviour.attachToLayer(self.ID) - - def open (self): - super (Footlocker, self).open() - self.behaviour.open() - - def close(self): - super (Footlocker, self).close() - self.behaviour.close() diff -r 0ffebdca7ba3 -r ccf4d6cffcf1 src/parpg/objects/doors.py --- a/src/parpg/objects/doors.py Thu Sep 29 18:09:56 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# This file is part of PARPG. - -# PARPG 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. - -# PARPG 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 PARPG. If not, see . - -"""Containes classes defining concrete door game objects.""" - -__all__ = ["ShantyDoor", ] - -from composed import Door - -class ShantyDoor(Door): - def __init__ (self, ID, name = 'Shanty Door', text = 'A door', - gfx = 'shanty-door', target_map_name = 'my-map', - target_x = 0.0, target_y = 0.0, **kwargs): - Door.__init__(self, ID = ID, name = name, text = text, gfx = gfx, - target_map_name = target_map_name, - target_x = target_x, - target_y = target_y, **kwargs) diff -r 0ffebdca7ba3 -r ccf4d6cffcf1 src/parpg/objects/items.py --- a/src/parpg/objects/items.py Thu Sep 29 18:09:56 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -# This file is part of PARPG. - -# PARPG 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. - -# PARPG 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 PARPG. If not, see . - -__all__ = ["MapItem", ] - -from composed import CarryableItem - -class MapItem(CarryableItem): - """Item that is lying on a map""" - def __init__(self, ID, item_type, item, name = 'Item', text = 'An item', - gfx = 'item', **kwargs): - CarryableItem.__init__(self, ID = ID, item_type = item_type, name = name, - text = text, gfx = gfx, **kwargs) - self.item = item