# 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