diff gamemodel.py @ 0:7a89ea5404b1

Initial commit of parpg-core.
author M. George Hansen <technopolitica@gmail.com>
date Sat, 14 May 2011 01:12:35 -0700
parents
children 06145a6ee387
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gamemodel.py	Sat May 14 01:12:35 2011 -0700
@@ -0,0 +1,775 @@
+#   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 <http://www.gnu.org/licenses/>.
+
+# there should be NO references to FIFE here!
+import sys
+import os.path
+import logging
+from copy import deepcopy
+
+from fife import fife
+from fife.extensions.serializers.xmlobject import XMLObjectLoader 
+
+from gamestate import GameState
+from objects import createObject
+from objects.composed import CarryableItem, CarryableContainer
+from gamemap import GameMap
+from common.utils import locateFiles
+from common.utils import parseBool
+from inventory import Inventory
+from parpg.dialogueparsers import YamlDialogueParser, DialogueFormatError
+
+try:
+    import xml.etree.cElementTree as ElementTree
+except ImportError:
+    import xml.etree.ElementTree as ElementTree
+
+import yaml
+
+logger = logging.getLogger('gamemodel')
+
+class GameModel(object):
+    """GameModel holds the logic for the game.
+       Since some data (object position and so forth) is held in the
+       fife, and would be pointless to replicate, we hold a instance of
+       the fife view here. This also prevents us from just having a
+       function heavy controller."""
+    ALL_AGENTS_KEY = "All"
+    MAX_ID_NUMBER = 1000
+    
+    def __init__(self, engine, settings):
+        """Initialize the instance.
+        @param engine: A fife.Engine object
+        @type emgome: fife.Engine 
+        @param setting: The applications settigns
+        @type setting: parpg.settings.Settings object
+        @return: None"""
+        self.settings = settings
+
+        self.map_change = False
+        self.load_saver = False
+        self.savegame = None
+        quests_directory = os.path.join(self.settings.system_path,
+                                        self.settings.parpg.QuestsPath)
+        self.game_state = GameState(quests_dir=quests_directory)
+        #self.game_state.quest_engine = 
+        #self.game_state.quest_engine.readQuests()
+        self.pc_run = 1
+        self.target_position = None
+        self.target_map_name = None
+        self.object_db = {}
+        self.active_map = None
+        self.map_files = {}
+        self.agents = {}
+        self.agents[self.ALL_AGENTS_KEY] = {}
+        self.engine = engine
+        self.fife_model = engine.getModel()
+
+        # set values from settings
+        maps_file = os.path.join(self.settings.system_path, 
+                                 self.settings.parpg.MapsPath,
+                                 self.settings.parpg.MapsFile)
+        self.game_state.maps_file = maps_file
+        all_agents_file = os.path.join(self.settings.system_path,
+                                       self.settings.parpg.MapsPath,
+                                       self.settings.parpg.AllAgentsFile)
+        self.all_agents_file = all_agents_file
+        objects_dir = os.path.join(self.settings.system_path,
+                                    self.settings.parpg.ObjectsPath)
+        self.objects_directory = objects_dir
+        object_db_file = os.path.join(self.objects_directory,
+                                      self.settings.parpg.ObjectDatabaseFile)
+        self.object_db_file = object_db_file
+        dialogues_dir = os.path.join(self.settings.system_path, 
+                                     self.settings.parpg.DialoguesPath)
+        self.dialogues_directory = dialogues_dir
+        self.dialogues = {}
+        self.agent_import_files = {}
+        self.obj_loader = XMLObjectLoader(
+                                          self.engine.getImagePool(), 
+                                          self.engine.getAnimationPool(), 
+                                          self.engine.getModel(),
+                                          self.engine.getVFS() 
+                                          )
+
+    def checkAttributes(self, attributes):
+        """Checks for attributes that where not given in the map file
+        and fills them with values from the object database
+        @param attributes: attributes to check
+        @type attributes: Dictionary
+        @return: The modified attributes""" 
+        if attributes.has_key("object_type"):
+            class_name = attributes.pop("object_type")
+        else:
+            class_name = attributes["type"]
+        if not attributes.has_key("type"):
+            attributes["type"] = class_name
+        if self.object_db.has_key(class_name):
+            db_attributes = deepcopy(self.object_db[class_name])
+            for key in db_attributes.keys():
+                if attributes.has_key(key):
+                    attributes[key] = attributes[key] or db_attributes[key]
+                else:
+                    attributes[key] = db_attributes[key]
+        return attributes
+    
+    def isIDUsed(self, ID):
+        if self.game_state.hasObject(ID):
+            return True
+        for namespace in self.agents:
+            if ID in self.agents[namespace]:
+                return True
+        return False
+    
+    def createUniqueID(self, ID):
+        if self.isIDUsed(ID):
+            id_number = 1
+            while self.isIDUsed(ID + "_" + str(id_number)):
+                id_number += 1
+                if id_number > self.MAX_ID_NUMBER:
+                    raise ValueError(
+                        "Number exceeds MAX_ID_NUMBER:" + str(self.MAX_ID_NUMBER))
+            
+            ID = ID + "_" + str(id_number)
+        return ID
+
+    def createContainerItems(self, container_objs):
+        """Create the items of a container from a dictionary
+        @param container_objs: Dictionary containing the items
+        @type container_objs: dict"""
+        items = []
+        for container_obj in container_objs:
+            items.append(self.createContainerObject(container_obj))
+        
+        return items
+
+    def createContainerObject(self, attributes):
+        """Create an object that can be stored in 
+        an container and return it
+        @param attributes: Dictionary of all object attributes
+        @type attributes: Dictionary
+        @return: The created object """
+        # create the extra data
+        extra = {}
+        extra['controller'] = self
+        attributes = self.checkAttributes(attributes)
+        
+        info = {}
+        info.update(attributes)
+        info.update(extra)
+        ID = info.pop("id") if info.has_key("id") else info.pop("ID")
+        if not info.has_key("item_type"):
+            info["item_type"] = info["type"]
+        ID = self.createUniqueID(ID)
+        if info.has_key("attributes"):
+            attributes = info["attributes"]
+            if "Container" in attributes:
+                info["actions"]["Open"] = ""
+                if info.has_key("Items"):
+                    inventory_objs = info["Items"]
+                    info["items"] = self.createContainerItems(inventory_objs)
+                
+                new_item = CarryableContainer(ID = ID, **info) 
+            else:
+                new_item = CarryableItem(ID = ID, **info) 
+        else:
+            new_item = CarryableItem(ID = ID, **info) 
+        self.game_state.addObject(None, new_item)
+        return new_item
+      
+    def createInventoryObject(self, container, attributes):
+        """Create an inventory object and place it into a container
+           @type container: base.Container
+           @param container: Container where the item is on
+           @type attributes: Dictionary
+           @param attributes: Dictionary of all object attributes
+           @return: None"""
+        index = attributes.pop("index") if attributes.has_key("index") else None
+        slot = attributes.pop("slot") if attributes.has_key("slot") else None
+        obj = self.createContainerObject(attributes)        
+        #obj = createObject(attributes, extra)
+        if slot:
+            container.moveItemToSlot(obj, slot)
+        else:
+            container.placeItem(obj, index)
+    
+    def deleteObject(self, object_id):
+        """Removes an object from the game
+        @param object_id: ID of the object
+        @type object_id: str """
+        del self.agents["All"][object_id]
+        self.game_state.deleteObject(object_id)
+        
+    def save(self, path, filename):
+        """Writes the saver to a file.
+           @type filename: string
+           @param filename: the name of the file to write to
+           @return: None"""
+        fname = '/'.join([path, filename])
+        try:
+            save_file = open(fname, 'w')
+        except(IOError):
+            sys.stderr.write("Error: Can't create save game: " + fname + "\n")
+            return
+        save_state = {}
+        save_state["Agents"] = {}
+        for map_name in self.agents:
+            if map_name == self.ALL_AGENTS_KEY:
+                continue
+            agents_dict = {}
+            for agent in self.agents[map_name]:
+                agent_obj = self.game_state.getObjectById(agent, map_name)
+                agent_inst = self.game_state.maps[map_name].\
+                                    agent_layer.getInstance(agent)
+                agent_dict = self.agents[map_name][agent]
+                agent_dict.update(agent_obj.getStateForSaving())
+                agent_dict["Rotation"] = agent_inst.getRotation()
+                agents_dict[agent] = agent_dict
+            save_state["Agents"][map_name] = agents_dict
+        agents_dict = {}
+        for agent in self.agents["All"]:
+            map_name = self.agents["All"][agent]["Map"]
+            agent_dict = self.agents["All"][agent]
+            agent_obj = None
+            if agent == "PlayerCharacter":
+                agent_obj = self.game_state.player_character
+            else:
+                agent_obj = self.game_state.getObjectById(agent, map_name)
+            if agent_obj:
+                agent_inst = self.game_state.maps[map_name].\
+                                    agent_layer.getInstance(agent)
+                agent_dict.update(agent_obj.getStateForSaving())
+                agent_dict["Rotation"] = agent_inst.getRotation()
+                agent_dict["MapName"] = map_name
+            agents_dict[agent] = agent_dict
+        save_state["Agents"]["All"] = agents_dict
+        save_state["GameState"] = self.game_state.getStateForSaving()
+        yaml.dump(save_state, save_file)
+        
+        save_file.close()       
+
+    def load(self, path, filename):
+        """Loads a saver from a file.
+           @type filename: string
+           @param filename: the name of the file (including path) to load from
+           @return: None"""
+        fname = '/'.join([path, filename])
+
+        try:
+            load_file = open(fname, 'r')
+        except(IOError):
+            sys.stderr.write("Error: Can't find save game file\n")
+            return        
+        self.deleteMaps()
+        self.clearAgents()
+        
+        save_state = yaml.load(load_file)
+        self.game_state.restoreFromState(save_state["GameState"])
+        maps = save_state["Agents"]
+        for map_name in maps:
+            for agent_name in maps[map_name]:
+                agent = {agent_name:maps[map_name][agent_name]}
+                self.addAgent(map_name, agent)
+                
+        # Load the current map
+        if self.game_state.current_map_name:
+            self.loadMap(self.game_state.current_map_name)         
+        load_file.close()
+        
+
+        # Recreate all the behaviours. These can't be saved because FIFE
+        # objects cannot be pickled
+        
+        self.placeAgents()
+        self.placePC()
+      
+        # In most maps we'll create the PlayerCharacter Instance internally. 
+        # In these cases we need a target position
+         
+    def teleport(self, agent, position):
+        """Called when a an agent is moved instantly to a new position. 
+        The setting of position may wan to be created as its own method down the road.
+        @type position: String Tuple
+        @param position: X,Y coordinates passed from engine.changeMap
+        @return: fife.Location"""
+        logging.debug(position)
+        coord = fife.DoublePoint3D(float(position[0]), float(position[1]), 0)
+        location = fife.Location(self.active_map.agent_layer)
+        location.setMapCoordinates(coord)
+        agent.teleport(location)         
+               
+    def getObjectAtCoords(self, coords):
+        """Get the object which is at the given coords
+        @type coords: fife.Screenpoint
+        @param coords: Coordinates where to check for an object
+        @rtype: fife.Object
+        @return: An object or None"""
+        instances = self.active_map.cameras[
+                                            self.active_map.my_cam_id].\
+            getMatchingInstances(coords, self.active_map.agent_layer)
+        # no object returns an empty tuple
+        if(instances != ()):
+            front_y = 0
+            
+
+            for obj in instances:
+                # check to see if this in our list at all
+                if(self.objectActive(obj.getId())):
+                    # check if the object is on the foreground
+                    obj_map_coords = \
+                                      obj.getLocation().getMapCoordinates()
+                    obj_screen_coords = self.active_map.\
+                        cameras[self.active_map.my_cam_id]\
+                        .toScreenCoordinates(obj_map_coords)
+
+                    if obj_screen_coords.y > front_y:
+                        #Object on the foreground
+                        front_y = obj_screen_coords.y
+                        return obj
+                    else:
+                        return None
+        else:
+            return None
+
+    def getCoords(self, click):
+        """Get the map location x, y coordinates from the screen coordinates
+           @type click: fife.ScreenPoint
+           @param click: Screen coordinates
+           @rtype: fife.Location
+           @return: The map coordinates"""
+        coord = self.active_map.cameras[self.active_map.my_cam_id].\
+                    toMapCoordinates(click, False)
+        coord.z = 0
+        location = fife.Location(self.active_map.agent_layer)
+        location.setMapCoordinates(coord)
+        return location
+
+    def pause(self, paused):
+        """ Pause/Unpause the game
+        @return: nothing"""
+        if self.active_map:
+            self.active_map.pause(paused)
+    
+    def togglePause(self):
+        """ Toggle paused state.
+        @return: nothing"""
+        self.active_map.togglePause()
+        
+    def isPaused(self):
+        """Returns wheter the game is paused or not"""
+        return self.active_map.isPaused()
+    
+    def readMapFiles(self):
+        """Read all a available map-files and store them"""
+        maps_data = file(self.game_state.maps_file)
+        self.map_files = yaml.load(maps_data)["Maps"]
+    
+    def addAgent(self, namespace, agent):
+        """Adds an agent to the agents dictionary
+        @param namespace: the namespace where the agent is to be added to
+        @type namespace: str
+        @param agent: The agent to be added
+        @type agent: dict """
+        from fife.extensions.serializers.xml_loader_tools import loadImportFile
+        if not self.agents.has_key(namespace):
+            self.agents[namespace] = {}
+            
+        agent_values = agent.values()[0]
+        unique_agent_id = self.createUniqueID(agent.keys()[0])
+        del agent[agent.keys()[0]]
+        agent[unique_agent_id] = agent_values
+        self.agents[namespace].update(agent)
+        object_model = ""
+        if agent_values.has_key("ObjectModel"): 
+            object_model =  agent_values["ObjectModel"]
+        elif agent_values["ObjectType"] == "MapItem":
+            object_data = self.object_db[agent_values["ItemType"]]
+            object_model = object_data["gfx"] if object_data.has_key("gfx") \
+                        else "generic_item"
+        else:
+            object_model = self.object_db[agent_values["ObjectType"]]["gfx"]
+        import_file = self.agent_import_files[object_model]
+        loadImportFile(self.obj_loader, import_file, self.engine)
+        
+    def readAgentsOfMap(self, map_name):
+        """Read the agents of the map
+        @param map_name: Name of the map
+        @type map_name: str """
+        #Get the agents of the map        
+        map_agents_file = self.map_files[map_name].\
+                            replace(".xml", "_agents.yaml")   
+        agents_data = file(map_agents_file)
+        agents = yaml.load_all(agents_data)
+        for agent in agents:
+            if not agent == None:
+                self.addAgent(map_name, agent)  
+    
+    def readAllAgents(self):
+        """Read the agents of the all_agents_file and store them"""
+        agents_data = file(self.all_agents_file)
+        agents = yaml.load_all(agents_data)
+        for agent in agents:
+            if not agent == None:
+                self.addAgent(self.ALL_AGENTS_KEY, agent)  
+                
+    def getAgentsOfMap(self, map_name):
+        """Returns the agents that are on the given map
+        @param map_name: Name of the map
+        @type map_name: str
+        @return: A dictionary with the agents of the map"""
+        if not self.agents.has_key(map_name):
+            return {}
+        ret_dict = self.agents[map_name].copy()
+        for agent_name, agent_value in self.agents[self.ALL_AGENTS_KEY]\
+                                                .iteritems():
+            if agent_value["Map"] == map_name:
+                ret_dict[agent_name] = agent_value
+        return ret_dict
+                
+    def getAgentsOfActiveMap(self):
+        """Returns the agents that are on active map
+        @return: A dictionary with the agents of the map """
+        return self.getAgentsOfMap(self.active_map.map.getId())
+
+    def clearAgents(self):
+        """Resets the agents dictionary"""
+        self.agents = {}
+        self.agents[self.ALL_AGENTS_KEY] = {}
+    
+    def loadMap(self, map_name):
+        """Load a new map.
+           @type map_name: string
+           @param map_name: Name of the map to load
+           @return: None"""
+        if not map_name in self.game_state.maps:  
+            map_file = self.map_files[map_name]
+            new_map = GameMap(self.engine, self)
+            self.game_state.maps[map_name] = new_map
+            new_map.load(map_file)    
+
+    def createAgent(self, agent, inst_id):
+        object_type = agent["ObjectType"]
+        object_id = agent["ObjectModel"] \
+                                if agent.has_key("ObjectModel") \
+                                else None
+        if object_id == None:
+            if object_type == "MapItem":
+                object_data = self.object_db[agent["ItemType"]]
+                object_id = object_data["gfx"] if object_data.has_key("gfx") \
+                            else "generic_item"
+            else:
+                object_id = self.object_db[object_type]["gfx"]
+        map_obj = self.fife_model.getObject(str(object_id), "PARPG")
+        if not map_obj:
+            logging.warning("Object with inst_id={0}, ns=PARPG, "
+                                  "could not be found. "
+                                  "Omitting...".format(str(obj_id)))
+
+        x_pos = agent["Position"][0]
+        y_pos = agent["Position"][1]
+        z_pos = agent["Position"][2] if len(agent["Position"]) == 3 \
+                                        else -0.1 if object_type == "MapItem" \
+                                        else 0.0  
+        stack_pos = agent["Stackposition"] if \
+                        agent.has_key("StackPosition") \
+                        else None
+        inst = self.active_map.agent_layer.\
+                        createInstance(map_obj,
+                                       fife.ExactModelCoordinate(x_pos, 
+                                                                 y_pos, 
+                                                                 z_pos),
+                                       inst_id)
+        inst.setId(inst_id)
+
+        rotation = agent["Rotation"]
+        inst.setRotation(rotation)
+
+        fife.InstanceVisual.create(inst)
+        if (stack_pos):
+            inst.get2dGfxVisual().setStackPosition(int(stack_pos))
+
+        if (map_obj.getAction('default')):
+            target = fife.Location(self.active_map.agent_layer)
+            inst.act('default', target, True)
+            
+        inst_dict = {}
+        inst_dict["id"] = inst_id
+        inst_dict["type"] = object_type
+        inst_dict["xpos"] = x_pos
+        inst_dict["ypos"] = y_pos
+        inst_dict["gfx"] = object_id
+        inst_dict["is_open"] = parseBool(agent["Open"]) \
+                                if agent.has_key("Open") \
+                                else False
+        inst_dict["locked"] = parseBool(agent["Locked"]) \
+                                if agent.has_key("Locked") \
+                                else False
+        inst_dict["name"] = agent["ViewName"]
+        inst_dict["real_name"] = agent["RealName"] \
+                                    if agent.has_key("RealName") \
+                                    else agent["ViewName"]
+        inst_dict["text"] = agent["Text"] \
+                                    if agent.has_key("Text") \
+                                    else None
+        if self.dialogues.has_key(inst_id):
+            inst_dict["dialogue"] = self.dialogues[inst_id]
+        inst_dict["target_map_name"] = agent["TargetMap"] \
+                                        if agent.\
+                                            has_key("TargetMap") \
+                                        else None
+        inst_dict["target_x"] = agent["TargetPosition"][0] \
+                                    if agent.\
+                                        has_key("TargetPosition") \
+                                    else None
+        inst_dict["target_y"] = agent["TargetPosition"][1] \
+                                    if agent.\
+                                        has_key("TargetPosition") \
+                                    else None
+        if agent.has_key("Inventory"):
+            inventory = Inventory()
+            inventory_objs = agent["Inventory"]
+            for inventory_obj in inventory_objs:
+                self.createInventoryObject(inventory,
+                                           inventory_obj 
+                                           )
+            inst_dict["inventory"] = inventory
+
+        if agent.has_key("Items"):
+            container_objs = agent["Items"]
+            items = self.createContainerItems(container_objs)
+            inst_dict["items"] = items
+            
+        if agent.has_key("ItemType"):
+            if not agent.has_key("item"):
+                item_data = {}
+                item_data["type"] = agent["ItemType"]
+                item_data["ID"] = inst_id 
+                item_data = self.createContainerObject(item_data)
+            else:
+                item_data = agent["item"]
+            inst_dict["item"] = item_data
+            inst_dict["item_type"] = agent["ItemType"]
+
+        self.createMapObject(self.active_map.agent_layer, inst_dict)
+    
+    def placeAgents(self):
+        """Places the current maps agents """
+        if not self.active_map:
+            return
+        agents = self.getAgentsOfMap(self.game_state.current_map_name)
+        for agent in agents:
+            if agent == "PlayerCharacter":
+                continue
+            if self.active_map.agent_layer.getInstances(agent):
+                continue
+            self.createAgent(agents[agent], agent)
+
+    def placePC(self):
+        """Places the PlayerCharacter on the map"""
+        agent = self.agents[self.ALL_AGENTS_KEY]["PlayerCharacter"]
+        inst_id = "PlayerCharacter"
+        self.createAgent(agent, inst_id)
+        
+        # create the PlayerCharacter agent
+        self.active_map.addPC()
+        self.game_state.player_character.start()
+        if agent.has_key("PeopleKnown"):
+            self.game_state.player_character.people_i_know = agent["PeopleKnown"]
+                      
+    def changeMap(self, map_name, target_position = None):
+        """Registers for a map change on the next pump().
+           @type map_name: String
+           @param map_name: Id of the map to teleport to
+           @type map_file: String
+           @param map_file: Filename of the map to teleport to
+           @type target_position: Tuple
+           @param target_position: Position of PlayerCharacter on target map.
+           @return None"""
+        # set the parameters for the map change if moving to a new map
+        if map_name != self.game_state.current_map_name:
+            self.target_map_name = map_name
+            self.target_position = target_position
+            # issue the map change
+            self.map_change = True
+
+    def deleteMaps(self):
+        """Clear all currently loaded maps from FIFE as well as clear our
+            local map cache
+            @return: nothing"""
+        self.engine.getModel().deleteMaps()
+        self.engine.getModel().deleteObjects()
+        self.game_state.clearObjects()
+        self.game_state.maps = {}
+        
+    def setActiveMap(self, map_name):
+        """Sets the active map that is to be rendered.
+           @type map_name: String
+           @param map_name: The name of the map to load
+           @return: None"""
+        # Turn off the camera on the old map before we turn on the camera
+        # on the new map.
+        self.active_map.cameras[self.active_map.my_cam_id].setEnabled(False)
+        # Make the new map active.
+        self.active_map = self.game_state.maps[map_name]
+        self.active_map.makeActive()
+        self.game_state.current_map_name = map_name
+
+    def createMapObject (self, layer, attributes):
+        """Create an object and add it to the current map.
+           @type layer: fife.Layer
+           @param layer: FIFE layer object exists in
+           @type attributes: Dictionary
+           @param attributes: Dictionary of all object attributes
+           @type instance: fife.Instance
+           @param instance: FIFE instance corresponding to the object
+           @return: None"""
+        # create the extra data
+        extra = {}
+        if layer is not None:
+            extra['agent_layer'] = layer
+        attributes = self.checkAttributes(attributes)
+        
+        obj = createObject(attributes, extra)
+        
+        if obj.trueAttr("PC"):
+            self.addPC(layer, obj)
+        else:
+            self.addObject(layer, obj) 
+
+    def addPC(self, layer, player_char):
+        """Add the PlayerCharacter to the map
+           @type layer: fife.Layer
+           @param layer: FIFE layer object exists in
+           @type player_char: PlayerCharacter
+           @param player_char: PlayerCharacter object
+           @type instance: fife.Instance
+           @param instance: FIFE instance of PlayerCharacter
+           @return: None"""
+        # For now we copy the PlayerCharacter, 
+        # in the future we will need to copy
+        # PlayerCharacter specifics between the different PlayerCharacter's
+        self.game_state.player_character = player_char
+        self.game_state.player_character.setup()        
+        self.game_state.player_character.behaviour.speed = self.settings.parpg.PCSpeed
+
+
+    def addObject(self, layer, obj):
+        """Adds an object to the map.
+           @type layer: fife.Layer
+           @param layer: FIFE layer object exists in
+           @type obj: GameObject
+           @param obj: corresponding object class
+           @type instance: fife.Instance
+           @param instance: FIFE instance of object
+           @return: None"""
+        ref = self.game_state.getObjectById(obj.ID, \
+                                            self.game_state.current_map_name) 
+        if ref is None:
+            # no, add it to the game state
+            self.game_state.addObject(self.game_state.current_map_name, obj)
+        else:
+            # yes, use the current game state data
+            obj.X = ref.X
+            obj.Y = ref.Y
+            obj.gfx = ref.gfx  
+             
+        if obj.trueAttr("NPC"):
+            # create the agent
+            obj.setup()
+            obj.behaviour.speed = self.settings.parpg.PCSpeed - 1
+            # create the PlayerCharacter agent
+            obj.start()
+        if obj.trueAttr("AnimatedContainer"):
+            # create the agent
+            obj.setup()
+
+    def objectActive(self, ident):
+        """Given the objects ID, pass back the object if it is active,
+           False if it doesn't exist or not displayed
+           @type ident: string
+           @param ident: ID of object
+           @rtype: boolean
+           @return: Status of result (True/False)"""
+        for game_object in \
+           self.game_state.getObjectsFromMap(self.game_state.current_map_name):
+            if (game_object.ID == ident):
+                # we found a match
+                return game_object
+        # no match
+        return False    
+
+    def movePlayer(self, position):
+        """Code called when the player should move to another location
+           @type position: fife.ScreenPoint
+           @param position: Screen position to move to
+           @return: None"""
+        if(self.pc_run == 1):
+            self.game_state.player_character.run(position)
+        else:
+            self.game_state.player_character.walk(position)
+        
+    def teleportAgent(self, agent, position):
+        """Code called when an agent should teleport to another location
+           @type position: fife.ScreenPoint
+           @param position: Screen position to teleport to
+           @return: None"""
+        agent.teleport(position)
+        self.agents[agent.ID]["Position"] = position
+
+    def readObjectDB(self):
+        """Reads the Object Information Database from a file. """
+        database_file = file(self.object_db_file, "r")
+        database = yaml.load_all(database_file)
+        for object_info in database:
+            self.object_db.update(object_info)
+
+    def getAgentImportFiles(self):
+        """Searches the agents directory for import files """
+        files = locateFiles("*.xml", self.objects_directory)
+        for xml_file in files:
+            xml_file = os.path.relpath(xml_file).replace("\\", "/")
+            try:
+                root = ElementTree.parse(xml_file).getroot()
+                if root.tag == "object":
+                    self.agent_import_files[root.attrib["id"]] = xml_file
+            except SyntaxError as error:
+                assert(isinstance(error, SyntaxError))
+                logging.critical("Error parsing file {0}: "
+                                       "{1}".format(xml_file, error.msg))
+                sys.exit(1)
+    
+    def getDialogues(self):
+        """Searches the dialogue directory for dialogues """
+        files = locateFiles("*.yaml", self.dialogues_directory)
+        dialogue_parser = YamlDialogueParser()
+        for dialogue_filepath in files:
+            dialogue_filepath = os.path.relpath(dialogue_filepath) \
+                                .replace("\\", "/")
+            # Note Technomage 2010-11-13: the new DialogueEngine uses its own
+            #     parser now, YamlDialogueParser.
+#            dialogues = yaml.load_all(file(dialogue_file, "r"))
+            with file(dialogue_filepath, 'r') as dialogue_file:
+                try:
+                    dialogue = dialogue_parser.load(dialogue_file)
+                except (DialogueFormatError,) as error:
+                    logging.error('unable to load dialogue file {0}: {1}'
+                                  .format(dialogue_filepath, error))
+                else:
+                    self.dialogues[dialogue.npc_name] = dialogue
+            # Note Technomage 2010-11-13: the below code is used to load
+            #     multiple dialogues from a single file. Is this functionality
+            #     used/necessary?
+#            for dialogue in dialogues:
+#                self.dialogues[dialogue["NPC"]] = dialogue