changeset 203:92bb014104ee

Added parpg-source subrepo in parpg directory, which replaces the src directory.
author KarstenBock@gmx.net
date Thu, 12 Jan 2012 19:13:29 +0100
parents 7747b0f73694
children 132da1d0b5b4
files .hgsub .hgsubstate src/parpg.py src/parpg/__init__.py src/parpg/application.py src/parpg/bGrease/__init__.py src/parpg/bGrease/collision.py src/parpg/bGrease/color.py src/parpg/bGrease/component/__init__.py src/parpg/bGrease/component/base.py src/parpg/bGrease/component/field.py src/parpg/bGrease/component/general.py src/parpg/bGrease/component/schema.py src/parpg/bGrease/controller/__init__.py src/parpg/bGrease/controller/integrator.py src/parpg/bGrease/entity.py src/parpg/bGrease/geometry.py src/parpg/bGrease/impl/__init__.py src/parpg/bGrease/impl/controls.py src/parpg/bGrease/impl/mode.py src/parpg/bGrease/impl/world.py src/parpg/bGrease/mode.py src/parpg/bGrease/renderer/__init__.py src/parpg/bGrease/renderer/camera.py src/parpg/bGrease/renderer/vector.py src/parpg/bGrease/world.py src/parpg/behaviours/__init__.py src/parpg/behaviours/base.py src/parpg/behaviours/moving.py src/parpg/behaviours/npc.py src/parpg/behaviours/player.py src/parpg/charactercreationcontroller.py src/parpg/charactercreationview.py src/parpg/characterstatistics.py src/parpg/common/__init__.py src/parpg/common/listeners/__init__.py src/parpg/common/listeners/command_listener.py src/parpg/common/listeners/console_executor.py src/parpg/common/listeners/event_listener.py src/parpg/common/listeners/key_listener.py src/parpg/common/listeners/mouse_listener.py src/parpg/common/listeners/widget_listener.py src/parpg/common/ordereddict.py src/parpg/common/utils.py src/parpg/components/__init__.py src/parpg/components/base.py src/parpg/components/behaviour.py src/parpg/components/change_map.py src/parpg/components/character_statistics.py src/parpg/components/containable.py src/parpg/components/container.py src/parpg/components/description.py src/parpg/components/dialogue.py src/parpg/components/equip.py src/parpg/components/equipable.py src/parpg/components/fifeagent.py src/parpg/components/general.py src/parpg/components/graphics.py src/parpg/components/lockable.py src/parpg/components/usable.py src/parpg/console.py src/parpg/controllerbase.py src/parpg/dialogue.py src/parpg/dialogueactions.py src/parpg/dialoguecontroller.py src/parpg/dialogueparsers.py src/parpg/dialogueprocessor.py src/parpg/entities/__init__.py src/parpg/entities/action.py src/parpg/entities/general.py src/parpg/font.py src/parpg/gamemap.py src/parpg/gamemodel.py src/parpg/gamescenecontroller.py src/parpg/gamesceneview.py src/parpg/gamestate.py src/parpg/gui/__init__.py src/parpg/gui/actionsbox.py src/parpg/gui/charactercreationview.py src/parpg/gui/containergui.py src/parpg/gui/containergui_base.py src/parpg/gui/dialogs.py src/parpg/gui/dialoguegui.py src/parpg/gui/drag_drop_data.py src/parpg/gui/filebrowser.py src/parpg/gui/hud.py src/parpg/gui/inventorygui.py src/parpg/gui/menus.py src/parpg/gui/popups.py src/parpg/gui/spinners.py src/parpg/gui/tabwidget.py src/parpg/inventory.py src/parpg/main.py src/parpg/mainmenucontroller.py src/parpg/mainmenuview.py src/parpg/mode.py src/parpg/quest_engine.py src/parpg/serializers.py src/parpg/settings.py src/parpg/sounds.py src/parpg/systems/__init__.py src/parpg/systems/gamerulessystem.py src/parpg/systems/scriptingsystem.py src/parpg/vfs.py src/parpg/viewbase.py src/parpg/world.py
diffstat 104 files changed, 2 insertions(+), 14891 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsub	Thu Jan 12 18:01:28 2012 +0100
+++ b/.hgsub	Thu Jan 12 19:13:29 2012 +0100
@@ -1,2 +1,3 @@
+parpg = ../parpg-source
 data = [svn]http://subversion.assembla.com/svn/parpg-assets/trunk/
 tools = https://hg.assembla.com/parpg-tools
--- a/.hgsubstate	Thu Jan 12 18:01:28 2012 +0100
+++ b/.hgsubstate	Thu Jan 12 19:13:29 2012 +0100
@@ -1,2 +1,3 @@
 23 data
+0000000000000000000000000000000000000000 parpg
 833aac39c9bd43873554f19ab3d6c27ddba317ff tools
--- a/src/parpg.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-#!/usr/bin/env python2 
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-#TODO: Modularize this script
-import sys
-from optparse import OptionParser
-from os import path
-
-from parpg.main import main
-
-usage = ('usage: %prog [options] settings_path [system_path user_path]\n\n'
-         'The settings_path argument is mandatory and is the directory in \n'
-         'which your parpg.cfg file is located. Optionally, you may \n'
-         'specify where data files are located (system_path), and where \n'
-         'the user settings and data files should be saved to (user_path)\n\n'
-         'Example: python %prog .')
-
-parser = OptionParser(description='PARPG Launcher Script', usage=usage)
-parser.add_option('-f', '--logfile',
-                  help='Name of log file to save to')
-parser.add_option('-l', '--loglevel', default='critical',
-                  help='desired output level for log file')
-opts, args = parser.parse_args()
-
-if not args:
-    if path.isfile("./parpg.cfg"):
-        args =(".")
-    else:
-        parser.print_help()
-        sys.exit(1)
-
-main(args, opts)
\ No newline at end of file
--- a/src/parpg/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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 <http://www.gnu.org/licenses/>.
-
-COPYRIGHT_HEADER = """\
-#   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/>.
-"""
--- a/src/parpg/application.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""This module contains the main Application class 
-and the basic Listener for PARPG """
-
-import os
-import sys
-
-from fife import fife
-from fife.extensions import pychan
-from fife.extensions.basicapplication import ApplicationBase
-
-from parpg import console, vfs
-from parpg.font import PARPGFont
-from parpg.gamemodel import GameModel
-from parpg.mainmenuview import MainMenuView
-from parpg.mainmenucontroller import MainMenuController
-from parpg.common.listeners.event_listener import EventListener
-from parpg.common.listeners.key_listener import KeyListener
-from parpg.common.listeners.mouse_listener import MouseListener
-from parpg.common.listeners.command_listener import CommandListener
-from parpg.common.listeners.console_executor import ConsoleExecuter
-from parpg.common.listeners.widget_listener import WidgetListener
-from parpg.mode import FifeManager
-
-class KeyFilter(fife.IKeyFilter):
-    """
-    This is the implementation of the fife.IKeyFilter class.
-
-    Prevents any filtered keys from being consumed by guichan.
-    """
-    def __init__(self, keys):
-        fife.IKeyFilter.__init__(self)
-        self._keys = keys
-
-    def isFiltered(self, event):
-        """Checks if an key is filtered"""
-        return event.getKey().getValue() in self._keys
-
-class ApplicationListener(KeyListener,
-                          MouseListener,
-                          ConsoleExecuter,
-                          CommandListener,
-                          WidgetListener):    
-    """Basic listener for PARPG"""
-
-    def __init__(self, event_listener, engine, view, model):
-        """Initialize the instance.
-           @type engine: fife.engine
-           @param engine: ???
-           @type view: viewbase.ViewBase
-           @param view: View that draws the current state
-           @type model: GameModel
-           @param model: The game model"""
-
-        KeyListener.__init__(self, event_listener)
-        MouseListener.__init__(self, event_listener)
-        ConsoleExecuter.__init__(self, event_listener)
-        CommandListener.__init__(self, event_listener)
-        WidgetListener.__init__(self, event_listener)        
-        self.engine = engine
-        self.view = view
-        self.model = model
-        keyfilter = KeyFilter([fife.Key.ESCAPE])
-        keyfilter.__disown__()        
-
-        engine.getEventManager().setKeyFilter(keyfilter)
-        self.quit = False
-        self.about_window = None
-        self.console = console.Console(self)
-
-    def quitGame(self):
-        """Forces a quit game on next cycle.
-           @return: None"""
-        self.quit = True
-
-    def onConsoleCommand(self, command):
-        """
-        Called on every console comand, delegates calls  to the a console
-        object, implementing the callbacks
-        @type command: string
-        @param command: the command to run
-        @return: result
-        """
-        return self.console.handleConsoleCommand(command)
-
-    def onCommand(self, command):
-        """Enables the game to be closed via the 'X' button on the window frame
-           @type command: fife.Command
-           @param command: The command to read.
-           @return: None"""
-        if(command.getCommandType() == fife.CMD_QUIT_GAME):
-            self.quit = True
-            command.consume()
-
-class PARPGApplication(ApplicationBase):
-    """Main Application class
-       We use an MVC model model
-       self.gamesceneview is our view,self.model is our model
-       self.controller is the controller"""
-
-    def __init__(self, setting):
-        """Initialise the instance.
-           @return: None"""
-        self._setting = setting
-        self.manager = FifeManager()
-        self.engine = fife.Engine()
-        self.loadSettings()
-        self.engine.init()
-        # KLUDGE M. George Hansen 2011-06-04: See parpg/vfs.py.
-        vfs.VFS = self.engine.getVFS()
-        vfs.VFS.addNewSource(setting.parpg.DataPath)
-
-        pychan.init(self.engine, debug = True)
-        pychan.setupModalExecution(self.mainLoop,self.breakFromMainLoop)
-
-        self.quitRequested = False
-        self.breakRequested = False
-        self.returnValues = []
-        #self.engine.getModel(self)
-        self.model = GameModel(self.engine, setting)
-        self.model.readMapFiles()
-        self.model.readObjectDB()
-        self.model.getAgentImportFiles()
-        self.model.readAllAgents()
-        self.model.getDialogues()
-        # KLUDGE M. George Hansen 2011-06-04: Hack to allow loaded PyChan XML
-        #     scripts to locate their resources.
-        os.chdir(setting.parpg.DataPath)
-        self.view = MainMenuView(self.engine, self.model)
-        self.loadFonts()
-        self.event_listener = EventListener(self.engine)
-        controller = MainMenuController(self.engine, self.view, self.model, 
-                                        self)
-        #controller.initHud()
-        self.manager.push_mode(controller)
-        self.listener = ApplicationListener(self.event_listener,
-                                            self.engine, 
-                                            self.view, 
-                                            self.model)
-        #start_map = self._setting.fife.get("PARPG", "Map")
-        #self.model.changeMap(start_map)
-
-    def loadFonts(self):
-        # add the fonts path to the system path to import font definitons
-        sys.path.insert(0, os.path.join(self._setting.parpg.DataPath, 'fonts'))
-        from oldtypewriter import fontdefs
-
-        for fontdef in fontdefs:
-            pychan.internal.get_manager().addFont(PARPGFont(fontdef,
-                                                            self._setting))
-
-
-    def loadSettings(self):
-        """
-        Load the settings from a python file and load them into the engine.
-        Called in the ApplicationBase constructor.
-        """
-
-        engineSetting = self.engine.getSettings()
-        assert(isinstance(engineSetting, fife.EngineSettings))
-        engineSetting.setDefaultFontGlyphs(self._setting.fife.FontGlyphs)
-        engineSetting.setDefaultFontPath(
-            '{0}/fonts/{1}'.format(self._setting.parpg.DataPath,
-                                   self._setting.fife.Font)
-        )
-        engineSetting.setDefaultFontSize(self._setting.fife.DefaultFontSize)
-        engineSetting.setBitsPerPixel(self._setting.fife.BitsPerPixel)
-        engineSetting.setInitialVolume(self._setting.fife.InitialVolume)
-        engineSetting.setSDLRemoveFakeAlpha(
-            self._setting.fife.SDLRemoveFakeAlpha
-        )
-        engineSetting.setGLUseFramebuffer(self._setting.fife.GLUseFramebuffer)
-        engineSetting.setGLUseNPOT(self._setting.fife.GLUseNPOT)
-        engineSetting.setScreenWidth(self._setting.fife.ScreenWidth)
-        engineSetting.setScreenHeight(self._setting.fife.ScreenHeight)
-        engineSetting.setRenderBackend(self._setting.fife.RenderBackend)
-        engineSetting.setFullScreen(self._setting.fife.FullScreen)
-        engineSetting.setVideoDriver(self._setting.fife.VideoDriver)
-        engineSetting.setLightingModel(self._setting.fife.Lighting)
-        engineSetting.setColorKeyEnabled(self._setting.fife.ColorKeyEnabled)
-        engineSetting.setMouseSensitivity(self._setting.fife.MouseSensitivity)
-        engineSetting.setMouseAcceleration(
-            self._setting.fife.MouseAcceleration
-        )
-        
-        engineSetting.setColorKey(*[int(digit) 
-                                    for digit in self._setting.fife.ColorKey])
-
-        engineSetting.setWindowTitle(self._setting.fife.WindowTitle)
-        engineSetting.setWindowIcon(
-            '/'.join(['gui/icons', self._setting.fife.WindowIcon])
-        )
-
-    def createListener(self):
-        """ __init__ takes care of creating an event listener, so
-            basicapplication's createListener is harmful. Without 
-            overriding it, the program quit's on esc press, rather than
-            invoking the main menu
-        """
-        pass
-
-    def _pump(self):
-        """Main game loop.
-           There are 2 main loops, this one and the one in GameSceneView.
-           @return: None"""
-        if self.listener.quit:
-            self.breakRequested = True #pylint: disable-msg=C0103
-        else:
-            self.manager._pump()
\ No newline at end of file
--- a/src/parpg/bGrease/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-
-__versioninfo__ = (0, 3, 0)
-__version__ = '.'.join(str(n) for n in __versioninfo__)
-
-__all__ = ('BaseWorld', 'Entity', 'System', 'Renderer')
-
-import component
-import geometry
-import collision
-from entity import Entity
-from world import BaseWorld
-
-import abc
-
-class System(object):
-	"""Grease system abstract base class. Systems define behaviorial aspects
-	of a |World|. All systems must define a :meth:`step`
-	method that is invoked by the world each timestep.  User-defined systems
-	are not required to subclass this class.
-	
-	See :ref:`an example system from the tutorial <tut-system-example>`.
-	"""
-	__metaclass__ = abc.ABCMeta
-
-	world = None
-	"""The |World| this system belongs to"""
-
-	def set_world(self, world):
-		"""Bind the system to a world"""
-		self.world = world
-	
-	@abc.abstractmethod
-	def step(self, dt):
-		"""Execute a time step for the system. Must be defined
-		by all system classes.
-
-		:param dt: Time since last step invocation
-		:type dt: float
-		"""
-
-class Renderer(object):
-	"""Grease renderer abstract base class. Renderers define the presentation
-	of a |World|. All renderers must define a :meth:`draw`
-	method that is invoked by the world when the display needs to be redrawn.
-	User-defined renderers are not required to subclass this class.
-
-	See :ref:`an example renderer from the tutorial <tut-renderer-example>`.
-	"""
-	__metaclass__ = abc.ABCMeta
-
-	world = None
-	"""The |World| this renderer belongs to"""
-
-	def set_world(self, world):
-		"""Bind the system to a world"""
-		self.world = world
-
-	@abc.abstractmethod
-	def draw(self):
-		"""Issue drawing commands for this renderer. Must be defined
-		for all renderer classes.
-		"""
-
--- a/src/parpg/bGrease/collision.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,527 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-"""
-**Grease collision detection systems**
-
-Grease uses two-phase broad and narrow collision detection. *Broad-phase*
-collision systems are used to efficiently identify pairs that may be colliding
-without resorting to a brute-force check of all possible pairs. *Narrow-phase*
-collision systems use the pairs generated by the broad-phase and perform more
-precise collision tests to determine if a collision has actually occurred. The
-narrow-phase system also calculates more details about each collision,
-including collision point and normal vector for use in collision response.
-
-A typical collision detection system consists of a narrow-phase system that
-contains a broad-phased system. The narrow-phase system is usually the only
-
-one that the application directly interacts with, though the application is
-free to use the broad-phased system directly if desired. This could be
-useful in cases where speed, rather than precision is paramount.
-
-The narrow-phase system can be assigned handler objects to run after
-collision detection. These can perform tasks like handling collision response
-or dispatching collision events to application handlers.
-
-Note that broad-phase systems can return false positives, though they should
-never return false negatives. Do not assume that all pairs returned by a
-broad-phase system are actually in collision.
-"""
-
-__version__ = '$Id$'
-
-from parpg.bGrease.geometry import Vec2d
-from bisect import bisect_right
-
-
-class Pair(tuple):
-        """Pair of entities in collision. This is an ordered sequence of two
-        entities, that compares and hashes unordered.
-
-        Also stores additional collision point and normal vectors
-        for each entity.
-
-        Sets of ``Pair`` objects are exposed in the ``collision_pairs``
-        attribute of collision systems to indicate the entity pairs in
-        collision.
-        """
-        info = None
-        """A sequence of (entity, collision point, collision normal)
-	for each entity in the pair
-	"""
-
-        def __new__(cls, entity1, entity2, point=None, normal=None):
-                pair = tuple.__new__(cls, (entity1, entity2))
-                return pair
-
-        def __hash__(self):
-                return hash(self[0]) ^ hash(self[1])
-
-        def __eq__(self, other):
-                other = tuple(other)
-                return tuple(self) == other or (self[1], self[0]) == other
-
-        def __repr__(self):
-                return '%s%r' % (self.__class__.__name__, tuple(self))
-
-        def set_point_normal(self, point0, normal0, point1, normal1):
-                """Set the collision point and normal for both entities"""
-                self.info = (
-                        (self[0], point0, normal0),
-                        (self[1], point1, normal1),
-                )
-
-
-class BroadSweepAndPrune(object):
-        """2D Broad-phase sweep and prune bounding box collision detector
-
-        This algorithm is efficient for collision detection between many
-        moving bodies. It has linear algorithmic complexity and takes
-        advantage of temporal coherence between frames. It also does
-        not suffer from bad worst-case performance (like RDC can). 
-        Unlike spacial hashing, it does not need to be optimized for 
-        specific space and body sizes.
-
-        Other algorithms may be more efficient for collision detection with
-        stationary bodies, bodies that are always evenly distributed, or ad-hoc
-        queries.
-
-        :param collision_component: Name of the collision component used by this
-        	system, defaults to 'collision'. This component supplies each
-        	entities' aabb and collision masks.
-        :type collision_component: str
-        """
-        world = None
-        """|World| object this system belongs to"""
-
-        collision_component = None
-        """Name of world's collision component used by this system"""
-
-        LEFT_ATTR = "left"
-        RIGHT_ATTR = "right"
-        TOP_ATTR = "top"
-        BOTTOM_ATTR = "bottom"
-
-        def __init__(self, collision_component='collision'):
-                self.collision_component = collision_component
-                self._by_x = None
-                self._by_y = None
-                self._collision_pairs = None
-
-        def set_world(self, world):
-                """Bind the system to a world"""
-                self.world = world
-
-        def step(self, dt):
-                """Update the system for this time step, updates and sorts the 
-                axis arrays.
-                """
-                component = getattr(self.world.components, self.collision_component)
-                LEFT = self.LEFT_ATTR
-                RIGHT = self.RIGHT_ATTR
-                TOP = self.TOP_ATTR
-                BOTTOM = self.BOTTOM_ATTR
-                if self._by_x is None:
-                        # Build axis lists from scratch
-                        # Note we cache the box positions here
-                        # so that we can perform hit tests efficiently
-                        # it also isolates us from changes made to the 
-                        # box positions after we run
-                        by_x = self._by_x = []
-                        append_x = by_x.append
-                        by_y = self._by_y = []
-                        append_y = by_y.append
-                        for data in component.itervalues():
-                                append_x([data.aabb.left, LEFT, data])
-                                append_x([data.aabb.right, RIGHT, data])
-                                append_y([data.aabb.bottom, BOTTOM, data])
-                                append_y([data.aabb.top, TOP, data])
-                else:
-                        by_x = self._by_x
-                        by_y = self._by_y
-                        removed = []
-                        for entry in by_x:
-                                entry[0] = getattr(entry[2].aabb, entry[1])
-                        for entry in by_y:
-                                entry[0] = getattr(entry[2].aabb, entry[1])
-                        # Removing entities is inefficient, but expected to be rare
-                        if component.deleted_entities:
-                                deleted_entities = component.deleted_entities
-                                deleted_x = []
-                                deleted_y = []
-                                for i, (_, _, data) in enumerate(by_x):
-                                        if data.entity in deleted_entities:
-                                                deleted_x.append(i)
-                                deleted_x.reverse()
-                                for i in deleted_x:
-                                        del by_x[i]
-                                for i, (_, _, data) in enumerate(by_y):
-                                        if data.entity in deleted_entities:
-                                                deleted_y.append(i)
-                                deleted_y.reverse()
-                                for i in deleted_y:
-                                        del by_y[i]
-                        # Tack on new entities
-                        for entity in component.new_entities:
-                                data = component[entity]
-                                by_x.append([data.aabb.left, LEFT, data])
-                                by_x.append([data.aabb.right, RIGHT, data])
-                                by_y.append([data.aabb.bottom, BOTTOM, data])
-                                by_y.append([data.aabb.top, TOP, data])
-
-                # Tim-sort is highly efficient with mostly sorted lists.
-                # Because positions tend to change little each frame
-                # we take advantage of this here. Obviously things are
-                # less efficient with very fast moving, or teleporting entities
-                by_x.sort()
-                by_y.sort()
-                self._collision_pairs = None
-
-        @property
-        def collision_pairs(self):
-                """Set of candidate collision pairs for this timestep"""
-                if self._collision_pairs is None:
-                        if self._by_x is None:
-                                # Axis arrays not ready
-                                return set()
-
-                        LEFT = self.LEFT_ATTR
-                        RIGHT = self.RIGHT_ATTR
-                        TOP = self.TOP_ATTR
-                        BOTTOM = self.BOTTOM_ATTR
-                        # Build candidates overlapping along the x-axis
-                        component = getattr(self.world.components, self.collision_component)
-                        xoverlaps = set()
-                        add_xoverlap = xoverlaps.add
-                        discard_xoverlap = xoverlaps.discard
-                        open = {}
-                        for _, side, data in self._by_x:
-                                if side is LEFT:
-                                        for open_entity, (from_mask, into_mask) in open.iteritems():
-                                                if data.from_mask & into_mask or from_mask & data.into_mask:
-                                                        add_xoverlap(Pair(data.entity, open_entity))
-                                        open[data.entity] = (data.from_mask, data.into_mask)
-                                elif side is RIGHT:
-                                        del open[data.entity]
-
-                        if len(xoverlaps) <= 10 and len(xoverlaps)*4 < len(self._by_y):
-                                # few candidates were found, so just scan the x overlap candidates
-                                # along y. This requires an additional sort, but it should
-                                # be cheaper than scanning everyone and its simpler
-                                # than a separate brute-force check
-                                entities = set([entity for entity, _ in xoverlaps] 
-                                               + [entity for _, entity in xoverlaps])
-                                by_y = []
-                                for entity in entities:
-                                        data = component[entity]
-                                        # We can use tuples here, which are cheaper to create
-                                        by_y.append((data.aabb.bottom, BOTTOM, data))
-                                        by_y.append((data.aabb.top, TOP, data))
-                                by_y.sort()
-                        else:
-                                by_y = self._by_y
-
-                        # Now check the candidates along the y-axis
-                        open = set()
-                        add_open = open.add
-                        discard_open = open.discard
-                        self._collision_pairs = set()
-                        add_pair = self._collision_pairs.add
-                        for _, side, data in by_y:
-                                if side is BOTTOM:
-                                        for open_entity in open:
-                                                pair = Pair(data.entity, open_entity)
-                                                if pair in xoverlaps:
-                                                        discard_xoverlap(pair)
-                                                        add_pair(pair)
-                                                        if not xoverlaps:
-                                                                # No more candidates, bail
-                                                                return self._collision_pairs
-                                        add_open(data.entity)
-                                elif side is TOP:
-                                        discard_open(data.entity)
-                return self._collision_pairs
-
-        def query_point(self, x_or_point, y=None, from_mask=0xffffffff):
-                """Hit test at the point specified. 
-
-                :param x_or_point: x coordinate (float) or sequence of (x, y) floats.
-
-                :param y: y coordinate (float) if x is not a sequence
-
-                :param from_mask: Bit mask used to filter query results. This value
-                	is bit ANDed with candidate entities' ``collision.into_mask``.
-                	If the result is non-zero, then it is considered a hit. By
-                	default all entities colliding with the input point are
-                	returned.
-
-                :return: A set of entities where the point is inside their bounding
-                	boxes as of the last time step.
-                """
-                if self._by_x is None:
-                        # Axis arrays not ready
-                        return set()
-                if y is None:
-                        x, y = x_or_point
-                else:
-                        x = x_or_point
-                LEFT = self.LEFT_ATTR
-                RIGHT = self.RIGHT_ATTR
-                TOP = self.TOP_ATTR
-                BOTTOM = self.BOTTOM_ATTR
-                x_index = bisect_right(self._by_x, [x])
-                x_hits = set()
-                add_x_hit = x_hits.add
-                discard_x_hit = x_hits.discard
-                if x_index <= len(self._by_x) // 2:
-                        # closer to the left, scan from left to right
-                        while (x == self._by_x[x_index][0] 
-                               and self._by_x[x_index][1] is LEFT 
-                               and x_index < len(self._by_x)):
-                                # Ensure we hit on exact left edge matches
-                                x_index += 1
-                        for _, side, data in self._by_x[:x_index]:
-                                if side is LEFT and from_mask & data.into_mask:
-                                        add_x_hit(data.entity)
-                                else:
-                                        discard_x_hit(data.entity)
-                else:
-                        # closer to the right
-                        for _, side, data in reversed(self._by_x[x_index:]):
-                                if side is RIGHT and from_mask & data.into_mask:
-                                        add_x_hit(data.entity)
-                                else:
-                                        discard_x_hit(data.entity)
-                if not x_hits:
-                        return x_hits
-
-                y_index = bisect_right(self._by_y, [y])
-                y_hits = set()
-                add_y_hit = y_hits.add
-                discard_y_hit = y_hits.discard
-                if y_index <= len(self._by_y) // 2:
-                        # closer to the bottom
-                        while (y == self._by_y[y_index][0] 
-                               and self._by_y[y_index][1] is BOTTOM 
-                               and y_index < len(self._by_y)):
-                                # Ensure we hit on exact bottom edge matches
-                                y_index += 1
-                        for _, side, data in self._by_y[:y_index]:
-                                if side is BOTTOM:
-                                        add_y_hit(data.entity)
-                                else:
-                                        discard_y_hit(data.entity)
-                else:
-                        # closer to the top
-                        for _, side, data in reversed(self._by_y[y_index:]):
-                                if side is TOP:
-                                        add_y_hit(data.entity)
-                                else:
-                                        discard_y_hit(data.entity)
-                if y_hits:
-                        return x_hits & y_hits
-                else:
-                        return y_hits
-
-
-class Circular(object):
-        """Basic narrow-phase collision detector which treats all entities as
-        circles with their radius defined in the collision component.
-
-        :param handlers: A sequence of collision handler functions that are invoked
-        	after collision detection.
-        :type handlers: sequence of functions
-
-        :param collision_component: Name of collision component for this system,
-        	defaults to 'collision'. This supplies each entity's collision
-        	radius and masks.
-        :type collision_component: str
-
-        :param position_component: Name of position component for this system,
-        	defaults to 'position'. This supplies each entity's position.
-        :type position_component: str
-
-        :param update_aabbs: If True (the default), then the entities'
-        	`collision.aabb` fields will be updated using their position
-        	and collision radius before invoking the broad phase system. 
-        	Set this False if another system updates the aabbs.
-        :type update_aabbs: bool
-
-        :param broad_phase: A broad-phase collision system to use as a source
-        	for collision pairs. If not specified, a :class:`BroadSweepAndPrune`
-        	system will be created automatically.
-        """
-        world = None
-        """|World| object this system belongs to"""
-
-        position_component = None
-        """Name of world's position component used by this system"""
-
-        collision_component = None
-        """Name of world's collision component used by this system"""
-
-        update_aabbs = True
-        """Flag to indicate whether the system updates the entities' `collision.aabb`
-	field before invoking the broad phase collision system
-	"""
-
-        handlers = None
-        """A sequence of collision handler functions invoke after collision
-	detection
-	"""
-
-        broad_phase = None
-        """Broad phase collision system used as a source for collision pairs"""
-
-        def __init__(self, handlers=(), position_component='position', 
-                     collision_component='collision', update_aabbs=True, broad_phase=None):
-                self.handlers = tuple(handlers)
-                if broad_phase is None:
-                        broad_phase = BroadSweepAndPrune(collision_component)
-                self.collision_component = collision_component
-                self.position_component = position_component
-                self.update_aabbs = bool(update_aabbs)
-                self.broad_phase = broad_phase
-                self._collision_pairs = None
-
-        def set_world(self, world):
-                """Bind the system to a world"""
-                self.world = world
-                self.broad_phase.set_world(world)
-                for handler in self.handlers:
-                        if hasattr(handler, 'set_world'):
-                                handler.set_world(world)
-
-        def step(self, dt):
-                """Update the collision system for this time step and invoke
-                the handlers
-                """
-                if self.update_aabbs:
-                        for position, collision in self.world.components.join(
-                                self.position_component, self.collision_component):
-                                aabb = collision.aabb
-                                x, y = position.position
-                                radius = collision.radius
-                                aabb.left = x - radius
-                                aabb.right = x + radius
-                                aabb.bottom = y - radius
-                                aabb.top = y + radius
-                self.broad_phase.step(dt)
-                self._collision_pairs = None
-                for handler in self.handlers:
-                        handler(self)
-
-        @property
-        def collision_pairs(self):
-                """The set of entity pairs in collision in this timestep"""
-                if self._collision_pairs is None:
-                        position = getattr(self.world.components, self.position_component)
-                        collision = getattr(self.world.components, self.collision_component)
-                        pairs = self._collision_pairs = set()
-                        for pair in self.broad_phase.collision_pairs:
-                                entity1, entity2 = pair
-                                position1 = position[entity1].position
-                                position2 = position[entity2].position
-                                radius1 = collision[entity1].radius
-                                radius2 = collision[entity2].radius
-                                separation = position2 - position1
-                                if separation.get_length_sqrd() <= (radius1 + radius2)**2:
-                                        normal = separation.normalized()
-                                        pair.set_point_normal(
-                                                normal * radius1 + position1, normal,
-                                                normal * -radius2 + position2, -normal)
-                                        pairs.add(pair)
-                return self._collision_pairs
-
-        def query_point(self, x_or_point, y=None, from_mask=0xffffffff):
-                """Hit test at the point specified. 
-
-                :param x_or_point: x coordinate (float) or sequence of (x, y) floats.
-
-                :param y: y coordinate (float) if x is not a sequence
-
-                :param from_mask: Bit mask used to filter query results. This value
-                	is bit ANDed with candidate entities' ``collision.into_mask``.
-                	If the result is non-zero, then it is considered a hit. By
-                	default all entities colliding with the input point are
-                	returned.
-
-                :return: A set of entities where the point is inside their collision
-                	radii as of the last time step.
-
-                """
-                if y is None:
-                        point = Vec2d(x_or_point)
-                else:
-                        point = Vec2d(x_or_point, y)
-                hits = set()
-                position = getattr(self.world.components, self.position_component)
-                collision = getattr(self.world.components, self.collision_component)
-                for entity in self.broad_phase.query_point(x_or_point, y, from_mask):
-                        separation = point - position[entity].position
-                        if separation.get_length_sqrd() <= collision[entity].radius**2:
-                                hits.add(entity)
-                return hits
-
-
-def dispatch_events(collision_system):
-        """Collision handler that dispatches `on_collide()` events to entities
-        marked for collision by the specified collision system. The `on_collide()`
-        event handler methods are defined by the application on the desired entity
-        classes. These methods should have the following signature::
-
-        	def on_collide(self, other_entity, collision_point, collision_normal):
-        		'''Handle A collision between this entity and `other_entity`
-
-        		- other_entity (Entity): The other entity in collision with 
-        		  `self`
-
-        		- collision_point (Vec2d): The point on this entity (`self`)
-        		  where the collision occurred. Note this may be `None` for 
-        		  some collision systems that do not report it.
-
-        		- collision_normal (Vec2d): The normal vector at the point of
-        		  collision. As with `collision_point`, this may be None for
-        		  some collision systems.
-        		'''
-
-        Note the arguments to `on_collide()` are always passed positionally, so you
-        can use different argument names than above if desired.
-
-        If a pair of entities are in collision, then the event will be dispatched
-        to both objects in arbitrary order if all of their collision masks align.
-        """
-        collision = getattr(collision_system.world.components, 
-                            collision_system.collision_component)
-        for pair in collision_system.collision_pairs:
-                entity1, entity2 = pair
-                if pair.info is not None:
-                        args1, args2 = pair.info
-                else:
-                        args1 = entity1, None, None
-                        args2 = entity2, None, None
-                try:
-                        on_collide = entity1.on_collide
-                        masks_align = collision[entity2].from_mask & collision[entity1].into_mask
-                except (AttributeError, KeyError):
-                        pass
-                else:
-                        if masks_align:
-                                on_collide(*args2)
-                try:
-                        on_collide = entity2.on_collide
-                        masks_align = collision[entity1].from_mask & collision[entity2].into_mask
-                except (AttributeError, KeyError):
-                        pass
-                else:
-                        if masks_align:
-                                on_collide(*args1)
--- a/src/parpg/bGrease/color.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-
-class RGBA(object):
-	"""Four channel color representation.
-
-	RGBA colors are floating point color representations with color channel
-	values between (0..1). Colors may be initialized from 3 or 4 floating
-	point numbers or a hex string::
-
-		RGBA(1.0, 1.0, 1.0) # Alpha defaults to 1.0
-		RGBA(1.0, 1.0, 0, 0.5)
-		RGBA("#333")
-		RGBA("#7F7F7F")
-	
-	Individual color channels can be accessed by attribute name, or the
-	color object can be treated as a sequence of 4 floats.
-	"""
-
-	def __init__(self, r_or_colorstr, g=None, b=None, a=None):
-		if isinstance(r_or_colorstr, str):
-			assert g is b is a is None, "Ambiguous color arguments" 
-			self.r, self.g, self.b, self.a = self._parse_colorstr(r_or_colorstr)
-		elif g is b is a is None:
-			try:
-				self.r, self.g, self.b, self.a = r_or_colorstr
-			except ValueError:
-				self.r, self.g, self.b = r_or_colorstr
-				self.a = 1.0
-		else:
-			self.r = r_or_colorstr
-			self.g = g
-			self.b = b
-			self.a = a
-		if self.a is None:
-			self.a = 1.0
-	
-	def _parse_colorstr(self, colorstr):
-		length = len(colorstr)
-		if not colorstr.startswith("#") or length not in (4, 5, 7, 9):
-			raise ValueError("Invalid color string: " + colorstr)
-		if length <= 5:
-			parsed = [int(c*2, 16) / 255.0 for c in colorstr[1:]]
-		else:
-			parsed = [int(colorstr[i:i+2], 16) / 255.0 for i in range(1, length, 2)]
-		if len(parsed) == 3:
-			parsed.append(1.0)
-		return parsed
-	
-	def __len__(self):
-		return 4
-	
-	def __getitem__(self, item):
-		return (self.r, self.g, self.b, self.a)[item]
-	
-	def __iter__(self):
-		return iter((self.r, self.g, self.b, self.a))
-	
-	def __eq__(self, other):
-		return tuple(self) == tuple(other)
-	
-	def __repr__(self):
-		return "%s(%.2f, %.2f, %.2f, %.2f)" % (self.__class__.__name__, 
-			self.r, self.g, self.b, self.a)
-			
-			
--- a/src/parpg/bGrease/component/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-"""Components store all entity data in a given |World|. You can
-think of components as tables with entities as their primary keys. Like
-database tables, components are defined with a "schema" that specifies
-the data fields. Each field in a component has a name and a type.
-
-Component objects themselves have a dict-like interface with entities
-as keys and data records as values. An application will typically 
-interact with components via entity attributes, entity extents or
-by joining them. For more information see:
-
-- :class:`~grease.entity.Entity` class.
-- :class:`~grease.world.EntityExtent` class.
-- :meth:`~grease.world.ComponentParts.join` method of ComponentParts.
-
-See also :ref:`defining custom components in the tutorial <custom-component-example>`.
-"""
-
-__version__ = '$Id$'
-
-__all__ = ('Component', 'ComponentError', 'Position', 'Transform', 'Movement', 
-           'Shape', 'Renderable', 'Collision')
-
-from parpg.bGrease.component.general import Component
-from parpg.bGrease.geometry import Vec2d, Vec2dArray, Rect
-from parpg.bGrease import color
-
-
-class ComponentError(Exception):
-        """General component error"""
-
-
-class Position(Component):
-        """Predefined component that stores position and orientation info for 
-        entities.
-
-        Fields:
-
-        - **position** (Vec2d) -- Position vector
-        - **angle** (float) -- Angle, in degrees
-        """
-
-        def __init__(self):
-                Component.__init__(self, position=Vec2d, angle=float)
-
-
-class Transform(Component):
-        """Predefined component that stores offset, shear, 
-        rotation and scale info for entity shapes.
-
-        Fields:
-
-        - **offset** (Vec2d)
-        - **shear** (Vec2d)
-        - **rotation** (float)
-        - **scale** (float, default 1.0)
-        """
-
-        def __init__(self):
-                Component.__init__(self, offset=Vec2d, shear=Vec2d, rotation=float, scale=float)
-                self.fields['scale'].default = lambda: 1.0
-
-
-class Movement(Component):
-        """Predefined component that stores velocity, 
-        acceleration and rotation info for entities.
-
-        Fields:
-
-        - **velocity** (Vec2d) -- Rate of change of entity position
-        - **accel** (Vec2d) -- Rate of change of entity velocity
-        - **rotation** (Vec2d) -- Rate of change of entity angle, in degrees/time
-        """
-
-        def __init__(self):
-                Component.__init__(self, velocity=Vec2d, accel=Vec2d, rotation=float)
-
-
-class Shape(Component):
-        """Predefined component that stores shape vertices for entities
-
-        - **closed** (bool) -- If the shapes is closed implying an edge between
-          last and first vertices.
-        - **verts** (Vec2dArray) -- Array of vertex points
-        """
-
-        def __init__(self):
-                Component.__init__(self, closed=int, verts=Vec2dArray)
-                self.fields['closed'].default = lambda: 1
-
-
-class Renderable(Component):
-        """Predefined component that identifies entities to be 
-        rendered and provides their depth and color.
-
-        - **depth** (float) -- Drawing depth, can be used to determine z-order
-        	  while rendering.
-        - **color** (color.RGBA) -- Color used for entity. The effect of this
-        	  field depends on the renderer.
-        """
-
-        def __init__(self):
-                Component.__init__(self, depth=float, color=color.RGBA)
-                self.fields['color'].default = lambda: color.RGBA(1,1,1,1)
-
-
-class Collision(Component):
-        """Predefined component that stores collision masks to determine 
-        which entities can collide.
-
-        Fields:
-
-        - **aabb** (Rect) -- The axis-aligned bounding box for the entity.
-        	This is used for broad-phase collision detection.
-
-        - **radius** (float) -- The collision radius of the entity, used for narrow-phase
-        	collision detection. The exact meaning of this value depends on the collision
-        	system in use.
-
-        - **from_mask** (int) -- A bitmask that determines what entities this object
-        	can collide with.
-
-        - **into_mask** (int) -- A bitmask that determines what entities can collide
-        	with this object.
-
-        When considering an entity A for collision with entity B, A's ``from_mask`` is
-        bit ANDed with B's ``into_mask``. If the result is nonzero (meaning 1 or more
-        bits is set the same for each) then the collision test is made. Otherwise,
-        the pair cannot collide. 
-
-        The default value for both of these masks is ``0xffffffff``, which means that
-        all entities will collide with each other by default.
-        """
-        def __init__(self):
-                Component.__init__(self, aabb=Rect, radius=float, from_mask=int, into_mask=int)
-                self.fields['into_mask'].default = lambda: 0xffffffff
-                self.fields['from_mask'].default = lambda: 0xffffffff
--- a/src/parpg/bGrease/component/base.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-class ComponentBase(object):
-	"""Component abstract base class
-
-	Strictly speaking you do not need to derive from this class to create your
-	own components, but it does serve to document the full interface that a
-	component implements and it provides some basic implementations for
-	certain methods
-	"""
-
-	## Optional attributes and methods ##
-
-	def set_manager(self, manager):
-		"""Set the manager of this component. If this method exists it will be
-		automatically called when the component is added to a manager.
-
-		This method stores the manager and allows the component to be added
-		only once to a single manager.
-		"""
-		assert getattr(self, 'manager', None) is None, 'Component cannot be added to multiple managers'
-		self.manager = manager
-
-	def __del__(self):
-		"""Break circrefs to allow faster collection"""
-		if hasattr(self, 'manager'):
-			del self.manager
-	
-	## Mandatory methods ##
-
-	def add(self, entity_id, data=None, **data_kw):
-		"""Add a data entry in the component for the given entity.  Additional
-		data (if any) for the entry can be provided in the data argument or as
-		keyword arguments. Additional data is optional and if omitted then
-		suitable defaults will be used. Return an entity data object
-		for the new entity entry.
-
-		The semantics of the data arguments is up to the component.
-
-		An entity_id is a unique key, thus multiple separate data entries for
-		a given entity are not allowed.  Components can indivdually decide
-		what to do if an entity_id is added multiple times to the component.
-		Potential options include, raising an exception, replacing the
-		existing data or coalescing it somehow.
-		"""
-	
-	def remove(self, entity_id):
-		"""Remove the entity data entry from the component. If the
-		entity is not in the component, raise KeyError
-		"""
-	
-	def __delitem_(self, entity_id):
-		"""Same as remove()"""
-
-	def __len__(self):
-		"""Return the number of entities in the component"""
-		raise NotImplementedError()
-	
-	def __iter__(self):
-		"""Return an iterator of entity data objects in this component
-
-		No order is defined for these data objects
-		"""
-		raise NotImplementedError()
-	
-	def __contains__(self, entity_id):
-		"""Return True if the entity is contained in the component"""
-		raise NotImplementedError()
-	
-	def __getitem__(self, entity_id):
-		"""Return the entity data object for the given entity. 
-		The entity data object returned may be mutable, immutable or a
-		mutable copy of the data at the discretion of the component
-		"""
-		raise NotImplementedError()
-
--- a/src/parpg/bGrease/component/field.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,303 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-
-__version__ = '$Id$'
-
-import operator
-from parpg.bGrease.geometry import Vec2d, Vec2dArray, Rect
-from parpg.bGrease import color
-
-# Allowed field types -> default values
-types = {int:lambda: 0, 
-         float:lambda: 0.0, 
-         bool:lambda: False,
-         str:lambda:"", 
-         object:lambda:None,
-         Vec2d:lambda: Vec2d(0,0), 
-         Vec2dArray:lambda: Vec2dArray(),
-         color.RGBA: lambda: color.RGBA(0.0, 0.0, 0.0, 0.0),
-         Rect: lambda: Rect(0.0, 0.0, 0.0, 0.0),
-         list: lambda: list(),
-         dict: lambda: dict(),
-         }
-
-class Schema(dict):
-        """Field schema definition for custom components"""
-
-        def __init__(self, **fields):
-                for ftype in fields.values():
-                        assert ftype in types, fname + " has an illegal field type"
-                self.update(fields)
-
-
-class FieldAccessor(object):
-        """Facade for manipulating a field for a set of entities"""
-
-        __field = None
-        __entities = None
-        __attrs = None
-        __getter = None
-        __parent_getters = ()
-
-        def __init__(self, field, entities, attrs=()):
-                self.__field = field
-                self.__entities = entities
-                field_getter = operator.attrgetter(field.name)
-                self.__attrs = attrs
-                if attrs:
-                        getters = [field_getter] + [operator.attrgetter(attr) for attr in attrs]
-                        def get(entity):
-                                value = entity
-                                for getter in getters:
-                                        value = getter(value)
-                                return value
-                        self.__getter = get
-                        self.__parent_getters = getters[:-1]
-                else:
-                        self.__getter = field_getter
-
-        def __getattr__(self, name):
-                """Return a FieldAccessor for the child attribute"""
-                return self.__class__(self.__field, self.__entities, self.__attrs + (name,))
-
-        def __setattr__(self, name, value):
-                if value is self:
-                        return # returned by mutators
-                if hasattr(self.__class__, name):
-                        # Set local attr
-                        self.__dict__[name] = value
-                elif not name.startswith('_'):
-                        getattr(self, name).__set__(value)
-                else:
-                        raise AttributeError("Cannot set field attribute: %s" % name)
-
-        @property
-        def __setter(self):
-                """Return the proper setter function for setting the field value"""
-                if not self.__attrs:
-                        return setattr
-                else:
-                        parent_getters = self.__parent_getters
-                        def setter(data, name, value):
-                                for getter in parent_getters:
-                                        data = getter(data)
-                                setattr(data, name, value)
-                        self.__setter = setter
-                        return setter
-
-        def __set__(self, value):
-                """Set field values en masse"""
-                # Mass set field attr
-                setter = self.__setter
-                component = self.__field.component
-                if self.__attrs:
-                        name = self.__attrs[-1]
-                else:
-                        name = self.__field.name
-                if isinstance(value, FieldAccessor):
-                        # Join set between two entity sets
-                        if not self.__attrs:
-                                cast = self.__field.cast
-                        else: 
-                                cast = lambda x: x
-                        for entity in self.__entities:
-                                try:
-                                        setter(component[entity], name, cast(value[entity]))
-                                except KeyError:
-                                        pass
-                else:
-                        if not self.__attrs:
-                                value = self.__field.cast(value)
-                        for entity in self.__entities:
-                                try:
-                                        setter(component[entity], name, value)
-                                except KeyError:
-                                        pass
-
-        def __getitem__(self, entity):
-                """Return the field value for a single entity (used for joins)"""
-                if entity in self.__entities:
-                        return self.__getter(self.__field.component[entity])
-                raise KeyError(entity)
-
-        def __contains__(self, entity):
-                return entity in self.__entities
-
-        def __repr__(self):
-                return '<%s %s @ %x>' % (
-                        self.__class__.__name__, 
-                        '.'.join((self.__field.name,) + self.__attrs), id(self))
-
-        def __nonzero__(self):
-                return bool(self.__entities)
-
-        def __iter__(self):
-                """Return an iterator of all field values in the set"""
-                component = self.__field.component
-                getter = self.__getter
-                for entity in self.__entities:
-                        try:
-                                data = component[entity]
-                        except KeyError:
-                                continue
-                        yield getter(data)
-
-        ## batch comparison operators ##
-
-        def __match(self, value, op):
-                component = self.__field.component
-                getter = self.__getter
-                matches = set()
-                add = matches.add
-                if isinstance(value, FieldAccessor):
-                        # Join match between entity sets
-                        for entity in self.__entities:
-                                try:
-                                        data = component[entity]
-                                        other = value[entity]
-                                except KeyError:
-                                        continue
-                                if op(getter(data), other):
-                                        add(entity)
-                else:
-                        for entity in self.__entities:
-                                try:
-                                        data = component[entity]
-                                except KeyError:
-                                        continue
-                                if op(getter(data), value):
-                                        add(entity)
-                return matches
-
-        def __eq__(self, value):
-                """Return an entity set of all entities with a matching field value"""
-                return self.__match(value, operator.eq)
-
-        def __ne__(self, value):
-                """Return an entity set of all entities not matching field value"""
-                return self.__match(value, operator.ne)
-
-        def __gt__(self, value):
-                """Return an entity set of all entities with a greater field value"""
-                return self.__match(value, operator.gt)
-
-        def __ge__(self, value):
-                """Return an entity set of all entities with a greater or equal field value"""
-                return self.__match(value, operator.ge)
-
-        def __lt__(self, value):
-                """Return an entity set of all entities with a lesser field value"""
-                return self.__match(value, operator.lt)
-
-        def __le__(self, value):
-                """Return an entity set of all entities with a lesser or equal field value"""
-                return self.__match(value, operator.le)
-
-        def _contains(self, values):
-                """Return an entity set of all entities with a field value contained in values"""
-                return self.__match(values, operator.contains)
-
-        ## Batch in-place mutator methods
-
-        def __mutate(self, value, op):
-                component = self.__field.component
-                if self.__attrs:
-                        name = self.__attrs[-1]
-                else:
-                        name = self.__field.name
-                getter = self.__getter
-                setter = self.__setter
-                if isinstance(value, FieldAccessor):
-                        # Join between entity sets
-                        for entity in self.__entities:
-                                try:
-                                        data = component[entity]
-                                        other = value[entity]
-                                except KeyError:
-                                        continue
-                                setter(data, name, op(getter(data), other))
-                else:
-                        for entity in self.__entities:
-                                try:
-                                        data = component[entity]
-                                except KeyError:
-                                        continue
-                                setter(data, name, op(getter(data), value))
-                return self
-
-        def __iadd__(self, value):
-                return self.__mutate(value, operator.iadd)
-
-        def __isub__(self, value):
-                return self.__mutate(value, operator.isub)
-
-        def __imul__(self, value):
-                return self.__mutate(value, operator.imul)
-
-        def __idiv__(self, value):
-                return self.__mutate(value, operator.idiv)
-
-        def __itruediv__(self, value):
-                return self.__mutate(value, operator.itruediv)
-
-        def __ifloordiv__(self, value):
-                return self.__mutate(value, operator.ifloordiv)
-
-        def __imod__(self, value):
-                return self.__mutate(value, operator.imod)
-
-        def __ipow__(self, value):
-                return self.__mutate(value, operator.ipow)
-
-        def __ilshift__(self, value):
-                return self.__mutate(value, operator.ilshift)
-
-        def __irshift__(self, value):
-                return self.__mutate(value, operator.irshift)
-
-        def __iand__(self, value):
-                return self.__mutate(value, operator.iand)
-
-        def __ior__(self, value):
-                return self.__mutate(value, operator.ior)
-
-        def __ixor__(self, value):
-                return self.__mutate(value, operator.ixor)
-
-
-class Field(object):
-        """Component field metadata and accessor interface"""
-
-        def __init__(self, component, name, type, accessor_factory=FieldAccessor):
-                self.component = component
-                self.name = name
-                self.type = type
-                self.default = types.get(type)
-                self.accessor_factory = accessor_factory
-
-        def cast(self, value):
-                """Cast value to the appropriate type for thi field"""
-                if self.type is not object:
-                        return self.type(value)
-                else:
-                        return value
-
-        def accessor(self, entities=None):
-                """Return the field accessor for the entities in the component,
-                or all entities in the set specified that are also in the component
-                """
-                if entities is None or entities is self.component.entities:
-                        entities = self.component.entities
-                else:
-                        entities = entities & self.component.entities
-                return self.accessor_factory(self, entities)
--- a/src/parpg/bGrease/component/general.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-
-__version__ = '$Id$'
-
-from parpg.bGrease.component import base
-from parpg.bGrease.component import field
-from parpg.bGrease.entity import ComponentEntitySet
-
-
-class Component(dict):
-        """General component with a configurable schema
-
-        The field schema is defined via keyword args where the 
-        arg name is the field name and the value is the type object.
-
-        The following types are supported for fields:
-
-        - :class:`int`
-        - :class:`float`
-        - :class:`bool`
-        - :class:`str`
-        - :class:`object`
-        - |Vec2d|
-        - |Vec2dArray|
-        - |RGBA|
-        - |Rect|
-        """
-
-        deleted_entities = ()
-        """List of entities deleted from the component since the last time step"""
-
-        new_entities = ()
-        """List of entities added to the component since the last time step"""
-
-        def __init__(self, **fields):
-                self.fields = {}
-                for fname, ftype in fields.items():
-                        assert ftype in field.types, fname + " has an illegal field type"
-                        self.fields[fname] = field.Field(self, fname, ftype)
-                self.entities = ComponentEntitySet(self)
-                self._added = []
-                self._deleted = []
-
-        def set_world(self, world):
-                self.world = world
-
-        def step(self, dt):
-                """Update the component for the next timestep"""
-                delitem = super(Component, self).__delitem__
-                for entity in self._deleted:
-                        delitem(entity)
-                self.new_entities = self._added
-                self.deleted_entities = self._deleted
-                self._added = []
-                self._deleted = []
-
-        def set(self, entity, data=None, **data_kw):
-                """Set the component data for an entity, adding it to the
-                component if it is not already a member.
-
-                If data is specified, its data for the new entity's fields are
-                copied from its attributes, making it easy to copy another
-                entity's data. Keyword arguments are also matched to fields.
-                If both a data attribute and keyword argument are supplied for
-                a single field, the keyword arg is used.
-                """
-                if data is not None:
-                        for fname, field in self.fields.items():
-                                if fname not in data_kw and hasattr(data, fname):
-                                        data_kw[fname] = getattr(data, fname)
-                data = self[entity] = Data(self.fields, entity, **data_kw)
-                return data
-
-        def __setitem__(self, entity, data):
-                assert entity.world is self.world, "Entity not in component's world"
-                if entity not in self.entities:
-                        self._added.append(entity)
-                        self.entities.add(entity)
-                super(Component, self).__setitem__(entity, data)
-
-        def remove(self, entity):
-                if entity in self.entities:
-                        self._deleted.append(entity)
-                        self.entities.remove(entity)
-                        return True
-                return False
-
-        __delitem__ = remove
-
-        def __repr__(self):
-                return '<%s %x of %r>' % (
-                        self.__class__.__name__, id(self), getattr(self, 'world', None))
-
-
-class Singleton(Component):
-        """Component that may contain only a single entity"""
-
-        def add(self, entity_id, data=None, **data_kw):
-                if entity_id not in self._data:
-                        self.entity_id_set.clear()
-                        self._data.clear()
-                Component.add(self, entity_id, data, **data_kw)
-
-        @property
-        def entity(self):
-                """Return the entity in the component, or None if empty"""
-                if self._data:
-                        return self.manager[self._data.keys()[0]]
-
-
-class Data(object):
-
-        def __init__(self, fields, entity, **data):
-                self.__dict__['_Data__fields'] = fields
-                self.__dict__['entity'] = entity
-                for field in fields.values():
-                        if field.name in data:
-                                setattr(self, field.name, data[field.name])
-                        else:
-                                setattr(self, field.name, field.default())
-
-        def __setattr__(self, name, value):
-                if name in self.__fields:
-                        self.__dict__[name] = self.__fields[name].cast(value)
-                else:
-                        raise AttributeError("Invalid data field: " + name)
-
-        def __repr__(self):
-                return '<%s(%r)>' % (self.__class__.__name__, self.__dict__)
-
-
--- a/src/parpg/bGrease/component/schema.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/src/parpg/bGrease/controller/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-
-__all__ = ('EulerMovement',)
-
-from parpg.bGrease.controller.integrator import EulerMovement
--- a/src/parpg/bGrease/controller/integrator.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-
-__version__ = '$Id$'
-
-
-class EulerMovement(object):
-	"""System that applies entity movement to position using Euler's method
-
-	:param position_component: Name of :class:`grease.component.Position` 
-		component to update.
-	:param movement_component: Name of :class:`grease.component.Movement` 
-		component used to update position.
-	"""
-
-	def __init__(self, position_component='position', movement_component='movement'):
-		self.position_component = position_component
-		self.movement_component = movement_component
-	
-	def set_world(self, world):
-		"""Bind the system to a world"""
-		self.world = world
-	
-	def step(self, dt):
-		"""Apply movement to position"""
-		assert self.world is not None, "Cannot run with no world set"
-		for position, movement in self.world.components.join(
-			self.position_component, self.movement_component):
-			movement.velocity += movement.accel * dt
-			position.position += movement.velocity * dt
-			position.angle += movement.rotation * dt
-
--- a/src/parpg/bGrease/entity.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-"""Grease entities are useful as actionable, interactive
-game elements that are often visible to the player.
-
-You might use entities to represent:
-
-- Characters
-- Bullets
-- Particles
-- Pick-ups
-- Space Ships
-- Weapons
-- Trees
-- Planets
-- Explosions
-
-See :ref:`an example entity class in the tutorial <tut-entity-example>`.
-"""
-
-__version__ = '$Id$'
-
-__all__ = ('Entity', 'EntityComponentAccessor', 'ComponentEntitySet')
-
-
-class EntityMeta(type):
-	"""The entity metaclass enforces fixed slots of `entity_id` and `world`
-	for all subclasses. This prevents accidental use of other entity instance 
-	attributes, which may not be saved. 
-	
-	Class attributes are not affected by this restriction, but subclasses
-	should be careful not to cause name collisions with world components,
-	which are exposed as entity attributes. Using a naming convention for
-	class attributes, such as UPPER_CASE_WITH_UNDERSCORES is recommended to
-	avoid name clashes.
-
-	Note as a result of this, entity subclasses are not allowed to define
-	`__slots__`, and doing so will cause a `TypeError` to be raised.
-	"""
-
-	def __new__(cls, name, bases, clsdict):
-		if '__slots__' in clsdict:
-			raise TypeError('__slots__ may not be defined in Entity subclasses')
-		clsdict['__slots__'] = ('world', 'entity_id')
-		return type.__new__(cls, name, bases, clsdict)
-
-
-class Entity(object):
-	"""Base class for grease entities.
-	
-	Entity objects themselves are merely identifiers within a :class:`grease.world.World`.
-	They also provide a facade for convenient entity-wise access of component
-	data. However, they do not contain any data themselves other than an
-	entity id.
-
-	Entities must be instantiated in the context of a world. To instantiate an
-	entity, you must pass the world as the first argument to the constructor.
-	Subclasses that implement the :meth:`__init__()` method, must accept the world
-	as their first argument (after ``self``). Other constructor arguments can be
-	specified arbitarily by the subclass.
-	"""
-	__metaclass__ = EntityMeta
-
-	def __new__(cls, world, *args, **kw):
-		"""Create a new entity and add it to the world"""
-		entity = object.__new__(cls)
-		entity.world = world
-		entity.entity_id = world.new_entity_id()
-		world.entities.add(entity)
-		return entity
-	
-	def __getattr__(self, name):
-		"""Return an :class:`EntityComponentAccessor` for this entity
-		for the component named.
-
-		Example::
-
-			my_entity.movement
-		"""
-		component = getattr(self.world.components, name)
-		return EntityComponentAccessor(component, self)
-	
-	def __setattr__(self, name, value):
-		"""Set the entity data in the named component for this entity.
-		This sets the values of the component fields to the values of
-		the matching attributes of the value provided. This value must
-		have attributes for each of the component fields.
-
-		This allows you to easily copy component data from one entity
-		to another.
-
-		Example::
-
-			my_entity.position = other_entity.position
-		"""
-		if name in self.__class__.__slots__:
-			super(Entity, self).__setattr__(name, value)
-		else:
-			component = getattr(self.world.components, name)
-			component.set(self, value)
-	
-	def __delattr__(self, name):
-		"""Remove this entity and its data from the component.
-		
-		Example::
-		
-			del my_entity.renderable
-		"""
-		component = getattr(self.world.components, name)
-		del component[self]
-	
-	def __hash__(self):
-		return self.entity_id
-	
-	def __eq__(self, other):
-		return self.world is other.world and self.entity_id == other.entity_id
-
-	def __repr__(self):
-		return "<%s id: %s of %s %x>" % (
-			self.__class__.__name__, self.entity_id,
-			self.world.__class__.__name__, id(self.world))
-
-	def delete(self):
-		"""Delete the entity from its world. This removes all of its
-		component data. If then entity has already been deleted, 
-		this call does nothing.
-		"""
-		self.world.entities.discard(self)
-
-	@property
-	def exists(self):
-		"""True if the entity still exists in the world"""
-		return self in self.world.entities
-
-
-class EntityComponentAccessor(object):
-	"""A facade for accessing specific component data for a single entity.
-	The implementation is lazy and does not actually access the component
-	data until needed. If an attribute is set for a component that the 
-	entity is not yet a member of, it is automatically added to the
-	component first.
-
-	:param component: The :class:`grease.Component` being accessed
-	:param entity: The :class:`Entity` being accessed
-	"""
-	
-	# beware, name mangling ahead. We want to avoid clashing with any
-	# user-configured component field names
-	__data = None
-
-	def __init__(self, component, entity):
-		clsname = self.__class__.__name__
-		self.__dict__['_%s__component' % clsname] = component
-		self.__dict__['_%s__entity' % clsname] = entity
-	
-	def __nonzero__(self):
-		"""The accessor is True if the entity is in the component,
-		False if not, for convenient membership tests
-		"""
-		return self.__entity in self.__component
-	
-	def __getattr__(self, name):
-		"""Return the data for the specified field of the entity's component"""
-		if self.__data is None:
-			try:
-				data = self.__component[self.__entity]
-			except KeyError:
-				raise AttributeError(name)
-			clsname = self.__class__.__name__
-			self.__dict__['_%s__data' % clsname] = data
-		return getattr(self.__data, name)
-	
-	def __setattr__(self, name, value):
-		"""Set the data for the specified field of the entity's component"""
-		if self.__data is None:
-			clsname = self.__class__.__name__
-			if self.__entity in self.__component:
-				self.__dict__['_%s__data' % clsname] = self.__component[self.__entity]
-			else:
-				self.__dict__['_%s__data' % clsname] = self.__component.set(self.__entity)
-		setattr(self.__data, name, value)
-
-
-class ComponentEntitySet(set):
-	"""Set of entities in a component, can be queried by component fields"""
-
-	_component = None
-
-	def __init__(self, component, entities=()):
-		self.__dict__['_component'] = component
-		super(ComponentEntitySet, self).__init__(entities)
-	
-	def __getattr__(self, name):
-		if self._component is not None and name in self._component.fields:
-			return self._component.fields[name].accessor(self)
-		raise AttributeError(name)
-	
-	def __setattr__(self, name, value):
-		if self._component is not None and name in self._component.fields:
-			self._component.fields[name].accessor(self).__set__(value)
-		raise AttributeError(name)
-
--- a/src/parpg/bGrease/geometry.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,600 +0,0 @@
-__version__ = "$Id$"
-__docformat__ = "reStructuredText"
-
-import operator
-import math
-import ctypes 
-
-class Vec2d(ctypes.Structure):
-    """2d vector class, supports vector and scalar operators,
-       and also provides a bunch of high level functions
-       """
-    __slots__ = ['x', 'y']
-    
-    @classmethod
-    def from_param(cls, arg):
-        return cls(arg)
-        
-    def __init__(self, x_or_pair, y = None):
-        
-        if y == None:
-            self.x = x_or_pair[0]
-            self.y = x_or_pair[1]
-        else:
-            self.x = x_or_pair
-            self.y = y
- 
-    def __len__(self):
-        return 2
- 
-    def __getitem__(self, key):
-        if key == 0:
-            return self.x
-        elif key == 1:
-            return self.y
-        else:
-            raise IndexError("Invalid subscript "+str(key)+" to Vec2d")
- 
-    def __setitem__(self, key, value):
-        if key == 0:
-            self.x = value
-        elif key == 1:
-            self.y = value
-        else:
-            raise IndexError("Invalid subscript "+str(key)+" to Vec2d")
- 
-    # String representaion (for debugging)
-    def __repr__(self):
-        return 'Vec2d(%s, %s)' % (self.x, self.y)
-    
-    # Comparison
-    def __eq__(self, other):
-        if hasattr(other, "__getitem__") and len(other) == 2:
-            return self.x == other[0] and self.y == other[1]
-        else:
-            return False
-    
-    def __ne__(self, other):
-        if hasattr(other, "__getitem__") and len(other) == 2:
-            return self.x != other[0] or self.y != other[1]
-        else:
-            return True
- 
-    def __nonzero__(self):
-        return self.x or self.y
- 
-    # Generic operator handlers
-    def _o2(self, other, f):
-        "Any two-operator operation where the left operand is a Vec2d"
-        if isinstance(other, Vec2d):
-            return Vec2d(f(self.x, other.x),
-                         f(self.y, other.y))
-        elif (hasattr(other, "__getitem__")):
-            return Vec2d(f(self.x, other[0]),
-                         f(self.y, other[1]))
-        else:
-            return Vec2d(f(self.x, other),
-                         f(self.y, other))
- 
-    def _r_o2(self, other, f):
-        "Any two-operator operation where the right operand is a Vec2d"
-        if (hasattr(other, "__getitem__")):
-            return Vec2d(f(other[0], self.x),
-                         f(other[1], self.y))
-        else:
-            return Vec2d(f(other, self.x),
-                         f(other, self.y))
- 
-    def _io(self, other, f):
-        "inplace operator"
-        if (hasattr(other, "__getitem__")):
-            self.x = f(self.x, other[0])
-            self.y = f(self.y, other[1])
-        else:
-            self.x = f(self.x, other)
-            self.y = f(self.y, other)
-        return self
- 
-    # Addition
-    def __add__(self, other):
-        if isinstance(other, Vec2d):
-            return Vec2d(self.x + other.x, self.y + other.y)
-        elif hasattr(other, "__getitem__"):
-            return Vec2d(self.x + other[0], self.y + other[1])
-        else:
-            return Vec2d(self.x + other, self.y + other)
-    __radd__ = __add__
-    
-    def __iadd__(self, other):
-        if isinstance(other, Vec2d):
-            self.x += other.x
-            self.y += other.y
-        elif hasattr(other, "__getitem__"):
-            self.x += other[0]
-            self.y += other[1]
-        else:
-            self.x += other
-            self.y += other
-        return self
- 
-    # Subtraction
-    def __sub__(self, other):
-        if isinstance(other, Vec2d):
-            return Vec2d(self.x - other.x, self.y - other.y)
-        elif (hasattr(other, "__getitem__")):
-            return Vec2d(self.x - other[0], self.y - other[1])
-        else:
-            return Vec2d(self.x - other, self.y - other)
-    def __rsub__(self, other):
-        if isinstance(other, Vec2d):
-            return Vec2d(other.x - self.x, other.y - self.y)
-        if (hasattr(other, "__getitem__")):
-            return Vec2d(other[0] - self.x, other[1] - self.y)
-        else:
-            return Vec2d(other - self.x, other - self.y)
-    def __isub__(self, other):
-        if isinstance(other, Vec2d):
-            self.x -= other.x
-            self.y -= other.y
-        elif (hasattr(other, "__getitem__")):
-            self.x -= other[0]
-            self.y -= other[1]
-        else:
-            self.x -= other
-            self.y -= other
-        return self
- 
-    # Multiplication
-    def __mul__(self, other):
-        if isinstance(other, Vec2d):
-            return Vec2d(self.x*other.y, self.y*other.y)
-        if (hasattr(other, "__getitem__")):
-            return Vec2d(self.x*other[0], self.y*other[1])
-        else:
-            return Vec2d(self.x*other, self.y*other)
-    __rmul__ = __mul__
-    
-    def __imul__(self, other):
-        if isinstance(other, Vec2d):
-            self.x *= other.x
-            self.y *= other.y
-        elif (hasattr(other, "__getitem__")):
-            self.x *= other[0]
-            self.y *= other[1]
-        else:
-            self.x *= other
-            self.y *= other
-        return self
- 
-    # Division
-    def __div__(self, other):
-        return self._o2(other, operator.div)
-    def __rdiv__(self, other):
-        return self._r_o2(other, operator.div)
-    def __idiv__(self, other):
-        return self._io(other, operator.div)
- 
-    def __floordiv__(self, other):
-        return self._o2(other, operator.floordiv)
-    def __rfloordiv__(self, other):
-        return self._r_o2(other, operator.floordiv)
-    def __ifloordiv__(self, other):
-        return self._io(other, operator.floordiv)
- 
-    def __truediv__(self, other):
-        return self._o2(other, operator.truediv)
-    def __rtruediv__(self, other):
-        return self._r_o2(other, operator.truediv)
-    def __itruediv__(self, other):
-        return self._io(other, operator.floordiv)
- 
-    # Modulo
-    def __mod__(self, other):
-        return self._o2(other, operator.mod)
-    def __rmod__(self, other):
-        return self._r_o2(other, operator.mod)
- 
-    def __divmod__(self, other):
-        return self._o2(other, divmod)
-    def __rdivmod__(self, other):
-        return self._r_o2(other, divmod)
- 
-    # Exponentation
-    def __pow__(self, other):
-        return self._o2(other, operator.pow)
-    def __rpow__(self, other):
-        return self._r_o2(other, operator.pow)
- 
-    # Bitwise operators
-    def __lshift__(self, other):
-        return self._o2(other, operator.lshift)
-    def __rlshift__(self, other):
-        return self._r_o2(other, operator.lshift)
- 
-    def __rshift__(self, other):
-        return self._o2(other, operator.rshift)
-    def __rrshift__(self, other):
-        return self._r_o2(other, operator.rshift)
- 
-    def __and__(self, other):
-        return self._o2(other, operator.and_)
-    __rand__ = __and__
- 
-    def __or__(self, other):
-        return self._o2(other, operator.or_)
-    __ror__ = __or__
- 
-    def __xor__(self, other):
-        return self._o2(other, operator.xor)
-    __rxor__ = __xor__
- 
-    # Unary operations
-    def __neg__(self):
-        return Vec2d(operator.neg(self.x), operator.neg(self.y))
- 
-    def __pos__(self):
-        return Vec2d(operator.pos(self.x), operator.pos(self.y))
- 
-    def __abs__(self):
-        return Vec2d(abs(self.x), abs(self.y))
- 
-    def __invert__(self):
-        return Vec2d(-self.x, -self.y)
- 
-    # vectory functions
-    def get_length_sqrd(self): 
-        """Get the squared length of the vector.
-        It is more efficent to use this method instead of first call 
-        get_length() or access .length and then do a sqrt().
-        
-        :return: The squared length
-        """
-        return self.x**2 + self.y**2
- 
-    def get_length(self):
-        """Get the length of the vector.
-        
-        :return: The length
-        """
-        return math.sqrt(self.x**2 + self.y**2)    
-    def __setlength(self, value):
-        length = self.get_length()
-        self.x *= value/length
-        self.y *= value/length
-    length = property(get_length, __setlength, doc = """Gets or sets the magnitude of the vector""")
-       
-    def rotate(self, angle_degrees):
-        """Rotate the vector by angle_degrees degrees clockwise."""
-        radians = -math.radians(angle_degrees)
-        cos = math.cos(radians)
-        sin = math.sin(radians)
-        x = self.x*cos - self.y*sin
-        y = self.x*sin + self.y*cos
-        self.x = x
-        self.y = y
- 
-    def rotated(self, angle_degrees):
-        """Create and return a new vector by rotating this vector by 
-        angle_degrees degrees clockwise.
-        
-        :return: Rotated vector
-        """
-        radians = -math.radians(angle_degrees)
-        cos = math.cos(radians)
-        sin = math.sin(radians)
-        x = self.x*cos - self.y*sin
-        y = self.x*sin + self.y*cos
-        return Vec2d(x, y)
-    
-    def get_angle(self):
-        if (self.get_length_sqrd() == 0):
-            return 0
-        return math.degrees(math.atan2(self.y, self.x))
-    def __setangle(self, angle_degrees):
-        self.x = self.length
-        self.y = 0
-        self.rotate(angle_degrees)
-    angle = property(get_angle, __setangle, doc="""Gets or sets the angle of a vector""")
- 
-    def get_angle_between(self, other):
-        """Get the angle between the vector and the other in degrees
-        
-        :return: The angle
-        """
-        cross = self.x*other[1] - self.y*other[0]
-        dot = self.x*other[0] + self.y*other[1]
-        return math.degrees(math.atan2(cross, dot))
-            
-    def normalized(self):
-        """Get a normalized copy of the vector
-        
-        :return: A normalized vector
-        """
-        length = self.length
-        if length != 0:
-            return self/length
-        return Vec2d(self)
- 
-    def normalize_return_length(self):
-        """Normalize the vector and return its length before the normalization
-        
-        :return: The length before the normalization
-        """
-        length = self.length
-        if length != 0:
-            self.x /= length
-            self.y /= length
-        return length
- 
-    def perpendicular(self):
-        return Vec2d(-self.y, self.x)
-    
-    def perpendicular_normal(self):
-        length = self.length
-        if length != 0:
-            return Vec2d(-self.y/length, self.x/length)
-        return Vec2d(self)
-        
-    def dot(self, other):
-        """The dot product between the vector and other vector
-            v1.dot(v2) -> v1.x*v2.x + v1.y*v2.y
-            
-        :return: The dot product
-        """
-        return float(self.x*other[0] + self.y*other[1])
-        
-    def get_distance(self, other):
-        """The distance between the vector and other vector
-        
-        :return: The distance
-        """
-        return math.sqrt((self.x - other[0])**2 + (self.y - other[1])**2)
-        
-    def get_dist_sqrd(self, other):
-        """The squared distance between the vector and other vector
-        It is more efficent to use this method than to call get_distance()
-        first and then do a sqrt() on the result.
-        
-        :return: The squared distance
-        """
-        return (self.x - other[0])**2 + (self.y - other[1])**2
-        
-    def projection(self, other):
-        other_length_sqrd = other[0]*other[0] + other[1]*other[1]
-        projected_length_times_other_length = self.dot(other)
-        return other*(projected_length_times_other_length/other_length_sqrd)
-    
-    def cross(self, other):
-        """The cross product between the vector and other vector
-            v1.cross(v2) -> v1.x*v2.y - v2.y-v1.x
-        
-        :return: The cross product
-        """
-        return self.x*other[1] - self.y*other[0]
-    
-    def interpolate_to(self, other, range):
-        return Vec2d(self.x + (other[0] - self.x)*range, self.y + (other[1] - self.y)*range)
-    
-    def convert_to_basis(self, x_vector, y_vector):
-        return Vec2d(self.dot(x_vector)/x_vector.get_length_sqrd(), self.dot(y_vector)/y_vector.get_length_sqrd())
- 
-    # Extra functions, mainly for chipmunk
-    def cpvrotate(self, other):
-        return Vec2d(self.x*other.x - self.y*other.y, self.x*other.y + self.y*other.x)
-    def cpvunrotate(self, other):
-        return Vec2d(self.x*other.x + self.y*other.y, self.y*other.x - self.x*other.y)
-    
-    # Pickle, does not work atm.
-    def __getstate__(self):
-        return [self.x, self.y]
-        
-    def __setstate__(self, dict):
-        self.x, self.y = dict
-    def __newobj__(cls, *args):
-        return cls.__new__(cls, *args)    
-Vec2d._fields_ = [
-            ('x', ctypes.c_double),
-            ('y', ctypes.c_double),
-        ]
-
-
-class Vec2dArray(list):
-
-	def __init__(self, iterable=()):
-		list.__init__(self, (Vec2d(i) for i in iterable))
-
-	def __setitem__(self, index, value):
-		list.__setitem__(self, index, Vec2d(value))
-	
-	def append(self, value):
-		"""Append a vector to the array"""
-		list.append(self, Vec2d(value))
-	
-	def insert(self, index, value):
-		"""Insert a vector into the array"""
-		list.insert(self, index, Vec2d(value))
-	
-	def transform(self, offset=Vec2d(0,0), angle=0, scale=1.0):
-		"""Return a new transformed Vec2dArray"""
-		offset = Vec2d(offset)
-		angle = math.radians(-angle)
-		rot_vec = Vec2d(math.cos(angle), math.sin(angle))
-		xformed = Vec2dArray()
-		for vec in self:
-			xformed.append(vec.cpvrotate(rot_vec) * scale + offset)
-		return xformed
-	
-	def segments(self, closed=True):
-		"""Generate arrays of line segments connecting adjacent vetices
-		in this array, exploding the shape into it's constituent segments
-		"""
-		if len(self) >= 2:
-			last = self[0]
-			for vert in self[1:]:
-				yield Vec2dArray((last, vert))
-				last = vert
-			if closed:
-				yield Vec2dArray((last, self[0]))
-		elif self and closed:
-			yield Vec2dArray((self[0], self[0]))
-
-
-
-class Rect(ctypes.Structure):
-	"""Simple rectangle. Will gain more functionality as needed"""
-	_fields_ = [
-		('left', ctypes.c_double),
-		('top', ctypes.c_double),
-		('right', ctypes.c_double),
-		('bottom', ctypes.c_double),
-	]
-
-	def __init__(self, rect_or_left, bottom=None, right=None, top=None):
-		if bottom is not None:
-			assert right is not None and top is not None, "No enough arguments to Rect"
-			self.left = rect_or_left
-			self.bottom = bottom
-			self.right = right
-			self.top = top
-		else:
-			self.left = rect_or_left.left
-			self.bottom = rect_or_left.bottom
-			self.right = rect_or_left.right
-			self.top = rect_or_left.top
-
-	@property
-	def width(self):
-		"""Rectangle width"""
-		return self.right - self.left
-	
-	@property
-	def height(self):
-		"""Rectangle height"""
-		return self.top - self.bottom
-
-
-########################################################################
-## Unit Testing                                                       ##
-########################################################################
-if __name__ == "__main__":
- 
-    import unittest
-    import pickle
- 
-    ####################################################################
-    class UnitTestVec2d(unittest.TestCase):
-    
-        def setUp(self):
-            pass
-        
-        def testCreationAndAccess(self):
-            v = Vec2d(111, 222)
-            self.assert_(v.x == 111 and v.y == 222)
-            v.x = 333
-            v[1] = 444
-            self.assert_(v[0] == 333 and v[1] == 444)
- 
-        def testMath(self):
-            v = Vec2d(111,222)
-            self.assertEqual(v + 1, Vec2d(112, 223))
-            self.assert_(v - 2 == [109, 220])
-            self.assert_(v * 3 == (333, 666))
-            self.assert_(v / 2.0 == Vec2d(55.5, 111))
-            #self.assert_(v / 2 == (55, 111)) # Not supported since this is a c_float structure in the bottom
-            self.assert_(v ** Vec2d(2, 3) == [12321, 10941048])
-            self.assert_(v + [-11, 78] == Vec2d(100, 300))
-            #self.assert_(v / [11,2] == [10,111]) # Not supported since this is a c_float structure in the bottom
- 
-        def testReverseMath(self):
-            v = Vec2d(111, 222)
-            self.assert_(1 + v == Vec2d(112, 223))
-            self.assert_(2 - v == [-109, -220])
-            self.assert_(3 * v == (333, 666))
-            #self.assert_([222,999] / v == [2,4]) # Not supported since this is a c_float structure in the bottom
-            self.assert_([111, 222] ** Vec2d(2, 3) == [12321, 10941048])
-            self.assert_([-11, 78] + v == Vec2d(100, 300))
- 
-        def testUnary(self):
-            v = Vec2d(111, 222)
-            v = -v
-            self.assert_(v == [-111, -222])
-            v = abs(v)
-            self.assert_(v == [111, 222])
- 
-        def testLength(self):
-            v = Vec2d(3,4)
-            self.assert_(v.length == 5)
-            self.assert_(v.get_length_sqrd() == 25)
-            self.assert_(v.normalize_return_length() == 5)
-            self.assertAlmostEquals(v.length, 1)
-            v.length = 5
-            self.assert_(v == Vec2d(3, 4))
-            v2 = Vec2d(10, -2)
-            self.assert_(v.get_distance(v2) == (v - v2).get_length())
-            
-        def testAngles(self):            
-            v = Vec2d(0, 3)
-            self.assertEquals(v.angle, 90)
-            v2 = Vec2d(v)
-            v.rotate(-90)
-            self.assertEqual(v.get_angle_between(v2), 90)
-            v2.angle -= 90
-            self.assertEqual(v.length, v2.length)
-            self.assertEquals(v2.angle, 0)
-            self.assertEqual(v2, [3, 0])
-            self.assert_((v - v2).length < .00001)
-            self.assertEqual(v.length, v2.length)
-            v2.rotate(300)
-            self.assertAlmostEquals(v.get_angle_between(v2), -60, 5) # Allow a little more error than usual (floats..)
-            v2.rotate(v2.get_angle_between(v))
-            angle = v.get_angle_between(v2)
-            self.assertAlmostEquals(v.get_angle_between(v2), 0)  
- 
-        def testHighLevel(self):
-            basis0 = Vec2d(5.0, 0)
-            basis1 = Vec2d(0, .5)
-            v = Vec2d(10, 1)
-            self.assert_(v.convert_to_basis(basis0, basis1) == [2, 2])
-            self.assert_(v.projection(basis0) == (10, 0))
-            self.assert_(basis0.dot(basis1) == 0)
-            
-        def testCross(self):
-            lhs = Vec2d(1, .5)
-            rhs = Vec2d(4, 6)
-            self.assert_(lhs.cross(rhs) == 4)
-            
-        def testComparison(self):
-            int_vec = Vec2d(3, -2)
-            flt_vec = Vec2d(3.0, -2.0)
-            zero_vec = Vec2d(0, 0)
-            self.assert_(int_vec == flt_vec)
-            self.assert_(int_vec != zero_vec)
-            self.assert_((flt_vec == zero_vec) == False)
-            self.assert_((flt_vec != int_vec) == False)
-            self.assert_(int_vec == (3, -2))
-            self.assert_(int_vec != [0, 0])
-            self.assert_(int_vec != 5)
-            self.assert_(int_vec != [3, -2, -5])
-        
-        def testInplace(self):
-            inplace_vec = Vec2d(5, 13)
-            inplace_ref = inplace_vec
-            inplace_src = Vec2d(inplace_vec)    
-            inplace_vec *= .5
-            inplace_vec += .5
-            inplace_vec /= (3, 6)
-            inplace_vec += Vec2d(-1, -1)
-            alternate = (inplace_src*.5 + .5)/Vec2d(3, 6) + [-1, -1]
-            self.assertEquals(inplace_vec, inplace_ref)
-            self.assertEquals(inplace_vec, alternate)
-        
-        def testPickle(self):
-            return # pickling does not work atm
-            testvec = Vec2d(5, .3)
-            testvec_str = pickle.dumps(testvec)
-            loaded_vec = pickle.loads(testvec_str)
-            self.assertEquals(testvec, loaded_vec)
-    
-    ####################################################################
-    unittest.main()
- 
--- a/src/parpg/bGrease/impl/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-
-__versioninfo__ = (0, 3, 0)
-__version__ = '.'.join(str(n) for n in __versioninfo__)
-
-__all__ = ('Mode', 'World')
-
-from mode import Mode
-from world import World
-
-
--- a/src/parpg/bGrease/impl/controls.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-"""Control systems for binding controls to game logic"""
-
-import bGrease
-from pyglet.window import key
-
-class KeyControls(grease.System):
-	"""System that maps subclass-defined action methods to keys. 
-
-	Keys may be mapped in the subclass definition using decorators
-	defined here as class methods or at runtime using the ``bind_key_*`` 
-	instance methods.
-
-	See :ref:`an example implementation in the tutorial <tut-controls-example>`.
-	"""
-	MODIFIER_MASK = ~(key.MOD_NUMLOCK | key.MOD_SCROLLLOCK | key.MOD_CAPSLOCK)
-	"""The MODIFIER_MASK allows you to filter out modifier keys that should be
-	ignored by the application. By default, capslock, numlock, and scrolllock 
-	are ignored.
-	"""
-
-	world = None
-	""":class:`grease.World` object this system is bound to"""
-
-	def __init__(self):
-		self._key_press_map = {}
-		self._key_release_map = {}
-		self._key_hold_map = {}
-		for name in self.__class__.__dict__:
-			member = getattr(self, name)
-			if hasattr(member, '_grease_hold_key_binding'):
-				for binding in member._grease_hold_key_binding:
-					self.bind_key_hold(member, *binding)
-			if hasattr(member, '_grease_press_key_binding'):
-				for binding in member._grease_press_key_binding:
-					self.bind_key_press(member, *binding)
-			if hasattr(member, '_grease_release_key_binding'):
-				for binding in member._grease_release_key_binding:
-					self.bind_key_release(member, *binding)
-		self.held_keys = set()
-
-	## decorator methods for binding methods to key input events ##
-
-	@classmethod
-	def key_hold(cls, symbol, modifiers=0):
-		"""Decorator to bind a method to be executed where a key is held down"""
-		def bind(f):
-			if not hasattr(f, '_grease_hold_key_binding'):
-				f._grease_hold_key_binding = []
-			f._grease_hold_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK))
-			return f
-		return bind
-
-	@classmethod
-	def key_press(cls, symbol, modifiers=0):
-		"""Decorator to bind a method to be executed where a key is initially depressed"""
-		def bind(f):
-			if not hasattr(f, '_grease_press_key_binding'):
-				f._grease_press_key_binding = []
-			f._grease_press_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK))
-			return f
-		return bind
-
-	@classmethod
-	def key_release(cls, symbol, modifiers=0):
-		"""Decorator to bind a method to be executed where a key is released"""
-		def bind(f):
-			if not hasattr(f, '_grease_release_key_binding'):
-				f._grease_release_key_binding = []
-			f._grease_release_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK))
-			return f
-		return bind
-	
-	## runtime binding methods ##
-	
-	def bind_key_hold(self, method, key, modifiers=0):
-		"""Bind a method to a key at runtime to be invoked when the key is
-		held down, this replaces any existing key hold binding for this key.
-		To unbind the key entirely, pass ``None`` for method.
-		"""
-		if method is not None:
-			self._key_hold_map[key, modifiers & self.MODIFIER_MASK] = method
-		else:
-			try:
-				del self._key_hold_map[key, modifiers & self.MODIFIER_MASK]
-			except KeyError:
-				pass
-
-	def bind_key_press(self, method, key, modifiers=0):
-		"""Bind a method to a key at runtime to be invoked when the key is initially
-		pressed, this replaces any existing key hold binding for this key. To unbind
-		the key entirely, pass ``None`` for method.
-		"""
-		if method is not None:
-			self._key_press_map[key, modifiers & self.MODIFIER_MASK] = method
-		else:
-			try:
-				del self._key_press_map[key, modifiers & self.MODIFIER_MASK]
-			except KeyError:
-				pass
-
-	def bind_key_release(self, method, key, modifiers=0):
-		"""Bind a method to a key at runtime to be invoked when the key is releaseed,
-		this replaces any existing key hold binding for this key. To unbind
-		the key entirely, pass ``None`` for method.
-		"""
-		if method is not None:
-			self._key_release_map[key, modifiers & self.MODIFIER_MASK] = method
-		else:
-			try:
-				del self._key_release_map[key, modifiers & self.MODIFIER_MASK]
-			except KeyError:
-				pass
-
-	def step(self, dt):
-		"""invoke held key functions"""
-		already_run = set()
-		for key in self.held_keys:
-			func = self._key_hold_map.get(key)
-			if func is not None and func not in already_run:
-				already_run.add(func)
-				func(dt)
-
-	def on_key_press(self, key, modifiers):
-		"""Handle pyglet key press. Invoke key press methods and
-		activate key hold functions
-		"""
-		key_mod = (key, modifiers & self.MODIFIER_MASK)
-		if key_mod in self._key_press_map:
-			self._key_press_map[key_mod]()
-		self.held_keys.add(key_mod)
-	
-	def on_key_release(self, key, modifiers):
-		"""Handle pyglet key release. Invoke key release methods and
-		deactivate key hold functions
-		"""
-		key_mod = (key, modifiers & self.MODIFIER_MASK)
-		if key_mod in self._key_release_map:
-			self._key_release_map[key_mod]()
-		self.held_keys.discard(key_mod)
-
-
-if __name__ == '__main__':
-	import pyglet
-
-	class TestKeyControls(KeyControls):
-		
-		MODIFIER_MASK = ~(key.MOD_NUMLOCK | key.MOD_SCROLLLOCK | key.MOD_CTRL)
-
-		remapped = False
-		
-		@KeyControls.key_hold(key.UP)
-		@KeyControls.key_hold(key.W)
-		def up(self, dt):
-			print 'UP!'
-		
-		@KeyControls.key_hold(key.LEFT)
-		@KeyControls.key_hold(key.A)
-		def left(self, dt):
-			print 'LEFT!'
-		
-		@KeyControls.key_hold(key.RIGHT)
-		@KeyControls.key_hold(key.D)
-		def right(self, dt):
-			print 'RIGHT!'
-		
-		@KeyControls.key_hold(key.DOWN)
-		@KeyControls.key_hold(key.S)
-		def down(self, dt):
-			print 'DOWN!'
-
-		@KeyControls.key_press(key.SPACE)
-		def fire(self):
-			print 'FIRE!'
-
-		@KeyControls.key_press(key.R)
-		def remap_keys(self):
-			if not self.remapped:
-				self.bind_key_hold(None, key.W)
-				self.bind_key_hold(None, key.A)
-				self.bind_key_hold(None, key.S)
-				self.bind_key_hold(None, key.D)
-				self.bind_key_hold(self.up, key.I)
-				self.bind_key_hold(self.left, key.J)
-				self.bind_key_hold(self.right, key.L)
-				self.bind_key_hold(self.down, key.K)
-			else:
-				self.bind_key_hold(None, key.I)
-				self.bind_key_hold(None, key.J)
-				self.bind_key_hold(None, key.K)
-				self.bind_key_hold(None, key.L)
-				self.bind_key_hold(self.up, key.W)
-				self.bind_key_hold(self.left, key.A)
-				self.bind_key_hold(self.right, key.D)
-				self.bind_key_hold(self.down, key.S)
-			self.remapped = not self.remapped
-			
-
-	window = pyglet.window.Window()
-	window.clear()
-	controls = TestKeyControls()
-	window.push_handlers(controls)
-	pyglet.clock.schedule_interval(controls.step, 0.5)
-	pyglet.app.run()
-
--- a/src/parpg/bGrease/impl/mode.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-"""
-Modes manage the state and transition between different application modes.
-Typically such modes are presented as different screens that the user can
-navigate between, similar to the way a browser navigates web pages. Individual
-modes may be things like:
-
-- Title screen
-- Options dialog
-- About screen
-- In-progress game
-- Inventory interface
-
-The modal framework provides a simple mechanism to ensure that modes are
-activated and deactivated properly. An activated mode is running and receives
-events. A deactivated mode is paused and does not receive events.
-
-Modes may be managed as a *last-in-first-out* stack, or as a list, or ring
-of modes in sequence, or some combination of all.
-
-For example usage see: :ref:`the mode section of the tutorial <tut-mode-section>`.
-"""
-
-__version__ = '$Id$'
-
-import abc
-import pyglet
-from parpg.bGrease.mode import *
-
-class PygletManager(BaseManager):
-        """Mode manager abstract base class using pyglet.
-
-        The mode manager keeps a stack of modes where a single mode
-        is active at one time. As modes are pushed on and popped from 
-        the stack, the mode at the top is always active. The current
-        active mode receives events from the manager's event dispatcher.
-        """
-
-        event_dispatcher = None
-        """:class:`pyglet.event.EventDispatcher` object that the
-	active mode receive events from.
-	"""
-
-        def activate_mode(self, mode):
-                """Perform actions to activate a node
-
-                :param mode: The :class: 'Mode' object to activate
-                """
-                BaseManager.activate_mode(self, mode)
-                self.event_dispatcher.push_handlers(mode)
-
-        def deactivate_mode(self, mode):
-                """Perform actions to deactivate a node
-
-                :param mode: The :class: 'Mode' object to deactivate
-                """
-                BaseManager.deactivate_mode(self, mode)
-                self.event_dispatcher.remove_handlers(mode)
-
-class Manager(PygletManager):
-        """A basic mode manager that wraps a single
-        :class:`pyglet.event.EventDispatcher` object for use by its modes.
-        """
-
-        def __init__(self, event_dispatcher):
-                self.modes = []
-                self.event_dispatcher = event_dispatcher
-
-
-class ManagerWindow(PygletManager, pyglet.window.Window):
-        """An integrated mode manager and pyglet window for convenience.
-        The window is the event dispatcher used by modes pushed to
-        this manager.
-
-        Constructor arguments are identical to :class:`pyglet.window.Window`
-        """
-
-        def __init__(self, *args, **kw):
-                super(ManagerWindow, self).__init__(*args, **kw)
-                self.modes = []
-                self.event_dispatcher = self
-
-        def on_key_press(self, symbol, modifiers):
-                """Default :meth:`on_key_press handler`, pops the current mode on ``ESC``"""
-                if symbol == pyglet.window.key.ESCAPE:
-                        self.pop_mode()
-
-        def on_last_mode_pop(self, mode):
-                """Hook executed when the last mode is popped from the manager.
-                When the last mode is popped from a window, an :meth:`on_close` event
-                is dispatched.
-
-                :param mode: The :class:`Mode` object just popped from the manager
-                """
-                self.dispatch_event('on_close')
-
-
-class Mode(BaseMode):
-        """Application mode abstract base class using pyglet
-
-        Subclasses must implement the :meth:`step` method
-
-        :param step_rate: The rate of :meth:`step()` calls per second. 
-
-        :param master_clock: The :class:`pyglet.clock.Clock` interface used
-        	as the master clock that ticks the world's clock. This 
-        	defaults to the main pyglet clock.
-        """
-        clock = None
-        """The :class:`pyglet.clock.Clock` instance used as this mode's clock.
-	You should use this clock to schedule tasks for this mode, so they
-	properly respect when the mode is active or inactive
-
-	Example::
-
-		my_mode.clock.schedule_once(my_cool_function, 4)
-	"""
-
-        def __init__(self, step_rate=60, master_clock=pyglet.clock, 
-                     clock_factory=pyglet.clock.Clock):
-                BaseMode.__init__(self)
-                self.step_rate = step_rate
-                self.time = 0.0
-                self.master_clock = master_clock
-                self.clock = clock_factory(time_function=lambda: self.time)
-                self.clock.schedule_interval(self.step, 1.0 / step_rate)
-
-        def on_activate(self):
-                """Being called when the Mode is activated"""
-                self.master_clock.schedule(self.tick)
-
-        def on_deactivate(self):
-                """Being called when the Mode is deactivated"""
-                self.master_clock.unschedule(self.tick)
-
-        def tick(self, dt):
-                """Tick the mode's clock.
-
-                :param dt: The time delta since the last tick
-                :type dt: float
-                """
-                self.time += dt
-                self.clock.tick(poll=False)
-
-        @abc.abstractmethod
-        def step(self, dt):
-                """Execute a timestep for this mode. Must be defined by subclasses.
-
-                :param dt: The time delta since the last time step
-                :type dt: float
-                """
-
-class Multi(BaseMulti, Mode):
-        """A mode with multiple submodes. One submode is active at one time.
-        Submodes can be switched to directly or switched in sequence. If
-        the Multi is active, then one submode is always active.
-
-        Multis are useful when modes can switch in an order other than
-        a LIFO stack, such as in "hotseat" multiplayer games, a
-        "wizard" style ui, or a sequence of slides.
-
-        Note unlike a normal :class:`Mode`, a :class:`Multi` doesn't have it's own
-        :attr:`clock` and :attr:`step_rate`. The active submode's are used
-        instead.
-        """
-
-        def __init__(self, submodes):
-                BaseMulti.__init__(self, submodes)
-                self.time = 0.0
-
-
-        def _set_active_submode(self, submode):
-                BaseMulti._set_active_submode(self, submode)
-                self.master_clock = submode.master_clock
-                self.clock = submode.clock
-
-        def clear_subnode(self):
-                """Clear any subnmode data"""
-                BaseMulti.clear_subnode(self)
-                self.master_clock = None
-                self.clock = None
-
-        def tick(self, dt):
-                """Tick the active submode's clock.
-
-                :param dt: The time delta since the last tick
-                :type dt: float
-                """
-                self.time += dt
-                if self.active_submode is not None:
-                        self.active_submode.clock.tick(poll=False)
--- a/src/parpg/bGrease/impl/world.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-"""Worlds are environments described by a configuration of components, systems and 
-renderers. These parts describe the data, behavioral and presentation aspects
-of the world respectively.
-
-The world environment is the context within which entities exist. A typical
-application consists of one or more worlds containing entities that evolve
-over time and react to internal and external interaction.
-
-See :ref:`an example of world configuration in the tutorial <tut-world-example>`.
-"""
-
-__version__ = '$Id$'
-
-import itertools
-import pyglet
-from pyglet import gl
-from parpg.bGrease.world import *
-from parpg.bGrease.impl import Mode
-
-class World(Mode, BaseWorld):
-	"""A coordinated collection of components, systems and entities
-	
-	A world is also a mode that may be pushed onto a 
-	:class:`grease.mode.Manager`
-
-	:param step_rate: The rate of :meth:`step()` calls per second. 
-
-	:param master_clock: The :class:`pyglet.clock.Clock` interface used
-		as the master clock that ticks the world's clock. This 
-		defaults to the main pyglet clock.
-	"""
-
-	clock = None
-	""":class:`pyglet.clock` interface for use by constituents
-	of the world for scheduling
-	"""
-
-	time = None
-	"""Current clock time of the world, starts at 0 when the world
-	is instantiated
-	"""
-
-	running = True
-	"""Flag to indicate that the world clock is running, advancing time
-	and stepping the world. Set running to False to pause the world.
-	"""
-
-	def __init__(self, step_rate=60, master_clock=pyglet.clock,
-				 clock_factory=pyglet.clock.Clock):
-		Mode.__init__(self, step_rate, master_clock, clock_factory)
-		BaseWorld.__init__(self)
-	
-	def activate(self, manager):
-		"""Activate the world/mode for the given manager, if the world is already active, 
-		do nothing. This method is typically not used directly, it is called
-		automatically by the mode manager when the world becomes active.
-
-		The systems of the world are pushed onto `manager.event_dispatcher`
-		so they can receive system events.
-
-		:param manager: :class:`mode.BaseManager` instance
-		"""
-		if not self.active:
-			for system in self.systems:
-				manager.event_dispatcher.push_handlers(system)
-		super(World, self).activate(manager)
-	
-	def deactivate(self, manager):
-		"""Deactivate the world/mode, if the world is not active, do nothing.
-		This method is typically not used directly, it is called
-		automatically by the mode manager when the world becomes active.
-
-		Removes the system handlers from the `manager.event_dispatcher`
-
-		:param manager: :class:`mode.BaseManager` instance
-		"""
-		for system in self.systems:
-			manager.event_dispatcher.remove_handlers(system)
-		super(World, self).deactivate(manager)
-
-	def tick(self, dt):
-		"""Tick the mode's clock, but only if the world is currently running
-		
-		:param dt: The time delta since the last tick
-		:type dt: float
-		"""
-		if self.running:
-			super(World, self).tick(dt)
-	
-	def step(self, dt):
-		"""Execute a time step for the world. Updates the world `time`
-		and invokes the world's systems.
-		
-		Note that the specified time delta will be pinned to 10x the
-		configured step rate. For example if the step rate is 60,
-		then dt will be pinned at a maximum of 0.1666. This avoids 
-		pathological behavior when the time between steps goes
-		much longer than expected.
-
-		:param dt: The time delta since the last time step
-		:type dt: float
-		"""
-		dt = min(dt, 10.0 / self.step_rate)
-		for component in self.components:
-			if hasattr(component, "step"):
-				component.step(dt)
-		for system in self.systems:
-			if hasattr(system, "step"):
-				system.step(dt)
-
-	def on_draw(self, gl=pyglet.gl):
-		"""Clear the current OpenGL context, reset the model/view matrix and
-		invoke the `draw()` methods of the renderers in order
-		"""
-		gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
-		gl.glLoadIdentity()
-		BaseWorld.draw_renderers(self)
\ No newline at end of file
--- a/src/parpg/bGrease/mode.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,391 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-"""
-Modes manage the state and transition between different application modes.
-Typically such modes are presented as different screens that the user can
-navigate between, similar to the way a browser navigates web pages. Individual
-modes may be things like:
-
-- Title screen
-- Options dialog
-- About screen
-- In-progress game
-- Inventory interface
-
-The modal framework provides a simple mechanism to ensure that modes are
-activated and deactivated properly. An activated mode is running and receives
-events. A deactivated mode is paused and does not receive events.
-
-Modes may be managed as a *last-in-first-out* stack, or as a list, or ring
-of modes in sequence, or some combination of all.
-
-For example usage see: :ref:`the mode section of the tutorial <tut-mode-section>`.
-"""
-
-__version__ = '$Id$'
-
-import abc
-
-
-class BaseManager(object):
-	"""Mode manager abstract base class.
-	
-	The mode manager keeps a stack of modes where a single mode
-	is active at one time. As modes are pushed on and popped from 
-	the stack, the mode at the top is always active. The current
-	active mode receives events from the manager's event dispatcher.
-	"""
-
-	modes = ()
-	"""The mode stack sequence. The last mode in the stack is
-	the current active mode. Read-only.
-	"""
-
-	@property
-	def current_mode(self):
-		"""The current active mode or ``None``. Read-only"""
-		try:
-			return self.modes[-1]
-		except IndexError:
-			return None
-	
-	def on_last_mode_pop(self, mode):
-		"""Hook executed when the last mode is popped from the manager.
-		Implementing this method is optional for subclasses.
-
-		:param mode: The :class:`Mode` object just popped from the manager
-		"""
-	
-	def activate_mode(self, mode):
-		"""Perform actions to activate a node
-		
-		:param mode: The :class: 'Mode' object to activate
-		"""
-		mode.activate(self)
-
-	def deactivate_mode(self, mode):
-		"""Perform actions to deactivate a node
-		
-		:param mode: The :class: 'Mode' object to deactivate
-		"""
-		mode.deactivate(self)
-
-		
-	def push_mode(self, mode):
-		"""Push a mode to the top of the mode stack and make it active
-		
-		:param mode: The :class:`Mode` object to make active
-		"""
-		current = self.current_mode
-		if current is not None:
-			self.deactivate_mode(current)
-		self.modes.append(mode)
-		self.activate_mode(mode)
-	
-	def pop_mode(self):
-		"""Pop the current mode off the top of the stack and deactivate it.
-		The mode now at the top of the stack, if any is then activated.
-
-		:param mode: The :class:`Mode` object popped from the stack
-		"""
-		mode = self.modes.pop()
-		mode.deactivate(self)
-		current = self.current_mode
-		if current is not None:
-			self.activate_mode(current)
-		else:
-			self.on_last_mode_pop(mode)
-		return mode
-	
-	def swap_modes(self, mode):
-		"""Exchange the specified mode with the mode at the top of the stack.
-		This is similar to popping the current mode and pushing the specified
-		one, but without activating the previous mode on the stack or
-		executing :meth:`on_last_mode_pop()` if there is no previous mode.
-
-		:param mode: The :class:`Mode` object that was deactivated and replaced.
-		"""
-		old_mode = self.modes.pop()
-		self.deactivate_mode(old_mode)
-		self.modes.append(mode)
-		self.activate_mode(mode)
-		return old_mode
-	
-	def remove_mode(self, mode):
-		"""Remove the specified mode. If the mode is at the top of the stack,
-		this is equivilent to :meth:`pop_mode()`. If not, no other modes
-		are affected. If the mode is not in the manager, do nothing.
-
-		:param mode: The :class:`Mode` object to remove from the manager.
-		"""
-		if self.current_mode is mode:
-			self.pop_mode()
-		else:
-			try:
-				self.modes.remove(mode)
-			except ValueError:
-				pass
-
-class BaseMode(object):
-	"""Application mode very abstract base class
-	"""
-	__metaclass__ = abc.ABCMeta
-
-	manager = None
-	"""The :class:`BaseManager` that manages this mode"""
-
-	def __init__(self):
-		self.active = False
-		
-	def on_activate(self):
-		"""Being called when the Mode is activated"""
-		pass
-	
-	def activate(self, mode_manager):
-		"""Activate the mode for the given mode manager, if the mode is already active, 
-		do nothing
-
-		The default implementation schedules time steps at :attr:`step_rate` per
-		second, sets the :attr:`manager` and sets the :attr:`active` flag to True.
-		"""
-		if not self.active:
-			self.on_activate()
-			self.manager = mode_manager
-			self.active = True
-
-	def on_deactivate(self):
-		"""Being called when the Mode is deactivated"""
-		pass
-
-	def deactivate(self, mode_manager):
-		"""Deactivate the mode, if the mode is not active, do nothing
-
-		The default implementation unschedules time steps for the mode and
-		sets the :attr:`active` flag to False.
-		"""
-		self.on_deactivate()
-		self.active = False
-
-
-class BaseMulti(BaseMode):
-	"""A mode with multiple submodes. One submode is active at one time.
-	Submodes can be switched to directly or switched in sequence. If
-	the Multi is active, then one submode is always active.
-
-	Multis are useful when modes can switch in an order other than
-	a LIFO stack, such as in "hotseat" multiplayer games, a
-	"wizard" style ui, or a sequence of slides.
-
-	Note unlike a normal :class:`Mode`, a :class:`Multi` doesn't have it's own
-	:attr:`clock` and :attr:`step_rate`. The active submode's are used
-	instead.
-	"""
-	active_submode = None
-	"""The currently active submode"""
-
-	def __init__(self, *submodes):
-		# We do not invoke the superclass __init__ intentionally
-		self.active = False
-		self.submodes = list(submodes)
-	
-	def add_submode(self, mode, before=None, index=None):
-		"""Add the submode, but do not make it active.
-
-		:param mode: The :class:`Mode` object to add.
-
-		:param before: The existing mode to insert the mode before. 
-			If the mode specified is not a submode, raise
-			ValueError.
-
-		:param index: The place to insert the mode in the mode list.
-			Only one of ``before`` or ``index`` may be specified.
-
-			If neither ``before`` or ``index`` are specified, the
-			mode is appended to the end of the list.
-		"""
-		assert before is None or index is None, (
-			"Cannot specify both 'before' and 'index' arguments")
-		if before is not None:
-			index = self.submodes.index(mode)
-		if index is not None:
-			self.submodes.insert(index, mode)
-		else:
-			self.submodes.append(mode)
-	
-	def remove_submode(self, mode=None):
-		"""Remove the submode.
-
-		:param mode: The submode to remove, if omitted the active submode
-			is removed. If the mode is not present, do nothing.  If the
-			mode is active, it is deactivated, and the next mode, if any
-			is activated. If the last mode is removed, the :class:`Multi`
-			is removed from its manager. 
-		"""
-		# TODO handle multiple instances of the same subnode
-		if mode is None:
-			mode = self.active_submode
-		elif mode not in self.submodes:
-			return
-		next_mode = self.activate_next()
-		self.submodes.remove(mode)
-		if next_mode is mode:
-			if self.manager is not None:
-				self.manager.remove_mode(self)
-			self._deactivate_submode()
-				
-	def activate_subnode(self, mode, before=None, index=None):
-		"""Activate the specified mode, adding it as a subnode
-		if it is not already. If the mode is already the active
-		submode, do nothing.
-
-		:param mode: The mode to activate, and add as necesary.
-
-		:param before: The existing mode to insert the mode before
-			if it is not already a submode.  If the mode specified is not
-			a submode, raise ValueError.
-
-		:param index: The place to insert the mode in the mode list
-			if it is not already a submode.  Only one of ``before`` or
-			``index`` may be specified.
-
-			If the mode is already a submode, the ``before`` and ``index``
-			arguments are ignored.
-		"""
-		if mode not in self.submodes:
-			self.add_submode(mode, before, index)
-		if self.active_submode is not mode:
-			self._activate_submode(mode)
-	
-	def activate_next(self, loop=True):
-		"""Activate the submode after the current submode in order.  If there
-		is no current submode, the first submode is activated.
-
-		Note if there is only one submode, it's active, and `loop` is True
-		(the default), then this method does nothing and the subnode remains
-		active.
-
-		:param loop: When :meth:`activate_next` is called 
-			when the last submode is active, a True value for ``loop`` will
-			cause the first submode to be activated.  Otherwise the
-			:class:`Multi` is removed from its manager.
-		:type loop: bool
-
-		:return:
-			The submode that was activated or None if there is no
-			other submode to activate.
-		"""
-		assert self.submodes, "No submode to activate"
-		next_mode = None
-		if self.active_submode is None:
-			next_mode = self.submodes[0]
-		else:
-			last_mode = self.active_submode
-			index = self.submodes.index(last_mode) + 1
-			if index < len(self.submodes):
-				next_mode = self.submodes[index]
-			elif loop:
-				next_mode = self.submodes[0]
-		self._activate_submode(next_mode)
-		return next_mode
-
-	def activate_previous(self, loop=True):
-		"""Activate the submode before the current submode in order.  If there
-		is no current submode, the last submode is activated.
-
-		Note if there is only one submode, it's active, and `loop` is True
-		(the default), then this method does nothing and the subnode remains
-		active.
-		
-		:param loop: When :meth:`activate_previous` is called 
-			when the first submode is active, a True value for ``loop`` will
-			cause the last submode to be activated.  Otherwise the
-			:class:`Multi` is removed from its manager.
-		:type loop: bool
-
-		:return:
-			The submode that was activated or None if there is no
-			other submode to activate.
-		"""
-		assert self.submodes, "No submode to activate"
-		prev_mode = None
-		if self.active_submode is None:
-			prev_mode = self.submodes[-1]
-		else:
-			last_mode = self.active_submode
-			index = self.submodes.index(last_mode) - 1
-			if loop or index >= 0:
-				prev_mode = self.submodes[index]
-		self._activate_submode(prev_mode)
-		return prev_mode
-	
-	def _set_active_submode(self, submode):
-		self.active_submode = submode
-		self.step_rate = submode.step_rate
-
-	def _activate_submode(self, submode):
-		"""Activate a submode deactivating any current submode. If the Multi
-		itself is active, this happens immediately, otherwise the actual
-		activation is deferred until the Multi is activated. If the submode
-		is None, the Mulitmode is removed from its manager.
-
-		If submode is already the active submode, do nothing.
-		"""
-		if self.active_submode is submode:
-			return
-		assert submode in self.submodes, "Unknown submode"
-		self._deactivate_submode()
-		self._set_active_submode(submode)
-		if submode is not None:
-			if self.active:
-				self.manager.activate_mode(submode)
-		else:
-			if self.manager is not None:
-				self.manager.remove_mode(self)
-	
-	def clear_subnode(self):
-		"""Clear any subnmode data"""
-		self.active_submode = None
-		self.step_rate = None
-				
-	def _deactivate_submode(self, clear_subnode=True):
-		"""Deactivate the current submode, if any. if `clear_subnode` is
-		True, `active_submode` is always None when this method returns
-		"""
-		if self.active_submode is not None:
-			if self.active:
-				self.manager.deactivate_mode(self.active_submode)
-			if clear_subnode:
-				self.clear_subnode()
-	
-	def activate(self, mode_manager):
-		"""Activate the :class:`Multi` for the specified manager. The
-		previously active submode of the :class:`Multi` is activated. If there
-		is no previously active submode, then the first submode is made active. 
-		A :class:`Multi` with no submodes cannot be activated
-		"""
-		assert self.submodes, "No submode to activate"
-		self.manager = mode_manager
-		if self.active_submode is None:
-			self._set_active_submode(self.submodes[0])
-		else:
-			self._set_active_submode(self.active_submode)
-		self.manager.activate_mode(self.active_submode)
-		super(BaseMulti, self).activate(mode_manager)
-	
-	def deactivate(self, mode_manager):
-		"""Deactivate the :class:`Multi` for the specified manager.
-		The `active_submode`, if any, is deactivated.
-		"""
-		self._deactivate_submode(clear_subnode=False)
-		super(BaseMulti, self).deactivate(mode_manager)
-
--- a/src/parpg/bGrease/renderer/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-"""Renderers define world presentation. This module contains the
-built-in renderer classes.
-
-See also:
-
-- :class:`~grease.Renderer` abstract base class.
-- :ref:`Example renderer class in the tutorial <tut-renderer-example>`
-"""
-
-__all__ = ('Vector', 'Camera')
-
-from parpg.bGrease.renderer.vector import Vector
-from parpg.bGrease.renderer.camera import Camera
--- a/src/parpg/bGrease/renderer/camera.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-import pyglet
-
-class Camera(object):
-	"""Sets the point of view for further renderers by altering the
-	model/view matrix when it is drawn. It does not actually perform
-	any drawing itself.
-
-	:param position: The position vector for the camera. Sets the center of the view.
-	:type position: Vec2d
-	:param angle: Camera rotation in degrees about the z-axis.
-	:type angle: float
-	:param zoom: Scaling vector for the coordinate axis.
-	:type zoom: Vec2d
-	:param relative: Flag to indicate if the camera settings are relative 
-		to the previous view state. If ``False`` the view state is reset before 
-		setting the camera view by loading the identity model/view matrix.
-	
-	At runtime the camera may be manipulated via attributes with the 
-	same names and functions as the parameters above.
-	"""
-
-	def __init__(self, position=None, angle=None, zoom=None, relative=False):
-		self.position = position
-		self.angle = angle
-		self.zoom = zoom
-		self.relative = relative
-	
-	def draw(self, gl=pyglet.gl):
-		if not self.relative:
-			gl.glLoadIdentity()
-		if self.position is not None:
-			px, py = self.position
-			gl.glTranslatef(px, py, 0)
-		if self.angle is not None:
-			gl.glRotatef(self.angle, 0, 0, 1)
-		if self.zoom is not None:
-			sx, sy = self.zoom
-			gl.glScalef(sx, sy ,0)
-
--- a/src/parpg/bGrease/renderer/vector.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-
-__version__ = '$Id$'
-
-__all__ = ('Vector',)
-
-from parpg.bGrease.geometry import Vec2d
-import ctypes
-from math import sin, cos, radians
-import pyglet
-
-
-class Vector(object):
-        """Renders shapes in a classic vector graphics style
-
-        :param scale: Scaling factor applied to shape vertices when rendered.
-
-        :param line_width: The line width provided to ``glLineWidth`` before rendering.
-        	If not specified or None, ``glLineWidth`` is not called, and the line
-        	width used is determined by the OpenGL state at the time of rendering.
-
-        :param anti_alias: If ``True``, OpenGL blending and line smoothing is enabled.
-        	This allows for fractional line widths as well. If ``False``, the blending
-        	and line smoothing modes are unchanged.
-
-        :param corner_fill: If true (the default), the shape corners will be filled
-        	with round points when the ``line_width`` exceeds 2.0. This improves
-        	the visual quality of the rendering at larger line widths at some
-        	cost to performance. Has no effect if ``line_width`` is not specified.
-
-        :param position_component: Name of :class:`grease.component.Position` 
-        	component to use. Shapes rendered are offset by the entity positions.
-
-        :param renderable_component: Name of :class:`grease.component.Renderable` 
-        	component to use. This component specifies the entities to be 
-        	rendered and their base color.
-
-        :param shape_component: Name of :class:`grease.component.Shape` 
-        	component to use. Source of the shape vertices for each entity.
-
-        The entities rendered are taken from the intersection of he position,
-        renderable and shape components each time :meth:`draw` is called.
-        """
-
-        CORNER_FILL_SCALE = 0.6
-        CORNER_FILL_THRESHOLD = 2.0
-
-        def __init__(self, scale=1.0, line_width=None, anti_alias=True, corner_fill=True,
-                     position_component='position', 
-                     renderable_component='renderable', 
-                     shape_component='shape'):
-                self.scale = float(scale)
-                self.corner_fill = corner_fill
-                self.line_width = line_width
-                self.anti_alias = anti_alias
-                self._max_line_width = None
-                self.position_component = position_component
-                self.renderable_component = renderable_component
-                self.shape_component = shape_component
-
-        def set_world(self, world):
-                self.world = world
-
-        def _generate_verts(self):
-                """Generate vertex and index arrays for rendering"""
-                vert_count = sum(len(shape.verts) + 1
-                                 for shape, ignored, ignored in self.world.components.join(
-                                         self.shape_component, self.position_component, self.renderable_component))
-                v_array = (CVertColor * vert_count)()
-                if vert_count > 65536:
-                        i_array = (ctypes.c_uint * 2 * vert_count)()
-                        i_size = pyglet.gl.GL_UNSIGNED_INT
-                else:
-                        i_array = (ctypes.c_ushort * (2 * vert_count))()
-                        i_size = pyglet.gl.GL_UNSIGNED_SHORT
-                v_index = 0
-                i_index = 0
-                scale = self.scale
-                rot_vec = Vec2d(0, 0)
-                for shape, position, renderable in self.world.components.join(
-                        self.shape_component, self.position_component, self.renderable_component):
-                        shape_start = v_index
-                        angle = radians(-position.angle)
-                        rot_vec.x = cos(angle)
-                        rot_vec.y = sin(angle)
-                        r = int(renderable.color.r * 255)
-                        g = int(renderable.color.g * 255)
-                        b = int(renderable.color.b * 255)
-                        a = int(renderable.color.a * 255)
-                        for vert in shape.verts:
-                                vert = vert.cpvrotate(rot_vec) * scale + position.position
-                                v_array[v_index].vert.x = vert.x
-                                v_array[v_index].vert.y = vert.y
-                                v_array[v_index].color.r = r
-                                v_array[v_index].color.g = g
-                                v_array[v_index].color.b = b
-                                v_array[v_index].color.a = a
-                                if v_index > shape_start:
-                                        i_array[i_index] = v_index - 1
-                                        i_index += 1
-                                        i_array[i_index] = v_index
-                                        i_index += 1
-                                v_index += 1
-                        if shape.closed and v_index - shape_start > 2:
-                                i_array[i_index] = v_index - 1
-                                i_index += 1
-                                i_array[i_index] = shape_start
-                                i_index += 1
-                return v_array, i_size, i_array, i_index
-
-        def draw(self, gl=pyglet.gl):
-                vertices, index_size, indices, index_count = self._generate_verts()
-                if index_count:
-                        if self.anti_alias:
-                                gl.glEnable(gl.GL_LINE_SMOOTH)
-                                gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST)
-                                gl.glEnable(gl.GL_BLEND)
-                                gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
-                        gl.glPushClientAttrib(gl.GL_CLIENT_VERTEX_ARRAY_BIT)
-                        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
-                        gl.glEnableClientState(gl.GL_COLOR_ARRAY)
-                        gl.glVertexPointer(
-                                2, gl.GL_FLOAT, ctypes.sizeof(CVertColor), ctypes.pointer(vertices))
-                        gl.glColorPointer(
-                                4, gl.GL_UNSIGNED_BYTE, ctypes.sizeof(CVertColor), 
-                                ctypes.pointer(vertices[0].color))
-                        if self.line_width is not None:
-                                gl.glLineWidth(self.line_width)
-                                if self._max_line_width is None:
-                                        range_out = (ctypes.c_float * 2)()
-                                        gl.glGetFloatv(gl.GL_ALIASED_LINE_WIDTH_RANGE, range_out)
-                                        self._max_line_width = float(range_out[1]) * self.CORNER_FILL_SCALE
-                                if self.corner_fill and self.line_width > self.CORNER_FILL_THRESHOLD:
-                                        gl.glEnable(gl.GL_POINT_SMOOTH)
-                                        gl.glPointSize(
-                                                min(self.line_width * self.CORNER_FILL_SCALE, self._max_line_width))
-                                        gl.glDrawArrays(gl.GL_POINTS, 0, index_count)
-                        gl.glDrawElements(gl.GL_LINES, index_count, index_size, ctypes.pointer(indices))
-                        gl.glPopClientAttrib()
-
-
-class CVert(ctypes.Structure):
-        _fields_ = [("x", ctypes.c_float), ("y", ctypes.c_float)]
-
-class CColor(ctypes.Structure):
-        _fields_ = [
-                ("r", ctypes.c_ubyte), 
-                ("g", ctypes.c_ubyte), 
-                ("b", ctypes.c_ubyte), 
-                ("a", ctypes.c_ubyte),
-        ]
-
-class CVertColor(ctypes.Structure):
-        _fields_ = [("vert", CVert), ("color", CColor)]
--- a/src/parpg/bGrease/world.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,301 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-#
-#############################################################################
-"""Worlds are environments described by a configuration of components, systems and 
-renderers. These parts describe the data, behavioral and presentation aspects
-of the world respectively.
-
-The world environment is the context within which entities exist. A typical
-application consists of one or more worlds containing entities that evolve
-over time and react to internal and external interaction.
-
-See :ref:`an example of world configuration in the tutorial <tut-world-example>`.
-"""
-
-__version__ = '$Id$'
-
-import itertools
-from parpg.bGrease import mode
-from parpg.bGrease.component import ComponentError
-from parpg.bGrease.entity import Entity, ComponentEntitySet
-
-
-class BaseWorld(object):
-        """A coordinated collection of components, systems and entities
-
-        A world is also a mode that may be pushed onto a 
-        :class:`grease.mode.Manager`
-        """
-
-        components = None
-        """:class:`ComponentParts` object containing all world components.
-	:class:`grease.component.Component` objects define and contain all entity data
-	"""
-
-        systems = None
-        """:class:`Parts` object containing all world systems. 
-	:class:`grease.System` objects define world and entity behavior
-	"""
-
-        renderers = None
-        """:class:`Parts` object containing all world renderers. 
-	:class:`grease.Renderer` objects define world presentation
-	"""
-
-        entities = None
-        """Set of all entities that exist in the world"""
-
-        def __init__(self):
-                self.components = ComponentParts(self)
-                self.systems = Parts(self)
-                self.renderers = Parts(self)
-                self.new_entity_id = itertools.count().next
-                self.new_entity_id() # skip id 0
-                self.entities = WorldEntitySet(self)
-                self._full_extent = EntityExtent(self, self.entities)
-                self._extents = {}
-                self.configure()
-
-        def configure(self):
-                """Hook to configure the world after construction. This method
-                is called immediately after the world is initialized. Override
-                in a subclass to configure the world's components, systems,
-                and renderers.
-
-                The default implementation does nothing.
-                """
-
-        def __getitem__(self, entity_class):
-                """Return an :class:`EntityExtent` for the given entity class. This extent
-                can be used to access the set of entities of that class in the world
-                or to query these entities via their components. 
-
-                Examples::
-
-                	world[MyEntity]
-                	world[...]
-
-                :param entity_class: The entity class for the extent.
-
-                	May also be a tuple of entity classes, in which case
-                	the extent returned contains union of all entities of the classes
-                	in the world.
-
-                	May also be the special value ellipsis (``...``), which
-                	returns an extent containing all entities in the world.  This allows
-                	you to conveniently query all entities using ``world[...]``.
-                """
-                if isinstance(entity_class, tuple):
-                        entities = set()
-                        for cls in entity_class:
-                                if cls in self._extents:
-                                        entities |= self._extents[cls].entities
-                        return EntityExtent(self, entities)
-                elif entity_class is Ellipsis:
-                        return self._full_extent
-                try:
-                        return self._extents[entity_class]
-                except KeyError:
-                        extent = self._extents[entity_class] = EntityExtent(self, set())
-                        return extent
-
-        def draw_renderers(self):
-                """Draw all renderers"""
-                for renderer in self.renderers:
-                        renderer.draw()
-
-class WorldEntitySet(set):
-        """Entity set for a :class:`World`"""
-
-        def __init__(self, world):
-                self.world = world
-
-        def add(self, entity):
-                """Add the entity to the set and all necessary class sets
-                Return the unique entity id for the entity, creating one
-                as needed.
-                """
-                super(WorldEntitySet, self).add(entity)
-                for cls in entity.__class__.__mro__:
-                        if issubclass(cls, Entity):
-                                self.world[cls].entities.add(entity)
-
-        def remove(self, entity):
-                """Remove the entity from the set and, world components,
-                and all necessary class sets
-                """
-                super(WorldEntitySet, self).remove(entity)
-                for component in self.world.components:
-                        try:
-                                del component[entity]
-                        except KeyError:
-                                pass
-                for cls in entity.__class__.__mro__:
-                        if issubclass(cls, Entity):
-                                self.world[cls].entities.discard(entity)
-
-        def discard(self, entity):
-                """Remove the entity from the set if it exists, if not,
-                do nothing
-                """
-                try:
-                        self.remove(entity)
-                except KeyError:
-                        pass
-
-
-class EntityExtent(object):
-        """Encapsulates a set of entities queriable by component. Extents
-        are accessed by using an entity class as a key on the :class:`World`::
-
-        	extent = world[MyEntity]
-        """
-
-        entities = None
-        """The full set of entities in the extent""" 
-
-        def __init__(self, world, entities):
-                self.__world = world
-                self.entities = entities
-
-        def __getattr__(self, name):
-                """Return a queriable :class:`ComponentEntitySet` for the named component 
-
-                Example::
-
-                	world[MyEntity].movement.velocity > (0, 0)
-
-                Returns a set of entities where the value of the :attr:`velocity` field
-                of the :attr:`movement` component is greater than ``(0, 0)``.
-                """
-                component = getattr(self.__world.components, name)
-                return ComponentEntitySet(component, self.entities & component.entities)
-
-
-class Parts(object):
-        """Maps world parts to attributes. The parts are kept in the
-        order they are set. Parts may also be inserted out of order.
-
-        Used for:
-
-        - :attr:`World.systems`
-        - :attr:`World.renderers`
-        """
-
-        _world = None
-        _parts = None
-        _reserved_names = ('entities', 'entity_id', 'world')
-
-        def __init__(self, world):
-                self._world = world
-                self._parts = []
-
-        def _validate_name(self, name):
-                if (name in self._reserved_names or name.startswith('_') 
-                    or hasattr(self.__class__, name)):
-                        raise ComponentError('illegal part name: %s' % name)
-                return name
-
-        def __setattr__(self, name, part):
-                if not hasattr(self.__class__, name):
-                        self._validate_name(name)
-                        if not hasattr(self, name):
-                                self._parts.append(part)
-                        else:
-                                old_part = getattr(self, name)
-                                self._parts[self._parts.index(old_part)] = part
-                        super(Parts, self).__setattr__(name, part)
-                        if hasattr(part, 'set_world'):
-                                part.set_world(self._world)
-                elif name.startswith("_"):
-                        super(Parts, self).__setattr__(name, part)
-                else:
-                        raise AttributeError("%s attribute is read only" % name)
-
-        def __delattr__(self, name):
-                self._validate_name(name)
-                part = getattr(self, name)
-                self._parts.remove(part)
-                super(Parts, self).__delattr__(name)
-
-        def insert(self, name, part, before=None, index=None):
-                """Add a part with a particular name at a particular index.
-                If a part by that name already exists, it is replaced.
-
-                :arg name: The name of the part.
-                :type name: str
-
-                :arg part: The component, system, or renderer part to insert
-
-                :arg before: A part object or name. If specified, the part is
-                	inserted before the specified part in order.
-
-                :arg index: If specified, the part is inserted in the position
-                	specified. You cannot specify both before and index.
-                :type index: int
-                """
-                assert before is not None or index is not None, (
-                        "Must specify a value for 'before' or 'index'")
-                assert before is None or index is None, (
-                        "Cannot specify both 'before' and 'index' arguments when inserting")
-                self._validate_name(name)
-                if before is not None:
-                        if isinstance(before, str):
-                                before = getattr(self, before)
-                        index = self._parts.index(before)
-                if hasattr(self, name):
-                        old_part = getattr(self, name)
-                        self._parts.remove(old_part)
-                self._parts.insert(index, part)
-                super(Parts, self).__setattr__(name, part)
-                if hasattr(part, 'set_world'):
-                        part.set_world(self._world)
-
-        def __iter__(self):
-                """Iterate the parts in order"""
-                return iter(tuple(self._parts))
-
-        def __len__(self):
-                return len(self._parts)
-
-
-class ComponentParts(Parts):
-        """Maps world components to attributes. The components are kept in the
-        order they are set. Components may also be inserted out of order.
-
-        Used for: :attr:`World.components`
-        """
-
-        def join(self, *component_names):
-                """Join and iterate entity data from multiple components together.
-
-                For each entity in all of the components named, yield a tuple containing
-                the entity data from each component specified.
-
-                This is useful in systems that pull data from multiple components.
-
-                Typical Usage::
-
-                	for position, movement in world.components.join("position", "movement"):
-                		# Do something with each entity's position and movement data
-                """
-                if component_names:
-                        components = [getattr(self, self._validate_name(name)) 
-                                      for name in component_names]
-                        if len(components) > 1:
-                                entities = components[0].entities & components[1].entities
-                                for comp in components[2:]:
-                                        entities &= comp.entities
-                        else:
-                                entities = components[0].entities
-                        for entity in entities:
-                                yield tuple(comp[entity] for comp in components)
--- a/src/parpg/behaviours/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +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 <http://www.gnu.org/licenses/>.
-
-from base import BaseBehaviour as Base
-from moving import MovingAgentBehaviour as Moving
-from npc import NPCBehaviour as NonPlayer
-from player import PlayerBehaviour as Player
\ No newline at end of file
--- a/src/parpg/behaviours/base.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +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 <http://www.gnu.org/licenses/>.
-
-from collections import deque
-
-from fife import fife
-
-_AGENT_STATE_NONE, _AGENT_STATE_IDLE, _AGENT_STATE_APPROACH, _AGENT_STATE_RUN, _AGENT_STATE_WANDER, _AGENT_STATE_TALK = xrange(6)
-
-class BaseBehaviour (fife.InstanceActionListener):
-    """Fife agent listener"""
-    def __init__(self):
-        fife.InstanceActionListener.__init__(self)
-        self.agent = None
-        self.state = None
-        self.animation_queue = deque()
-        self.nextAction = None 
-    
-    def attachToLayer(self, agent_ID, layer):
-        """Attaches to a certain layer
-           @type agent_ID: String
-           @param agent_ID: ID of the layer to attach to.
-           @type layer: Fife layer
-           @param layer: Layer of the agent to attach the behaviour to
-           @return: None"""
-        self.agent = 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.general.identifier)
-        self.agent.addActionListener(self)
-        self.state = _AGENT_STATE_NONE
-    
-    def idle(self):
-        """@return: None"""
-        self.state = _AGENT_STATE_IDLE        
-        
-    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()
-        try:
-            animtion = self.animation_queue.popleft()
-            self.animate(**animtion)
-        except IndexError:
-            self.idle()
-          
-    def onInstanceActionFrame(self, instance, action, frame):
-        pass
-         
-    def getLocation(self):
-        """Get the agents position as a fife.Location object. 
-           @rtype: fife.Location
-           @return: the location of the agent"""
-        return self.agent.getLocation()
-    
-        
-    def talk(self, pc):
-        """Makes the agent ready to talk to the PC
-           @return: None"""
-        self.state = _AGENT_STATE_TALK
-        self.pc = pc.behaviour.agent
-        self.clear_animations()
-        self.idle()
-        
-    def animate(self, action, direction = None, repeating = False):
-        """Perform an animation"""
-        direction = direction or self.agent.getFacingLocation()
-        self.agent.act(action, direction, repeating)
-        
-    def queue_animation(self, action, direction = None, repeating = False):
-        """Add an action to the queue"""
-        self.animation_queue.append({"action": action, "direction": direction,
-                                  "repeating": repeating})
-        
-    def clear_animations(self):
-        """Remove all actions from the queue"""
-        self.animation_queue.clear()
--- a/src/parpg/behaviours/moving.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +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 <http://www.gnu.org/licenses/>.
-
-from fife import fife
-import base
-from base import BaseBehaviour
-
-class MovingAgentBehaviour (BaseBehaviour):
-    """Fife agent listener"""
-    def __init__(self):
-        BaseBehaviour.__init__(self)
-        self.speed = 0
-        self.idle_counter = 1
-        
-    def onNewMap(self, layer):
-        """Sets the agent onto the new layer."""
-        BaseBehaviour.onNewMap(self, layer)
-        self.idle_counter = 1
-
-
-    def approach(self, location_or_agent, action=None):
-        """Approaches a location or another agent and then perform an action 
-        (if set).
-        @type loc: fife.Location
-        @param loc: the location or agent to approach
-        @type action: Action
-        @param action: The action to schedule for execution after the 
-        approach.
-        @return: None"""
-            
-        self.state = base._AGENT_STATE_APPROACH
-        self.nextAction = action
-        if  isinstance(location_or_agent, fife.Instance):
-            agent = location_or_agent
-            self.agent.follow('run', agent, self.speed + 1)
-        else:
-            location = location_or_agent
-            boxLocation = tuple([int(float(i)) for i in location])
-            l = fife.Location(self.getLocation())
-            l.setLayerCoordinates(fife.ModelCoordinate(*boxLocation))
-            self.agent.move('run', l, self.speed + 1)        
-        
-    def onInstanceActionFinished(self, instance, action):
-        """@type instance: ???
-        @param instance: ???
-        @type action: ???
-        @param action: ???
-        @return: None"""
-        BaseBehaviour.onInstanceActionFinished(self, instance, action)
-            
-        if(action.getId() != 'stand'):
-            self.idle_counter = 1
-        else:
-            self.idle_counter += 1 
-        
-    def idle(self):
-        """@return: None"""
-        BaseBehaviour.idle(self)
-        self.animate('stand')    
-        
-    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 = base._AGENT_STATE_RUN
-        self.clear_animations()
-        self.nextAction = None
-        self.agent.move('run', location, self.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 = base._AGENT_STATE_RUN
-        self.clear_animations()
-        self.nextAction = None
-        self.agent.move('walk', location, self.speed - 1)
-        
\ No newline at end of file
--- a/src/parpg/behaviours/npc.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +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 <http://www.gnu.org/licenses/>.
-
-from random import randrange
-
-from fife import fife
-
-import base
-from moving import MovingAgentBehaviour
-
-class NPCBehaviour(MovingAgentBehaviour):
-    """This is a basic NPC behaviour"""
-    def __init__(self, parent=None):
-        super(NPCBehaviour, self).__init__()
-        
-        self.parent = parent
-        self.state = base._AGENT_STATE_NONE
-        self.pc = None
-        self.target_loc = 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.
-        # HACK: 09.Oct.2011 Beliar
-        # I increased the wander rate to 900 since the idle method
-        # gets called way more often now.
-        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 == base._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
-           @type action: ???
-           @param action: ???
-           @return: None"""
-        if self.state == base._AGENT_STATE_WANDER:
-            self.target_loc = self.getTargetLocation()
-        MovingAgentBehaviour.onInstanceActionFinished(self, instance, action)
-        
-    
-    def idle(self):
-        """Controls the NPC when it is idling. Different actions
-           based on the NPC's state.
-           @return: None"""
-        if self.state == base._AGENT_STATE_NONE:
-            self.state = base._AGENT_STATE_IDLE
-            self.animate('stand')
-        elif self.state == base._AGENT_STATE_IDLE:
-            if self.wanderCounter > self.wanderRate:
-                self.wanderCounter = 0
-                self.state = base._AGENT_STATE_WANDER
-            else:
-                self.wanderCounter += 1
-                self.state = base._AGENT_STATE_NONE
-            
-            self.target_loc = self.getTargetLocation()
-            self.animate('stand')
-        elif self.state == base._AGENT_STATE_WANDER:
-            self.wander(self.target_loc)
-            self.state = base._AGENT_STATE_NONE
-        elif self.state == base._AGENT_STATE_TALK:
-            self.animate('stand', self.pc.getLocation())
-            
-    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.agent.move('walk', location, self.speed - 1)
\ No newline at end of file
--- a/src/parpg/behaviours/player.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +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 <http://www.gnu.org/licenses/>.
-
-import moving
-from moving import MovingAgentBehaviour
-
-class PlayerBehaviour (MovingAgentBehaviour):
-    def __init__(self, parent=None):
-        super(PlayerBehaviour, self).__init__()        
-        self.parent = parent
-        self.idle_counter = 1
-        self.speed = 0
-        self.agent = None
\ No newline at end of file
--- a/src/parpg/charactercreationcontroller.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,392 +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 <http://www.gnu.org/licenses/>.
-"""Provides the controller that defines the behaviour of the character creation
-   screen."""
-
-from parpg import vfs
-from controllerbase import ControllerBase
-from gamescenecontroller import GameSceneController
-from gamesceneview import GameSceneView
-from parpg.world import World
-from parpg.entities import General
-from parpg.components import character_statistics
-
-def getStatCost(offset):
-    """Gets and returns the cost to increase stat based on the offset"""
-
-    if offset < 0:
-        offset *= -1
-
-    if offset < 22:
-        return 1
-    elif offset < 29:
-        return 2
-    elif offset < 32:
-        return 3
-    elif offset < 35:
-        return 4
-    elif offset < 36:
-        return 5
-    elif offset < 38:
-        return 6
-    elif offset < 39:
-        return 7
-    elif offset < 40:
-        return 8
-    elif offset < 41:
-        return 9
-    else:
-        return 10    
-            
-class CharacterCreationController(ControllerBase, World):
-    """Controller defining the behaviour of the character creation screen."""
-    
-    #TODO: Change to actual values
-    MAX_TRAITS = 3
-    MIN_AGE = 16
-    MAX_AGE = 40
-    ORIGINS = {"None": None,}
-    GENDERS = ["Male", "Female",]
-    PICTURES = {"Male": ["None",], "Female": ["None",],}
-    TRAITS = {}
-    MAX_BULK = 100
-    INV_SLOTS = 20
-    
-    def __init__(self, engine, view, model, application):
-        """Construct a new L{CharacterCreationController} instance.
-           @param engine: Rendering engine used to display the associated view.
-           @type engine: L{fife.Engine}
-           @param view: View used to display the character creation screen.
-           @type view: L{ViewBase}
-           @param model: Model of the game state.
-           @type model: L{GameModel}
-           @param application: Application used to glue the various MVC
-               components together.
-           @type application: 
-               L{fife.extensions.basicapplication.ApplicationBase}"""
-        ControllerBase.__init__(self, engine, view, model, application)
-        World.__init__(self)
-        self.settings = self.model.settings
-        self.view.start_new_game_callback = self.startNewGame
-        self.view.cancel_new_game_callback = self.cancelNewGame
-
-    def reset_character(self):
-        inventory = []
-        for x in xrange(self.INV_SLOTS):
-            inventory.append(None)
-        self.char_data = General(self, "PlayerCharacter")
-        self.char_data.description.view_name = "Player"
-        self.char_data.description.real_name = "Enter name here"
-        self.char_data.characterstats.gender = self.GENDERS[0]
-        self.char_data.characterstats.origin = self.ORIGINS.keys()[0]
-        self.char_data.characterstats.age = 20
-        self.char_data.characterstats.picture = (
-            self.PICTURES[self.GENDERS[0]][0]
-        )
-        self.model.create_stats(self.char_data)
-        self.char_data.container.max_bulk = self.MAX_BULK
-        self.char_data.container.children = inventory
-        self._stat_points = 200 
-    
-    def update_agent(self):
-        """Updates the player agent data in the model"""
-        agent_data = (
-            self.model.agents[self.model.ALL_AGENTS_KEY]["PlayerCharacter"]
-        )
-        agent_data["Statistics"] = (
-            character_statistics.get_stat_values(
-                self.char_data.characterstats
-            )["primary"]
-        )
-        
-    def startNewGame(self):
-        """Create the new character and start a new game.
-           @return: None"""
-        self.update_agent()
-        view = GameSceneView(self.engine, self.model)
-        controller = GameSceneController(self.engine, view, self.model,
-                                         self.application)
-        self.application.view = view
-        self.application.manager.swap_modes(controller)
-        start_map = self.settings.parpg.Map
-        self.model.changeMap(start_map)
-    
-    def cancelNewGame(self):
-        """Exit the character creation view and return the to main menu.
-           @return: None"""
-        # KLUDGE Technomage 2010-12-24: This is to prevent a circular import
-        #     but a better fix needs to be thought up.
-        from mainmenucontroller import MainMenuController
-        from mainmenuview import MainMenuView
-        view = MainMenuView(self.engine, self.model)
-        controller = MainMenuController(self.engine, view, self.model,
-                                        self.application)
-        self.application.view = view
-        self.application.manager.activate_mode(controller)
-    
-    def on_activate(self):
-        self.reset_character()
-        self.view.show()
-    
-    def on_deactivate(self):
-        """Called when the controller is removed from the list.
-           @return: None"""
-        self.view.hide()
-        
-    @property
-    def name(self):
-        """Returns the name of the character.
-        @return: Name of the character"""
-        return self.char_data.description.real_name
-    
-    @property
-    def age(self):
-        """Returns the age of the character.
-        @return: Age of the character"""
-        return self.char_data.characterstats.age
-    
-    @property
-    def gender(self):
-        """Returns the gender of the character.
-        @return: Gender of the character"""
-        return self.char_data.characterstats.gender
-    
-    @property
-    def origin(self):
-        """Returns the origin of the character.
-        @return: Origin of the character"""
-        return self.char_data.characterstats.origin
-    
-    @property
-    def picture(self):
-        """Returns the ID of the current picture of the character."""
-        return self.char_data.characterstats.picture
-    
-    def getStatPoints(self):
-        """Returns the remaining statistic points that can be distributed"""
-        return self._stat_points
-    
-    def increaseStatistic(self, statistic):
-        """Increases the given statistic by one.
-        @param statistic: Name of the statistic to increase
-        @type statistic: string""" 
-        if self.canIncreaseStatistic(statistic):
-            cost = self.getStatisticIncreaseCost(statistic)
-            if  cost <= self._stat_points:
-                (self.char_data.characterstats.
-                 primary_stats[statistic].value) += 1
-                self._stat_points -= cost  
-
-    def getStatisticIncreaseCost(self, statistic):
-        """Calculate and return the cost to increase the statistic
-        @param statistic: Name of the statistic to increase
-        @type statistic: string
-        @return cost to increase the statistic"""
-        cur_value = (self.char_data.characterstats.
-                     primary_stats[statistic].value)
-        new_value = cur_value + 1
-        offset =  new_value - DEFAULT_STAT_VALUE
-        return getStatCost(offset)
-    
-    def canIncreaseStatistic(self, statistic):
-        """Checks whether the given statistic can be increased or not.
-        @param statistic: Name of the statistic to check
-        @type statistic: string
-        @return: True if the statistic can be increased, False if not."""
-        stat = self.char_data.characterstats.primary_stats[statistic].value
-        return stat < stat.statistic_type.maximum
-    
-    def decreaseStatistic(self, statistic):
-        """Decreases the given statistic by one.
-        @param statistic: Name of the statistic to decrease
-        @type statistic: string""" 
-        if self.canDecreaseStatistic(statistic):
-            gain = self.getStatisticDecreaseGain(statistic)
-            self.char_data.characterstats.primary_stats[statistic].value -= 1
-            self._stat_points += gain  
-
-    def getStatisticDecreaseGain(self, statistic):
-        """Calculate and return the gain of decreasing the statistic
-        @param statistic: Name of the statistic to decrease
-        @type statistic: string
-        @return cost to decrease the statistic"""
-        cur_value = (self.char_data.characterstats.
-                     primary_stats[statistic].value)
-        new_value = cur_value - 1
-        offset =  new_value - DEFAULT_STAT_VALUE
-        return getStatCost(offset)
-    
-    def canDecreaseStatistic(self, statistic):
-        """Checks whether the given statistic can be decreased or not.
-        @param statistic: Name of the statistic to check
-        @type statistic: string
-        @return: True if the statistic can be decreased, False if not."""
-        stat = self.char_data.characterstats.primary_stats[statistic].value
-        return stat > stat.statistic_type.minimum
-    
-    def getStatisticValue(self, statistic):
-        """Returns the value of the given statistic.
-        @param statistic: Name of the primary or secondary statistic
-        @type statistic: string
-        @return: Value of the given statistic"""
-        if self.char_data.characterstats.primary_stats.has_key:
-            return self.char_data.characterstats.primary_stats[statistic]
-        else:
-            return self.char_data.characterstats.secondary_stats[statistic]
-    
-    def areAllStatisticsValid(self):
-        """Checks if all statistics are inside the minimum/maximum values
-        @return True if all statistics are valid False if not"""
-        all_stats = self.char_data.characterstats.primary_stats.items()
-        all_stats.extend(self.char_data.characterstats.secondary_stats.items())
-        for stat in all_stats:
-            if not (stat.value > stat.statistic_type.minumum and\
-                stat.value < stat.statistic_type.maximum):
-                return False
-        return True
-    
-    def setName(self, name):
-        """Sets the name of the character to the given value.
-        @param name: New name
-        @type name: string"""
-        self.char_data.description.real_name = name
-    
-    def isNameValid(self, name):
-        """Checks whether the name is valid.
-        @param name: Name to check
-        @type name: string
-        @return: True if the name is valid, False if not"""
-        if name:
-            return True
-        return False
-    
-    def changeOrigin(self, origin):
-        """Changes the origin of the character to the given value.
-        @param origin: New origin
-        @type origin: string"""
-        if self.isOriginValid(origin):
-            self.char_data.characterstats.origin = origin
-            #TODO: Make changes according to origin
-   
-    def isOriginValid(self, origin):
-        """Checks whether the origin is valid.
-        @param origin: Origin to check
-        @type origin: string
-        @return: True if the origin is valid, False if not"""
-        return origin in self.ORIGINS
-    
-    def changeGender(self, gender):
-        """Changes the gender of the character to the given value.
-        @param gender: New gender
-        @param gender: string"""
-        if self.isGenderValid(gender):
-            self.char_data.characterstats.gender = gender
-    
-    def isGenderValid(self, gender):
-        """Checks whether the gender is valid.
-        @param gender: Gender to check
-        @type gender: string?
-        @return: True if the origin is valid, False if not"""        
-        return gender in self.GENDERS
-    
-    def changeAge(self, age):
-        """Sets the age of the character to the given value.
-        @param age: New age
-        @type age: integer
-        """
-        if self.isAgeValid(age):
-            self.char_data.characterstats.age = age
-    
-    def isAgeValid(self, age):
-        """Checks whether the age is valid.
-        @param age: Age to check
-        @type age: integer
-        @return: True if the origin is valid, False if not"""
-        return age >= self.MIN_AGE and age <= self.MAX_AGE 
-    
-    def setPicture(self, picture):
-        """Set picture of the character.
-        @param picture: ID of the new picture
-        @type picture: string"""
-        if self.isPictureValid(picture):
-            self.char_data.characterstats.picture = picture
-    
-    def isPictureValid(self, picture):
-        """Checks whether the picture is valid.
-        @param picture: ID of the picture to check
-        @type picture: string
-        @return: True if the picture is valid, False if not"""
-        return picture in self.PICTURES[self.gender]
-    
-    def addTrait(self, trait):
-        """Adds a trait to the character.
-        @param trait: ID of the trait to add
-        @type trait: string"""
-        if self.canAddAnotherTrait() and self.isTraitValid(trait)\
-                and not self.hasTrait(trait):
-            self.char_data.characterstats.traits.append(trait)                
-    
-    def canAddAnotherTrait(self):
-        """Checks whether another trait can be added.
-        @return: True if another trait can be added, False if not"""
-        return len(self.char_data.characterstats.traits) < self.MAX_TRAITS
-    
-    def removeTrait(self, trait):
-        """Remove trait from character.
-        @param trait: ID of the trait to remove
-        @type trait: string"""
-        if self.hasTrait(trait):
-            self.char_data.characterstats.traits.remove(trait)
-    
-    def hasTrait(self, trait):
-        """Checks whether the character has the trait.
-        @param trait: ID of the trait to check
-        @type trait: string
-        @return: True if the character has the trait, False if not"""
-        return trait in self.char_data.characterstats.traits
-    
-    def isTraitValid(self, trait):
-        """Checks whether the trait is valid.
-        @param trait: ID of the trait to check
-        @type trait: string
-        @return: True if the trait is valid, False if not"""
-        return trait in self.TRAITS
-    
-    def areCurrentTraitsValid(self):
-        """Checks whether the characters traits are valid.
-        @return: True if the traits are valid, False if not"""
-        if len(self.char_data.characterstats.traits) > self.MAX_TRAITS:
-            return False 
-        for trait in self.char_data.characterstats.traits:
-            if not self.isTraitValid(trait):
-                return False
-        return True
-    
-    def isCharacterValid(self):
-        """Checks whether the character as a whole is valid.
-        @return: True if the character is valid, False if not"""
-        #Single checks can be disabled by putting a "#" in front of them
-        if True\
-        and self._stat_points >= 0\
-        and self.areAllStatisticsValid() \
-        and self.areCurrentTraitsValid() \
-        and self.isNameValid(self.name)\
-        and self.isPictureValid(self.picture)\
-        and self.isAgeValid(self.age)\
-        and self.isGenderValid(self.gender)\
-        and self.isOriginValid(self.origin)\
-        :
-            return True
-        return False
--- a/src/parpg/charactercreationview.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +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 <http://www.gnu.org/licenses/>.
-"""Provides the view for displaying the character creation screen."""
-
-from fife.extensions import pychan
-
-from parpg import vfs
-from viewbase import ViewBase
-
-class CharacterCreationView(ViewBase):
-    """View used to display the character creation screen.
-       @ivar background: Widget displayed as the background.
-       @type background: L{pychan.Widget}
-       @ivar start_new_game_callback: Callback attached to the startButton.
-       @type start_new_game_callback: callable
-       @ivar cancel_new_game_callback: Callback attached to the cancelButton.
-       @type cancel_new_game_callback: callable
-       @ivar character_screen: Widget used to display the character creation
-           screen.
-       @type character_screen: L{pychan.Widget}"""
-
-    def __init__(self, engine, model, settings):
-        """Construct a new L{CharacterCreationView} instance.
-           @param engine: Rendering engine used to display the view.
-           @type engine: L{fife.Engine}
-           @param model: Model of the game state.
-           @type model: L{GameState}"""
-        ViewBase.__init__(self, engine, model)
-        self.settings = settings
-        xml_file = vfs.VFS.open('gui/main_menu_background.xml')
-        self.background = pychan.loadXML(xml_file)
-        screen_mode = self.engine.getRenderBackend().getCurrentScreenMode()
-        self.background.width = screen_mode.getWidth()
-        self.background.height = screen_mode.getHeight()
-        self.start_new_game_callback = None
-        self.cancel_new_game_callback = None
-
-        xml_file = vfs.VFS.open('gui/character_screen.xml')
-        self.character_screen = pychan.loadXML(xml_file)
-
-        self.character_screen.adaptLayout()
-        character_screen_events = {}
-        character_screen_events['startButton'] = self.startNewGame
-        character_screen_events['cancelButton'] = self.cancelNewGame
-        self.character_screen.mapEvents(character_screen_events)
-    
-    def show(self):
-        """Display the view.
-           @return: None"""
-        self.background.show()
-        self.character_screen.show()
-    
-    def hide(self):
-        """Hide the view.
-           @return: None"""
-        self.background.hide()
-        self.character_screen.hide()
-    
-    def startNewGame(self):
-        """Callback tied to the startButton.
-           @return: None"""
-        self.start_new_game_callback()
-    
-    def cancelNewGame(self):
-        """Callback tied to the cancelButton.
-           @return: None"""
-        self.cancel_new_game_callback()
--- a/src/parpg/characterstatistics.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-Provides classes that define character stats and traits.
-"""
-
-from abc import ABCMeta, abstractmethod
-from weakref import ref as weakref
-
-from .serializers import SerializableRegistry
-
-from components import character_statistics
-
-class AbstractCharacterStatistic(object):
-    __metaclass__ = ABCMeta
-    
-    @abstractmethod
-    def __init__(self, description, minimum, maximum):
-        self.description = description
-        self.minimum = minimum
-        self.maximum = maximum
-
-
-class PrimaryCharacterStatistic(AbstractCharacterStatistic):
-    def __init__(self, long_name, short_name, description, minimum=0,
-                 maximum=100):
-        AbstractCharacterStatistic.__init__(self, description=description,
-                                            minimum=minimum, maximum=maximum)
-        self.long_name = long_name
-        self.short_name = short_name
-
-SerializableRegistry.registerClass(
-    'PrimaryCharacterStatistic',
-    PrimaryCharacterStatistic,
-    init_args=[
-        ('long_name', unicode),
-        ('short_name', unicode),
-        ('description', unicode),
-        ('minimum', int),
-        ('maximum', int),
-    ],
-)
-
-
-class SecondaryCharacterStatistic(AbstractCharacterStatistic):
-    def __init__(self, name, description, unit, mean, sd, stat_modifiers,
-                 minimum=None, maximum=None):
-        AbstractCharacterStatistic.__init__(self, description=description,
-                                            minimum=minimum, maximum=maximum)
-        self.name = name
-        self.unit = unit
-        self.mean = mean
-        self.sd = sd
-        self.stat_modifiers = stat_modifiers
-
-SerializableRegistry.registerClass(
-    'SecondaryCharacterStatistic',
-    SecondaryCharacterStatistic,
-    init_args=[
-        ('name', unicode),
-        ('description', unicode),
-        ('unit', unicode),
-        ('mean', float),
-        ('sd', float),
-        ('stat_modifiers', dict),
-        ('minimum', float),
-        ('maximum', float),
-    ],
-)
-
-
-class AbstractStatisticValue(object):
-    __metaclass__ = ABCMeta
-    
-    @abstractmethod
-    def __init__(self, statistic_type, character):
-        self.statistic_type = statistic_type
-        self.character = weakref(character)
-
-
-class PrimaryStatisticValue(AbstractStatisticValue):
-    def value():
-        def fget(self):
-            return self._value
-        def fset(self, new_value):
-            assert 0 <= new_value <= 100
-            self._value = new_value
-    
-    def __init__(self, statistic_type, character, value):
-        AbstractStatisticValue.__init__(self, statistic_type=statistic_type,
-                                        character=character)
-        self._value = None
-        self.value = value
-
-
-class SecondaryStatisticValue(AbstractStatisticValue):
-    def normalized_value():
-        def fget(self):
-            return self._normalized_value
-        def fset(self, new_value):
-            self._normalized_value = new_value
-            statistic_type = self.statistic_type
-            mean = statistic_type.mean
-            sd = statistic_type.sd
-            self._value = self.calculate_value(mean, sd, new_value)
-        return locals()
-    normalized_value = property(**normalized_value())
-    
-    def value():
-        def fget(self):
-            return self._value
-        def fset(self, new_value):
-            self._value = new_value
-            statistic_type = self.statistic_type
-            mean = statistic_type.mean
-            sd = statistic_type.sd
-            self._normalized_value = self.calculate_value(mean, sd, new_value)
-        return locals()
-    value = property(**value())
-    
-    def __init__(self, statistic_type, character):
-        AbstractStatisticValue.__init__(self, statistic_type=statistic_type,
-                                        character=character)
-        mean = statistic_type.mean
-        sd = statistic_type.sd
-        normalized_value = self.derive_value(normalized=True)
-        self._normalized_value = normalized_value
-        self._value = self.calculate_value(mean, sd, normalized_value)
-    
-    def derive_value(self, normalized=True):
-        """
-        Derive the current value 
-        """
-        statistic_type = self.statistic_type
-        stat_modifiers = statistic_type.stat_modifiers
-        character = self.character()
-        
-        value = sum(
-            character_statistics.get_statistic(character, name).value * 
-            modifier for name, modifier in
-                stat_modifiers.items()
-        )
-        assert 0 <= value <= 100
-        if not normalized:
-            mean = statistic_type.mean
-            sd = statistic_type.sd
-            value = self.calculate_value(mean, sd, value)
-        return value
-    
-    @staticmethod
-    def calculate_value(mean, sd, normalized_value):
-        value = sd * (normalized_value - 50) + mean
-        return value
-    
-    @staticmethod
-    def calculate_normalized_value(mean, sd, value):
-        normalized_value = ((value - mean) / sd) + 50
-        return normalized_value
--- a/src/parpg/common/listeners/command_listener.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-#!/usr/bin/env python
-#   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/>.
-
-"""This module contains the CommandListener class for receiving command events"""
-
-
-class CommandListener(object):
-    """Base class for listeners that receiving command events"""
-
-    def __init__(self, event_listener):
-        self.event_listener = None
-        CommandListener.attach(self, event_listener)
-    
-    def attach(self, event_listener):
-        """Attaches the listener to the event"""
-        event_listener.addListener("Command", self)
-        self.event_listener = event_listener
-        
-    def detach(self):
-        """Detaches the listener from the event"""
-        self.event_listener.removeListener("Command", self)
-        self.event_listener = None
-
-    def onCommand(self, command):
-        """Called when a command is executed"""
-        pass
--- a/src/parpg/common/listeners/console_executor.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-#!/usr/bin/env python
-
-#   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/>.
-
-"""This module contains the ConsoleExecuter class that receives 
-console events"""
-
-class ConsoleExecuter(object):
-    """This class is a base class for listeners receiving console events"""
-
-    def __init__(self, event_listener):
-        self.event_listener = None
-        ConsoleExecuter.attach(self, event_listener)
-    
-    def attach(self, event_listener):
-        """Attaches the listener to the event"""
-        event_listener.addListener("ConsoleCommand", self)
-        self.event_listener = event_listener
-        
-    def detach(self):
-        """Detaches the listener from the event"""
-        self.event_listener.removeListener("ConsoleCommand", self)
-        self.event_listener = None
-
-    def onToolsClick(self):
-        """Called when the tools button has been clicked"""
-        pass
-    
-    def onConsoleCommand(self, command):
-        """Called when a console command is executed"""
-        pass
\ No newline at end of file
--- a/src/parpg/common/listeners/event_listener.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-#!/usr/bin/env python
-
-#   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/>.
-
-"""This module contains the EventListener that receives events and distributes 
-them to PARPG listeners"""
-import logging
-
-from fife import fife
-from fife.extensions import pychan
-
-logger = logging.getLogger('event_listener')
-
-class EventListener(fife.IKeyListener, 
-                   fife.ICommandListener, 
-                   fife.IMouseListener, 
-                   fife.ConsoleExecuter):
-    """Class that receives all events and distributes them to the listeners"""
-    def __init__(self, engine):
-        """Initialize the instance"""
-        self.event_manager = engine.getEventManager()
-
-        fife.IKeyListener.__init__(self)
-        self.event_manager.addKeyListener(self)
-        fife.ICommandListener.__init__(self)
-        self.event_manager.addCommandListener(self)
-        fife.IMouseListener.__init__(self)
-        self.event_manager.addMouseListener(self)
-        fife.ConsoleExecuter.__init__(self)
-        pychan.manager.hook.guimanager.getConsole().setConsoleExecuter(self)
-        
-        self.listeners = {"Mouse" : [],                          
-                          "Key" : [],
-                          "Command" : [],
-                          "ConsoleCommand" : [],
-                          "Widget" : []}               
-                
-    def addListener(self, listener_type, listener):
-        """Adds a listener"""
-        if listener_type in self.listeners.iterkeys():
-            if not listener in self.listeners[listener_type]:
-                self.listeners[listener_type].append(listener)            
-        else:
-            logger.warning("Listener type "
-                                  "'{0}' not supported".format(listener_type))
-    
-    def removeListener(self, listener_type, listener):
-        """Removes a listener"""
-        if listener_type in self.listeners.iterkeys():
-            self.listeners[listener_type].remove(listener)
-        else:
-            logger.warning("Listener type "
-                                  "'{0}' not supported".format(listener_type))
-            
-    def mousePressed(self, evt):
-        """Called when a mouse button is pressed"""
-        for listeners in self.listeners["Mouse"]:
-            listeners.mousePressed(evt)
-
-    def mouseReleased(self, evt):
-        """Called when a mouse button is released"""
-        for listeners in self.listeners["Mouse"]:
-            listeners.mouseReleased(evt)
-
-    def mouseEntered(self, evt):
-        """Called when a mouse enters a region"""
-        for listeners in self.listeners["Mouse"]:
-            listeners.mouseEntered(evt)
-
-    def mouseExited(self, evt):
-        """Called when a mouse exits a region"""
-        for listeners in self.listeners["Mouse"]:
-            listeners.mouseExited(evt)
-
-    def mouseClicked(self, evt):
-        """Called after a mouse button is pressed and released"""
-        for listeners in self.listeners["Mouse"]:
-            listeners.mouseClicked(evt)
-
-    def mouseWheelMovedUp(self, evt):
-        """Called when the mouse wheel has been moved up"""
-        for listeners in self.listeners["Mouse"]:
-            listeners.mouseWheelMovedUp(evt)
-
-    def mouseWheelMovedDown(self, evt):
-        """Called when the mouse wheel has been moved down"""
-        for listener in self.listeners["Mouse"]:
-            listener.mouseWheelMovedDown(evt)
-
-    def mouseMoved(self, evt):
-        """Called when when the mouse has been moved"""
-        for listener in self.listeners["Mouse"]:
-            listener.mouseMoved(evt)
-
-    def mouseDragged(self, evt):
-        """Called when dragging the mouse"""
-        for listener in self.listeners["Mouse"]:
-            listener.mouseDragged(evt)
-
-    def keyPressed(self, evt):
-        """Called when a key is being pressed"""
-        for listener in self.listeners["Key"]:
-            listener.keyPressed(evt)
-
-    def keyReleased(self, evt):
-        """Called when a key is being released"""
-        for listener in self.listeners["Key"]:
-            listener.keyReleased(evt)
-
-    def onCommand(self, command):
-        """Called when a command is executed"""
-        for listener in self.listeners["Command"]:
-            listener.onCommand(command)
-
-    def onToolsClick(self):
-        """Called when the tools button has been clicked"""
-        for listener in self.listeners["ConsoleCommand"]:
-            listener.onToolsClick()
-
-    def onConsoleCommand(self, command):
-        """Called when a console command is executed"""
-        for listener in self.listeners["ConsoleCommand"]:
-            listener.onConsoleCommand(command)
-
-    def onWidgetAction(self, evt):
-        """Called when a widget action is executed"""
-        for listener in self.listeners["Widget"]:
-            listener.onWidgetAction(evt)
-
-
--- a/src/parpg/common/listeners/key_listener.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-
-#   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/>.
-
-"""This module contains the KeyListener class for receiving key inputs"""
-
-class KeyListener(object):
-    """Base class for listeners receiving keyboard input"""
-
-    def __init__(self, event_listener):
-        self.event_listener = None
-        KeyListener.attach(self, event_listener)
-    
-    def attach(self, event_listener):
-        """Attaches the listener to the event"""
-        event_listener.addListener("Key", self)
-        self.event_listener = event_listener
-        
-    def detach(self):
-        """Detaches the listener from the event"""
-        self.event_listener.removeListener("Key", self)
-        
-    def keyPressed(self, event):
-        """Called when a key is being pressed"""
-        pass
-    
-    def keyReleased(self, event):
-        """Called when a key is being released"""
-        pass
\ No newline at end of file
--- a/src/parpg/common/listeners/mouse_listener.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-
-#   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/>.
-
-"""This module contains the MouseListener class for receiving mouse inputs"""
-
-class MouseListener(object):
-    """Base class for listeners receiving mouse input"""
-    
-    def __init__(self, event_listener):
-        self.event_listener = None
-        MouseListener.attach(self, event_listener)
-    
-    def attach(self, event_listener):
-        """Attaches the listener to the event"""
-        event_listener.addListener("Mouse", self)
-        self.event_listener = event_listener
-        
-    def detach(self):
-        """Detaches the listener from the event"""
-        self.event_listener.removeListener("Mouse", self)
-        self.event_listener = None
-        
-    def mousePressed(self, evt):
-        """Called when a mouse button is pressed"""
-        pass
-
-    def mouseReleased(self, evt):
-        """Called when a mouse button is released"""
-        pass
-
-    def mouseEntered(self, evt):
-        """Called when a mouse enters a region"""
-        pass
-
-    def mouseExited(self, evt):
-        """Called when a mouse exits a region"""
-        pass
-
-    def mouseClicked(self, evt):
-        """Called after a mouse button is pressed and released"""
-        pass
-
-    def mouseWheelMovedUp(self, evt):
-        """Called when the mouse wheel has been moved up"""
-        pass
-
-    def mouseWheelMovedDown(self, evt):
-        """Called when the mouse wheel has been moved down"""
-        pass
-
-    def mouseMoved(self, evt):
-        """Called when when the mouse has been moved"""
-        pass
-
-    def mouseDragged(self, evt):
-        """Called when dragging the mouse"""
-        pass
--- a/src/parpg/common/listeners/widget_listener.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-#!/usr/bin/env python
-
-#   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/>.
-
-"""This module contains the WidgetListener class for receiving widget events"""
-
-class WidgetListener(object):
-    """A Base class for listeners receiving widget events"""
-    
-    def __init__(self, event_listener):
-        self.event_listener = None
-        WidgetListener.attach(self, event_listener)
-    
-    def attach(self, event_listener):
-        """Attaches the listener to the event"""
-        event_listener.addListener("Widget", self)
-        self.event_listener = event_listener
-        
-    def detach(self):
-        """Detaches the listener from the event"""
-        self.event_listener.removeListener("Widget", self)
-        self.event_listener = None
-
-    def onWidgetAction(self, evt):
-        """Called when a widget action is executed"""
-        pass
\ No newline at end of file
--- a/src/parpg/common/ordereddict.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-# Copyright (c) 2009 Raymond Hettinger
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation files
-# (the "Software"), to deal in the Software without restriction,
-# including without limitation the rights to use, copy, modify, merge,
-# publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so,
-# subject to the following conditions:
-#
-#     The above copyright notice and this permission notice shall be
-#     included in all copies or substantial portions of the Software.
-#
-#     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-#     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-#     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-#     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-#     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-#     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-#     OTHER DEALINGS IN THE SOFTWARE.
-
-from UserDict import DictMixin
-
-class OrderedDict(dict, DictMixin):
-
-    def __init__(self, *args, **kwds):
-        if len(args) > 1:
-            raise TypeError('expected at most 1 arguments, got %d' % len(args))
-        try:
-            self.__end
-        except AttributeError:
-            self.clear()
-        self.update(*args, **kwds)
-
-    def clear(self):
-        self.__end = end = []
-        end += [None, end, end]         # sentinel node for doubly linked list
-        self.__map = {}                 # key --> [key, prev, next]
-        dict.clear(self)
-
-    def __setitem__(self, key, value):
-        if key not in self:
-            end = self.__end
-            curr = end[1]
-            curr[2] = end[1] = self.__map[key] = [key, curr, end]
-        dict.__setitem__(self, key, value)
-
-    def __delitem__(self, key):
-        dict.__delitem__(self, key)
-        key, prev, next = self.__map.pop(key)
-        prev[2] = next
-        next[1] = prev
-
-    def __iter__(self):
-        end = self.__end
-        curr = end[2]
-        while curr is not end:
-            yield curr[0]
-            curr = curr[2]
-
-    def __reversed__(self):
-        end = self.__end
-        curr = end[1]
-        while curr is not end:
-            yield curr[0]
-            curr = curr[1]
-
-    def popitem(self, last=True):
-        if not self:
-            raise KeyError('dictionary is empty')
-        if last:
-            key = reversed(self).next()
-        else:
-            key = iter(self).next()
-        value = self.pop(key)
-        return key, value
-
-    def __reduce__(self):
-        items = [[k, self[k]] for k in self]
-        tmp = self.__map, self.__end
-        del self.__map, self.__end
-        inst_dict = vars(self).copy()
-        self.__map, self.__end = tmp
-        if inst_dict:
-            return (self.__class__, (items,), inst_dict)
-        return self.__class__, (items,)
-
-    def keys(self):
-        return list(self)
-
-    setdefault = DictMixin.setdefault
-    update = DictMixin.update
-    pop = DictMixin.pop
-    values = DictMixin.values
-    items = DictMixin.items
-    iterkeys = DictMixin.iterkeys
-    itervalues = DictMixin.itervalues
-    iteritems = DictMixin.iteritems
-
-    def __repr__(self):
-        if not self:
-            return '%s()' % (self.__class__.__name__,)
-        return '%s(%r)' % (self.__class__.__name__, self.items())
-
-    def copy(self):
-        return self.__class__(self)
-
-    @classmethod
-    def fromkeys(cls, iterable, value=None):
-        d = cls()
-        for key in iterable:
-            d[key] = value
-        return d
-
-    def __eq__(self, other):
-        if isinstance(other, OrderedDict):
-            if len(self) != len(other):
-                return False
-            for p, q in  zip(self.items(), other.items()):
-                if p != q:
-                    return False
-            return True
-        return dict.__eq__(self, other)
-
-    def __ne__(self, other):
-        return not self == other
--- a/src/parpg/common/utils.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-# Miscellaneous game functions
-
-import sys
-import os
-import fnmatch
-
-from textwrap import dedent
-from contextlib import contextmanager
-from parpg import vfs
-
-def addPaths (*paths):
-    """Adds a list of paths to sys.path. Paths are expected to use forward
-       slashes, for example '../../engine/extensions'. Slashes are converted
-       to the OS-specific equivalent.
-       @type paths: ???
-       @param paths: Paths to files?
-       @return: None"""
-    for p in paths:
-        if not p in sys.path:
-            sys.path.append(os.path.sep.join(p.split('/')))
-
-def parseBool(value):
-    """Parses a string to get a boolean value"""
-    if (value.isdigit()):
-        return bool(int(value))
-    elif (value.isalpha):
-        return value.lower()[0] == "t"
-    return False
-
-def locateFiles(pattern, root=os.curdir):
-    """Locate all files matching supplied filename pattern in and below
-    supplied root directory."""
-    filepaths = []
-    filenames = vfs.VFS.listFiles(root)
-    for filename in fnmatch.filter(filenames, pattern):
-        vfs_file_path = '/'.join([root, filename])
-        filepaths.append(vfs_file_path)
-    dirnames = vfs.VFS.listDirectories(root)
-    for dirname in dirnames:
-        subdir_filepaths = locateFiles(pattern, '/'.join([root, dirname]))
-        filepaths.extend(subdir_filepaths)
-    return filepaths
-
-def dedent_chomp(string):
-    """Remove common leading whitespace and chomp each non-blank line."""
-    dedented_string = dedent(string).strip()
-    lines = dedented_string.splitlines()
-    formatted_lines = []
-    for index in range(len(lines)):
-        line = lines[index]
-        if index == len(lines) - 1:
-            # Don't do anything to the last line.
-            pass
-        elif not line or line.isspace():
-            line = '\n\n'
-        else:
-            line = ''.join([line, ' '])
-        formatted_lines.append(line)
-    result = ''.join(formatted_lines)
-    return result
-
-@contextmanager
-def cwd(dirname):
-    cwd = os.getcwd()
-
-    try:
-        os.chdir(dirname)
-        yield
-    finally:
-        os.chdir(cwd)
--- a/src/parpg/components/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-from character_statistics import CharacterStatistics
-from containable import Containable
-from container import Container
-from description import Description
-from dialogue import Dialogue
-from fifeagent import FifeAgent
-from lockable import Lockable
-from usable import Usable
-from change_map import ChangeMap
-from equipable import Equipable
-from equip import Equip
-from general import General
-from behaviour import Behaviour
-from graphics import Graphics
-
-components = {
-        "general": General(),
-        "characterstats": CharacterStatistics(),
-        "containable": Containable(),
-        "container": Container(),
-        "description": Description(),
-        "dialogue": Dialogue(),
-        "fifeagent": FifeAgent(),
-        "lockable": Lockable(),
-        "usable": Usable(),
-        "change_map": ChangeMap(),
-        "equipable": Equipable(),
-        "equip": Equip(),
-        "behaviour": Behaviour(),
-        "graphics": Graphics(),
-    }
\ No newline at end of file
--- a/src/parpg/components/base.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from parpg.bGrease.component import Component
-
-class Base(Component):
-    """Base component for PARPG."""
-    
-    @property
-    def saveable_fields(self):
-        return self.fields.keys()
\ No newline at end of file
--- a/src/parpg/components/behaviour.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from base import Base
-
-class Behaviour(Base):
-    """Component that stores the values of the behaviour"""
-    
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, behaviour_type=str)
-        self.behaviour_type = "Base"
\ No newline at end of file
--- a/src/parpg/components/change_map.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from base import Base
-from parpg.bGrease.geometry import Vec2d
-
-class ChangeMap(Base):
-    """Component that allows an entity to be contained by Container entity."""
-    
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, target_map=str, target_position=list)
\ No newline at end of file
--- a/src/parpg/components/character_statistics.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from base import Base
-
-class CharacterStatistics(Base):
-    """Component that defines character statistics."""
-
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, gender=str, picture=str, age=int, origin=str, 
-                      primary_stats=dict, secondary_stats=dict, traits=list, 
-                      )
-    @property
-    def saveable_fields(self):
-        fields = self.fields.keys()
-        fields.remove("primary_stats")
-        fields.remove("secondary_stats")
-        return fields
-    
-def get_statistic(stats, name):
-    """Gets the statistic by its name"""
-    if name in stats.primary_stats:
-        return stats.primary_stats[name]
-    elif name in stats.secondary_stats:
-        return stats.secondary_stats[name]
-    else:
-        for stat in stats.primary_stats:
-            if stat.statistic_type.short_name == name:
-                return stat
-    return None
-
-def get_stat_values(char_stats):
-    stats = {"primary":{}, "secondary":{}}
-    for name, stat in char_stats.primary_stats.iteritems():
-        stats["primary"][name] = stat.value
-    for name, stat in char_stats.secondary_stats.iteritems():
-        stats["secondary"][name] = stat.value
-    return stats
\ No newline at end of file
--- a/src/parpg/components/containable.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from copy import deepcopy
-
-from base import Base
-
-class Containable(Base):
-    """Component that allows an entity to be contained by Container entity."""
-    
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, bulk=int, weight=int, item_type=str, image=str, container=object, slot=int)
-
-    @property
-    def saveable_fields(self):
-        fields = self.fields.keys()
-        fields.remove("container")
-        return fields
\ No newline at end of file
--- a/src/parpg/components/container.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from copy import deepcopy
-
-from base import Base
-
-class Container(Base):
-    """
-    Component that allows an entity to contain one or more child entities.
-    """
-    
-    def __init__(self):
-        Base.__init__(self, children=list, max_bulk=int)
-
-    @property
-    def saveable_fields(self):
-        fields = self.fields.keys()
-        fields.remove("children")
-        return fields
-
-
-
-class BulkLimitError(Exception):
-    """Error that gets raised when the item would exceed the 
-    bulk limit of the container."""
-    
-    def __init__(self, bulk, max_bulk):
-        self.bulk = bulk
-        self.max_bulk = max_bulk
-    
-    def __str__(self):
-        return "Item would exceed the bulk limit of the container."
-
-class NoFreeSlotError(Exception):
-    """Error that gets raised when the container has no free slots."""
-  
-    def __str__(self):
-        return "Container can't hold any more items."
-    
-def get_free_slot(container):
-    """Returns the first slot of the container that is not occupied."""
-    index = 0
-    for child in container.children:
-        if not child:
-            return index
-        index += 1
-    raise NoFreeSlotError
-
-def get_total_bulk(container):
-    """Returns the bulk of all items in the container."""
-    total_bulk = 0
-    for child in container.children:
-        if child:
-            total_bulk += child.bulk
-    return total_bulk
-
-def get_total_weight(container):
-    """Returns the weight of all items in the container."""
-    total_weight = 0
-    for child in container.children:
-        if child:
-            total_weight += child.weight
-    return total_weight
-
-def get_item(container, slot_or_type):
-    """Returns the item that is in the slot, or has the given type."""
-    if type(slot_or_type) == int:
-        if len(container.children) >= (slot_or_type + 1):
-            return container.children[slot_or_type]
-    else:
-        for child in container.children:
-            if child and child.item_type == slot_or_type:
-                return child
-                
-    return None
-
-def remove_item(container, slot_or_type):
-    """Removes the item at the given slot, or with the given type."""
-    if type(slot_or_type) == int:
-        item = get_item(container, slot_or_type)
-        if item:
-            container.children[slot_or_type] = None
-            item.container = None
-            item.slot = -1
-    else:
-        for child in container.children:
-            if child and child.item_type == slot_or_type:
-                container.children[child.slot] = None
-                child.container = None
-                child.slot = -1
-
-def take_item(container, slot_or_type):
-    """Moves the item at the given slot, or with the given type,
-    out of the container and returns it."""
-    item = get_item(container, slot_or_type)
-    if item:
-        remove_item(container, slot_or_type)
-    return item
-
-def put_item(container, item, slot=-1):
-    """Puts the item at the given slot in the container.
-    Returns the item previously at the slot."""
-    if slot == -1:
-        slot = get_free_slot(container)
-    total_bulk = get_total_bulk(container)
-    total_bulk += item.bulk
-    old_item = get_item(container, slot)
-    if old_item:
-        total_bulk -= old_item.bulk
-    if total_bulk > container.max_bulk:
-        raise BulkLimitError(total_bulk, container.max_bulk)
-    remove_item(container, slot)
-    container.children[slot] = item
-    if item.container:
-        remove_item(item.container, item.slot)
-    item.container = container
-    item.slot = slot
-    return old_item
\ No newline at end of file
--- a/src/parpg/components/description.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from base import Base
-
-class Description(Base):
-    """Component that stores the description of an object"""
-    
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, view_name=str, real_name=str, desc=str)
--- a/src/parpg/components/dialogue.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from copy import deepcopy
-
-from base import Base
-
-class Dialogue(Base):
-    """Component that stores the dialogue"""
-    
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, dialogue=object)
-
-    @property
-    def saveable_fields(self):
-        fields = self.fields.keys()
-        fields.remove("dialogue")
-        return fields
\ No newline at end of file
--- a/src/parpg/components/equip.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from base import Base
-
-class Equip(Base):
-    """
-    Component that stores the equipment (what is being worn/wielded).
-    """
-    
-    def __init__(self):
-        Base.__init__(self, head=object, neck=object, body=object, belt=object, 
-                      leg=object, feet=object, l_arm=object, r_arm=object)
-        self.head = None
-        self.neck = None
-        self.body = None
-        self.belt = None
-        self.leg = None
-        self.feet = None
-        self.l_arm = None
-        self.r_arm = None
-
-    @property
-    def saveable_fields(self):
-        return []
-
-class SlotInvalidError(Exception):
-    """Error that gets raised when the slot is invalid."""
-    
-    def __init__(self, slot):
-        self.slot = slot
-    
-    def __str__(self):
-        return "\"%s\" is not a valid slot." % self.slot
-    
-class AlreadyEquippedError(Exception):
-    """Error that gets raised when the equipable already has a wearer"""
-    
-    def __str__(self):
-        return "The equipable is already weared."
-
-class CannotBeEquippedInSlot(Exception):
-    """Error that gets raised when the equipable can't be equiped in that 
-    slot"""
-    
-    def __init__(self, slot, equipable):
-        self.slot = slot
-        self.equipable = equipable
-        
-    def __str__(self):
-        return ("%s is not in the equipables slots. (%s)" % 
-                (self.slot, ', '.join(self.equipable.possible_slots))
-                )
-    
-    
-def equip(wearer, equipable, slot):
-    """Equip the wearer with the given equipable.
-    @returns The equipable that was at the given slot, or None"""
-    if equipable.wearer:
-        raise AlreadyEquippedError
-    if slot in equipable.possible_slots:
-        try:
-            old_item = getattr(wearer, slot) if hasattr(wearer, slot) else None
-            setattr(wearer, slot, equipable)
-            equipable.in_slot = slot
-            equipable.wearer = wearer
-            if old_item:
-                old_item.in_slot = None
-                old_item.wearer = None
-            return old_item
-        except AttributeError:
-            raise SlotInvalidError(slot)
-    raise CannotBeEquippedInSlot(slot, equipable)
-
-def get_equipable(wearer, slot):
-    """Return the equipable in the given slot"""
-    if not wearer:
-        return None
-    try:
-        item = getattr(wearer, slot)
-        return item
-    except AttributeError:
-        raise SlotInvalidError(slot)
-    
-def take_equipable(wearer, slot):
-    """Remove equipable from the given slot and return it"""
-    item = get_equipable(wearer, slot)
-    setattr(wearer, slot, None)
-    if item:
-        item.in_slot = None
-        item.wearer = None
-    return item
-    
-    
\ No newline at end of file
--- a/src/parpg/components/equipable.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from copy import deepcopy
-
-from base import Base
-
-class Equipable(Base):
-    """
-    Component that stores the data for an entity that can be equipped.
-    """
-    
-    def __init__(self):
-        Base.__init__(self, possible_slots=list, wearer=object, in_slot=str)
-        
-    @property
-    def saveable_fields(self):
-        fields = self.fields.keys()
-        fields.remove("wearer")
-        return fields
\ No newline at end of file
--- a/src/parpg/components/fifeagent.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from copy import deepcopy
-
-from base import Base
-
-
-class FifeAgent(Base):
-    """Component that stores the values for a fife agent"""
-    
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, layer=object, behaviour=object)
-
-    @property
-    def saveable_fields(self):
-        fields = self.fields.keys()
-        fields.remove("layer")
-        fields.remove("behaviour")
-        return fields
-
-        
-def setup_behaviour(agent):
-    """Attach the behaviour to the layer"""
-    if agent.behaviour:   
-        agent.behaviour.attachToLayer(agent.entity.getID(), agent.layer)
-        
-def approach(agent, target_or_location, action):
-    if agent.behaviour: 
-        agent.behaviour.approach(target_or_location, action)
-        
-commands = {"approach":approach}
\ No newline at end of file
--- a/src/parpg/components/general.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from base import Base
-
-class General(Base):
-    """Component that stores the general values of an parpg entity"""
-    
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, identifier=str)
\ No newline at end of file
--- a/src/parpg/components/graphics.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from base import Base
-
-
-class Graphics(Base):
-    """Component that stores the values for the graphical representation"""
-    
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, gfx=str)
\ No newline at end of file
--- a/src/parpg/components/lockable.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from base import Base
-
-class Lockable(Base):
-    """Component that stores the data of a lock"""
-
-    def __init__(self):
-        """Constructor"""
-        Base.__init__(self, closed=bool, locked=bool)
-
-class LockedError(Exception):
-
-    def __str__(self):
-        return "Is locked"
-
-class OpenError(Exception):
-
-    def __str__(self):
-        return "Is open"
-
-def lock(lock):
-    if not lock.closed:
-        raise OpenError
-    lock.locked = True    
-
-def unlock(lock):
-    lock.locked = False
-
-def open(lock):
-    if lock.locked:
-        raise LockedError
-    lock.closed = False
-
-def close(lock):
-    lock.closed = True
\ No newline at end of file
--- a/src/parpg/components/usable.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from base import Base
-
-class Usable(Base):
-    """
-    Component that stores data about the actions that an object can do.
-    """
-    
-    def __init__(self):
-        Base.__init__(self, actions=dict)
\ No newline at end of file
--- a/src/parpg/console.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,204 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-import re
-import os
-import sys
-from StringIO import StringIO
-import code
-
-class Console:
-    def __init__(self, app_listener):
-        """
-        @type appListener: ApplicationListener
-        @param appListener: ApplicationListener object providing a link with
-        the Controller, the view and the GameModel"""
-        exit_help   = "Terminate application"
-        grid_help   = "Toggle grid display"
-        run_help    = "Toggle player run/walk"
-        help_help   = "Show this help string"
-        load_help   = "Usage: load directory file"
-        python_help = "Run some python code"
-        quit_help   = "Terminate application"
-        save_help   = "Usage: save directory file"
-        pause_help  = "Pause/Unpause the game"
-
-        self.commands = [
-            {"cmd":"exit"  ,"callback":self.handleQuit  ,"help": exit_help},
-            {"cmd":"grid"  ,"callback":self.handleGrid  ,"help": grid_help},
-            {"cmd":"help"  ,"callback":self.handleHelp  ,"help": help_help},
-            {"cmd":"load"  ,"callback":self.handleLoad  ,"help": load_help},
-            {"cmd":"pause" ,"callback":self.handlePause ,"help": pause_help},
-            {"cmd":"python","callback":self.handlePython,"help": python_help},
-            {"cmd":"run"   ,"callback":self.handleRun   ,"help": run_help},
-            {"cmd":"save"  ,"callback":self.handleSave  ,"help": save_help},
-            {"cmd":"quit"  ,"callback":self.handleQuit  ,"help": quit_help},
-        ]
-        self.app_listener = app_listener
-        self.view = self.app_listener.view 
-        self.model = self.app_listener.model
-        self.game_state = self.app_listener.view.model.game_state
-        self.console_locals = {"__name__":"__paprg_console__",\
-                               "__doc__": None,\
-                               "app_listener":self.app_listener,\
-                               "model":self.app_listener.model,\
-                               "view":self.app_listener.view,\
-                               "engine":self.app_listener.engine}
-
-        self.console = code.InteractiveConsole(self.console_locals)
-
-    def handleQuit(self, command):
-        """Implements the quit console command 
-           @type command: string
-           @param command: The command to run
-           @return: The resultstring"""
-        self.app_listener.quitGame()
-        return "Terminating ..."
-
-    def handlePause(self, command):
-        """Implements the pause console command
-           @type command: string
-           @param command: The command to run
-           @return: The resultstring"""
-        self.model.togglePause()
-        return "Game (un)paused"
-
-    def handleGrid(self, command):
-        """Implements the grid console command 
-           @type command: string
-           @param command: The command to run
-           @return: The resultstring"""
-        self.app_listener.view.active_map.toggleRenderer('GridRenderer')
-        return "Grid toggled"
-
-    def handleRun(self, command):
-        """Toggles run/walk mode of the PC player
-           @type command: string
-           @param command: The command to run.
-           @return: The response"""
-        if self.app_listener.model.pc_run == 1:
-            self.app_listener.model.pc_run = 0
-            return "PC is now walking"
-        else:
-            self.app_listener.model.pc_run = 1
-            return "PC is now running"
-
-    def handleHelp(self, command):
-        """Implements the help console command 
-           @type command: string
-           @param command: The command to run
-           @return: The resultstring"""
-        res = ""
-        for cmd in self.commands:
-            res += "%10s: %s\n" % (cmd["cmd"], cmd["help"])
-        return res
-
-    def handlePython(self,command):
-        user_code = command[7:len(command)]
-
-        codeOut = StringIO()
-
-        #make stdout and stderr write to our file, not the terminal
-        sys.stdout = codeOut
-        sys.stderr = codeOut
-
-        #Workaround it not being possible to enter a blank line in the console
-        if user_code == " ":
-            user_code = ""
-
-        #Process the code
-        self.console.push(user_code)
-        if len(self.console.buffer) == 0:
-            output = codeOut.getvalue()
-        else:
-            output =  "..."
-
-
-        #restore stdout and stderr
-        sys.stdout = sys.__stdout__
-        sys.stderr = sys.__stderr__
-
-        temp_output = output
-        output = ""
-        counter = 0
-
-        #Make the output fit in the console screen
-        for char in temp_output:
-            counter += 1
-            if char == "\n":
-                counter = 0
-            elif counter == 110:
-                output += "\n"
-                counter = 0
-            output += char
-
-        return output
-
-    def handleLoad(self, command):
-        """Implements the load console command 
-           @type command: string
-           @param command: The command to run
-           @return: The resultstring"""
-        result = None
-        load_regex = re.compile('^load')
-        l_matches = load_regex.match(command.lower())
-        if (l_matches is not None):
-            end_load = l_matches.end()
-            try:
-                l_args = command.lower()[end_load + 1:].strip()
-                l_path, l_filename = l_args.split(' ')
-                self.app_listener.model.load_save = True
-                self.app_listener.model.savegame = os.path.join(l_path, l_filename)
-                result = "Load triggered"
-
-            except Exception, l_error:
-                self.app_listener.engine.getGuiManager().getConsole().println('Error: ' + str(l_error))
-                result="Failed to load file"
-
-        return result
-
-    def handleSave(self, command):
-        """Implements the save console command 
-           @type command: string
-           @param command: The command to run
-           @return: The resultstring"""
-        save_regex = re.compile('^save')
-        s_matches = save_regex.match(command.lower())
-        if (s_matches != None):
-            end_save = s_matches.end()
-            try:
-                s_args = command.lower()[end_save+1:].strip()
-                s_path, s_filename = s_args.split(' ')
-                self.app_listener.model.save(s_path, s_filename)
-                result = "Saved to file: " + s_path + s_filename
-
-            except Exception, s_error:
-                self.app_listener.engine.getGuiManager().getConsole(). \
-                    println('Error: ' + str(s_error))
-                result = "Failed to save file"
-        return result 
-
-    def handleConsoleCommand(self, command):
-        """Implements the console logic 
-           @type command: string
-           @param command: The command to run
-           @return: The response string """
-        result = None        
-        for cmd in self.commands:
-            regex = re.compile('^' + cmd["cmd"])
-            if regex.match(command.lower()):
-                result=cmd["callback"](command)
-
-        if result is None:
-            result = self.handlePython("python " + command) 
-        return result
--- a/src/parpg/controllerbase.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +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 <http://www.gnu.org/licenses/>.
-from fife import fife
-
-from parpg.common.listeners.key_listener import KeyListener
-from parpg.common.listeners.mouse_listener import MouseListener
-from parpg.common.listeners.command_listener import CommandListener
-from parpg.mode import FifeMode
-
-class ControllerBase(FifeMode, KeyListener, MouseListener, CommandListener):
-    """Base of Controllers"""
-    def __init__(self, 
-                 engine, 
-                 view, 
-                 model, 
-                 application):
-        '''
-        Constructor
-        @param engine: Instance of the active fife engine
-        @type engine: fife.Engine
-        @param view: Instance of a GameSceneView
-        @param type: parpg.GameSceneView
-        @param model: The model that has the current gamestate
-        @type model: parpg.GameModel
-        @param application: The application that created this controller
-        @type application: parpg.PARPGApplication
-        @param settings: The current settings of the application
-        @type settings: fife.extensions.fife_settings.Setting
-        '''
-        KeyListener.__init__(self, application.event_listener)        
-        MouseListener.__init__(self, application.event_listener)
-        CommandListener.__init__(self, application.event_listener)
-        FifeMode.__init__(self)
-        self.engine = engine
-        self.event_manager = engine.getEventManager()
-        self.view = view
-        self.model = model
-        self.application = application
-        
-    def pause(self, paused):
-        """Stops receiving events"""
-        if paused:
-            KeyListener.detach(self)
-            MouseListener.detach(self)
-        else:
-            KeyListener.attach(self, self.application.event_listener)
-            MouseListener.attach(self, self.application.event_listener)
-    
-    def setMouseCursor(self, image, dummy_image, mc_type="native"): 
-        """Set the mouse cursor to an image.
-           @type image: string
-           @param image: The image you want to set the cursor to
-           @type dummy_image: string
-           @param dummy_image: ???
-           @type type: string
-           @param type: ???
-           @return: None"""
-        cursor = self.engine.getCursor()
-        img_manager = self.engine.getImageManager()
-        if(mc_type == "target"):
-            target_cursor_id = img_manager.load(image)  
-            dummy_cursor_id = img_manager.load(dummy_image)
-            cursor.set(dummy_cursor_id)
-            cursor.setDrag(target_cursor_id, -16, -16)
-        else:
-            cursor_type = fife.CURSOR_IMAGE
-            zero_cursor_id = img_manager.load(image)
-            cursor.set(zero_cursor_id)
-            cursor.setDrag(zero_cursor_id)
-
-    def resetMouseCursor(self):
-        """Reset cursor to default image.
-           @return: None"""
-        image =  '/'.join(['gui/cursors/',
-                           self.model.settings.parpg.CursorDefault])
-        self.setMouseCursor(image, image)
-    
-    def pump(self, dt):
-        pass
--- a/src/parpg/dialogue.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +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 <http://www.gnu.org/licenses/>.
-"""
-Provides classes used to contain and organize dialogue data for use within
-in-game dialogues between the player character and NPCs.
-"""
-try:
-    from collections import OrderedDict
-except ImportError:
-    # Python version 2.4-2.6 doesn't have the OrderedDict
-    from parpg.common.ordereddict import OrderedDict
-
-class Dialogue(object):
-    """
-    Represents a complete dialogue and acts as a container for the dialogue
-    data belonging to a particular NPC.
-    """
-    __slots__ = ['npc_name', 'avatar_path', 'default_greeting',
-                 'greetings', 'sections']
-    
-    def __init__(self, npc_name, avatar_path, default_greeting, greetings=None,
-                 sections=None):
-        """
-        Initialize a new L{Dialogue} instance.
-        
-        @param npc_name: name displayed for the NPC in the dialogue.
-        @type npc_name: basestring
-        @param avatar_path: path to the image that should be displayed as the
-            NPC's avatar.
-        @type avatar_path: basestring
-        @param default_greeting: section of dialogue that should be
-            displayed when the dialogue is first initiated and no other start
-            sections are available.
-        @type default_greeting: L{DialogueSection}
-        @param greetings: sections of dialogue defining the conditions
-            under which each should be displayed when the dialogue is first
-            initiated.
-        @type greetings: list of 
-            L{RootDialogueSections<DialogueGreeting>}
-        @param sections: sections of dialogue that make up this
-            L{Dialogue} instance.
-        @type sections: list of L{DialogueSections<DialogueSection>}
-        """
-        self.npc_name = npc_name
-        self.avatar_path = avatar_path
-        self.default_greeting = default_greeting
-        self.greetings = greetings if greetings is not None else []
-        self.sections = OrderedDict()
-        all_sections = [default_greeting]
-        if (greetings is not None):
-            all_sections += greetings
-        if (sections is not None):
-            all_sections += sections
-        if (__debug__):
-            section_ids = [section.id for section in all_sections]
-        for section in all_sections:
-            # Sanity check: All DialogueResponses should have next_section_id
-            # attributes that refer to valid DialogueSections in the Dialogue.
-            if (__debug__):
-                for response in section.responses:
-                    assert response.next_section_id in section_ids + \
-                        ['end', 'back'], ('"{0}" does not refer to a ' 
-                                          'DialogueSection in this Dialogue')\
-                        .format(response.next_section_id)
-            self.sections[section.id] = section
-    
-    def __str__(self):
-        """Return the string representation of a L{Dialogue} instance."""
-        string_representation = 'Dialogue(npc_id={0.npc_name})'.format(self)
-        return string_representation
-
-
-class DialogueNode(object):
-    """
-    Abstract base class that represents a node or related group of attributes
-    within a Dialogue.
-    """
-    def __init__(self, text, actions=None):
-        """
-        Initialize a new L{DialogueNode} instance.
-        
-        @param text: textual content of the L{DialogueNode}.
-        @type text: basestring
-        @param actions: dialogue actions associated with the L{DialogueNode}.
-        @type actions: list of L{DialogueActions<DialogueAction>}
-        """
-        self.text = text
-        self.actions = actions or []
-
-
-class DialogueSection(DialogueNode):
-    """DialogueNode that represents a distinct section of the dialogue."""
-    __slots__ = ['id', 'text', 'responses', 'actions']
-    
-    def __init__(self, id_, text, responses=None, actions=None):
-        """
-        Initialize a new L{DialogueSection} instance.
-        
-        @param id_: named used to uniquely identify the L{DialogueSection}
-            within a L{Dialogue}.
-        @type id_: basestring
-        @param text: text displayed as the NPC's part of the L{Dialogue}.
-        @type text: basestring
-        @param responses: possible responses that the player can choose from.
-        @type responses: list of L{DialogueResponses<DialogueResponse>}
-        @param actions: dialogue actions that should be executed when the
-            L{DialogueSection} is reached.
-        @type actions: list of L{DialogueActions<DialogueAction>}
-        """
-        DialogueNode.__init__(self, text=text, actions=actions)
-        self.id = id_
-        if (responses is not None):
-            self.responses = list(responses)
-
-
-class DialogueGreeting(DialogueSection):
-    """
-    Represents a root section of dialogue in a L{Dialogue} along with the
-    conditional statement used to determine the whether this section should be
-    displayed first upon dialogue initiation.
-    
-    @ivar id: Name used to uniquely identify the L{DialogueSection} to which
-        the L{DialogueRootSectionReference} points.
-    @type id: basestring
-    @ivar condition: Boolean Python expression used to determine if the
-        L{DialogueSection} referenced is a valid starting section.
-    @type condition: basestring
-    """
-    __slots__ = ['id', 'condition', 'text', 'actions', 'responses']
-    
-    def __init__(self, id_, condition, text, responses=None, actions=None):
-        """
-        Initialize a new L{DialogueGreeting} instance.
-        
-        @param id_: named used to uniquely identify the L{DialogueSection}
-            within a L{Dialogue}.
-        @type id_: basestring
-        @param condition: Boolean Python expression used to determine if this
-            root dialogue section should be displayed.
-        @type condition: basestring
-        @param text: text displayed as the NPC's part of the L{Dialogue}.
-        @type text: basestring
-        @param responses: possible responses that the player can choose from.
-        @type responses: list of L{DialogueResponses<DialogueResponse>}
-        @param actions: dialogue actions that should be executed when the
-            L{DialogueSection} is reached.
-        @type actions: list of L{DialogueActions<DialogueAction>}
-        """
-        DialogueSection.__init__(self, id_=id_, text=text, responses=responses,
-                                 actions=actions)
-        self.condition = condition
-
-
-class DialogueResponse(DialogueNode):
-    """
-    L{DialogueNode} that represents one possible player response to a
-    particular L{DialogueSection}.
-    """
-    __slots__ = ['text', 'actions', 'condition', 'next_section_id']
-    
-    def __init__(self, text, next_section_id, actions=None, condition=None):
-        """
-        Initialize a new L{DialogueResponse} instance.
-        
-        @param text: text displayed as the content of the player's response.
-        @type text: basestring
-        @param next_section_id: ID of the L{DialogueSection} that should be
-            jumped to if this response is chosen by the player.
-        @type next_section_id: basestring
-        @param actions: dialogue actions that should be executed if this
-            response is chosen by the player.
-        @type actions: list of L{DialogueActions<DialogueAction>}
-        @param condition: Python expression that when evaluated determines
-            whether the L{DialogueResponse} should be displayed to the player
-            as a valid response.
-        @type condition: basestring
-        """
-        DialogueNode.__init__(self, text=text, actions=actions)
-        self.condition = condition
-        self.next_section_id = next_section_id
--- a/src/parpg/dialogueactions.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,410 +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 <http://www.gnu.org/licenses/>.
-"""
-Provides classes used to implement dialogue logic and allow dialogues to have
-external effects on the game state.
-"""
-import logging
-
-from parpg.components import container
-
-logger = logging.getLogger('dialogueaction')
-
-class DialogueAction(object):
-    """
-    Abstract base class for subclasses that represent dialogue actions embedded
-    within a DialogueSection or DialogueResponse.
-    
-    Subclasses must define the keyword class variable and implement both the
-    __init__ and __call__ methods.
-    
-    @cvar keyword: keyword used by the L{DialogueParser} to recognize the
-        L{DialogueAction} in serialized L{Dialogues<Dialogues>}.
-    @type keyword: basestring
-    """
-    logger = logging.getLogger('dialogueaction.DialogueAction')
-    registered_actions = {}
-    
-    @classmethod
-    def registerAction(cls, dialogue_action_type):
-        """
-        Register a L{DialogueAction} subclass for easy reference.
-        
-        @param dialogue_action_type: dialogue action to register.
-        @type dialogue_action_type: L{DialogueAction} subclass
-        """
-        cls.registered_actions[dialogue_action_type.keyword] = \
-            dialogue_action_type
-    
-    def __init__(self, *args, **kwargs):
-        """
-        Initialize a new L{DialogueAction} instance.
-        
-        @param args: positional arguments passed by the L{DialogueParser} after
-            reading a serialized L{Dialogue}.
-        @type args: list of objects
-        @param kwargs: keyword arguments passed by the L{DialogueParser} after
-            reading a serialized L{Dialogue}.
-        @type kwargs: dict of objects
-        """
-        if (not hasattr(type(self), 'keyword')):
-            raise AttributeError('DialogueAction subclasses must define the '
-                                 'keyword class variable.')
-        self.arguments = (args, kwargs)
-    
-    def __call__(self, game_state):
-        """
-        Execute the L{DialogueAction}.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        raise NotImplementedError('subclasses of DialogueAction must '
-                                  'override __call__')
-
-
-class MeetAction(DialogueAction):
-    """
-    L{DialogueAction} that adds an NPC to the list of NPCs known by the player.
-    """
-    keyword = 'meet'
-    
-    def __init__(self, *args, **kwargs):
-        """
-        Initialize a new L{MeetAction} instance.
-        
-        @param args: positional arguments.
-        @type args: list of objects
-        @param npc_id: identifier of the NPC that the player has met.
-        @type npc_id: basestring
-        @param kwargs: keyword arguments (not used).
-        @type kwargs: dict of objects
-        """
-        DialogueAction.__init__(self, *args, **kwargs)
-    
-    def __call__(self, game_state):
-        """
-        Add an NPC to the list of NPCs known by the player.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        npc_id = game_state["npc"].general.identifier
-        # NOTE Technomage 2010-11-13: This print statement seems overly
-        #     verbose, so I'm logging it as an INFO message instead.
-#        print("You've met {0}!".format(npc_id))
-        self.logger.info("You've met {0}!".format(npc_id))
-        game_state['meet'](npc_id)
-DialogueAction.registerAction(MeetAction)
-
-
-class InventoryAction(DialogueAction):
-    """
-    Abstract base class for L{DialogueActions<DialogueAction>} used to
-    manipulate the NPC's and the player's inventory.
-    """
-    def __init__(self, *args, **kwargs):
-        """
-        Initialize a new L{InventoryAction} instance.
-        
-        @param args: positional arguments.
-        @type args: list of objects
-        @param item_types: item types that should be manipulated.
-        @type item_types: list of basestrings
-        @param kwargs: keyword arguments.
-        @type kwargs: dict of objects
-        """
-        DialogueAction.__init__(self, *args, **kwargs)
-        self.item_types = args
-
-
-class TakeStuffAction(InventoryAction):
-    """
-    L{InventoryAction} used to move items from the NPC's inventory to the
-    player's inventory.
-    """
-    keyword = 'take_stuff'
-    
-    def __call__(self, game_state):
-        """
-        Move items from the NPC's inventory to the player's inventory.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        item_types = self.item_types
-        for item_type in item_types:            
-            item = container.take_item(game_state['npc'].container, item_type)
-            if (item):
-                container.put_item(game_state['pc'].container, item)
-                print("{0} gave you the {1}".format(game_state['npc'].
-                                                    description.view_name,
-                                                    item_type))
-            else:
-                print("{0} doesn't have the {1}".format(game_state['npc'].
-                                                        description.view_name,
-                                                        item_type))
-DialogueAction.registerAction(TakeStuffAction)
-
-
-class GiveStuffAction(InventoryAction):
-    """
-    L{InventoryAction} used to move items from the player's inventory to the
-    NPC's inventory.
-    """
-    keyword = 'give_stuff'
-    
-    def __call__(self, game_state):
-        """
-        Move items from the player's inventory to the NPC's inventory.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        item_types = self.item_types
-        for item_type in item_types:
-            item = container.take_item(game_state['pc'].container, item_type)
-            if (item):
-                container.put_item(game_state['npc'].container, item)
-                print("You give the {0} to {1}".format(item_type,
-                                                       game_state['npc'].
-                                                       description.view_name))
-            else:
-                print("You don't have the {0}".format(item_type))
-DialogueAction.registerAction(GiveStuffAction)
-
-
-class ReplaceItemAction(InventoryAction):
-    """
-    L{InventoryAction} used to replace an item with another in the player's
-    inventory.
-    """
-    
-    keyword = 'replace_item'
-    
-    def __call__(self, game_state):
-        """
-        Take an item from the player and place another at its place.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        old_type = self.item_types[0]
-        new_type = self.item_types[1]
-        item = container.take_item(game_state['pc'].container, old_type)
-        if item:
-            model = game_state['model']
-            new_item = model.createItemByType(new_type, new_type, 
-                                              item.entity.world)
-            container.put_item(game_state['pc'].container, 
-                               new_item.containable, item.slot)
-            model.deleteObject(item.entity.general.identifier)
-            item.delete()
-            print("{0} took the {1} and gave you the {2}".format(
-                game_state['npc'].description.view_name, old_type, item_type))
-        else:
-            print("You don't have the {0}".format(old_type))
-DialogueAction.registerAction(ReplaceItemAction)
-        
-class QuestAction(DialogueAction):
-    """
-    Abstract base class for quest-related L{DialogueActions<DialogueAction>}.
-    """
-    def __init__(self, *args, **kwargs):
-        """
-        Initialize a new L{QuestAction} instance.
-        
-        @param args: positional arguments.
-        @type args: list of objects
-        @param quest_id: ID of the quest to manipulate.
-        @type quest_id: basestring
-        @param kwargs: keyword arguments (not used).
-        @type kwargs: dict of objects
-        """
-        DialogueAction.__init__(self, *args, **kwargs)
-        self.quest_id = kwargs['quest'] if 'quest' in kwargs else args[0]
-
-
-class StartQuestAction(QuestAction):
-    """L{QuestAction} used to activate a quest."""
-    keyword = 'start_quest'
-    
-    def __call__(self, game_state):
-        """
-        Activate a quest.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        quest_id = self.quest_id
-        print("You've picked up the \"{0}\" quest!".format(quest_id))
-        game_state['quest'].activateQuest(quest_id)
-DialogueAction.registerAction(StartQuestAction)
-
-
-class CompleteQuestAction(QuestAction):
-    """
-    L{QuestAction} used to mark a quest as successfully finished/completed.
-    """
-    keyword = 'complete_quest'
-    
-    def __call__(self, game_state):
-        """
-        Successfully complete a quest.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        quest_id = self.quest_id
-        print("You've finished the \"{0}\" quest".format(quest_id))
-        game_state['quest'].finishQuest(quest_id)
-DialogueAction.registerAction(CompleteQuestAction)
-
-
-class FailQuestAction(QuestAction):
-    """L{QuestAction} used to fail an active quest."""
-    keyword = 'fail_quest'
-    
-    def __call__(self, game_state):
-        """
-        Fail an active quest.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        quest_id = self.quest_id
-        print("You've failed the \"{0}\" quest".format(quest_id))
-        game_state['quest'].failQuest(quest_id)
-DialogueAction.registerAction(FailQuestAction)
-
-
-class RestartQuestAction(QuestAction):
-    """L{QuestAction} used to restart an active quest."""
-    keyword = 'restart_quest'
-    
-    def __call__(self, game_state):
-        """
-        Restart an active quest.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        quest_id = self.quest_id
-        print("You've restarted the \"{0}\" quest".format(quest_id))
-        game_state['quest'].restartQuest(quest_id)
-DialogueAction.registerAction(RestartQuestAction)
-
-
-class QuestVariableAction(QuestAction):
-    """
-    Base class for L{QuestActions<QuestAction>} that modify quest
-    variables.
-    """
-    def __init__(self, *args, **kwargs):
-        """
-        Initialize a new L{QuestVariableAction} instance.
-        
-        @param args: positional arguments (not used).
-        @type args: list of objects
-        @param kwargs: keyword arguments.
-        @type kwargs: dict of objects
-        @keyword quest: ID of the quest whose variable should be modified.
-        @type quest: basestring
-        @keyword variable: name of the quest variable to modify.
-        @type variable: basestring
-        @keyword value: new value that should be used to modify the quest
-            variable.
-        @type value: object
-        """
-        QuestAction.__init__(self, *args, **kwargs)
-        self.variable_name = kwargs['variable']
-        self.value = kwargs['value']
-
-
-class IncreaseQuestVariableAction(QuestVariableAction):
-    """
-    L{QuestVariableAction} used to increase the value of a quest variable by a
-    set amount.
-    """
-    keyword = 'increase_quest_variable'
-    
-    def __call__(self, game_state):
-        """
-        Increase a quest variable by a set amount.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        quest_id = self.quest_id
-        variable_name = self.variable_name
-        value = self.value
-        print('Increased {0} by {1}'.format(variable_name, value))
-        game_state['quest'][quest_id].increaseValue(variable_name, value)
-DialogueAction.registerAction(IncreaseQuestVariableAction)
-
-
-class DecreaseQuestVariableAction(QuestVariableAction):
-    """
-    L{QuestVariableAction} used to decrease the value of a quest variable by a
-    set amount.
-    """
-    keyword = 'decrease_quest_variable'
-    
-    def __call__(self, game_state):
-        """
-        Decrease a quest variable by a set amount.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        quest_id = self.quest_id
-        variable_name = self.variable_name
-        value = self.value
-        print('Decreased {0} by {1}'.format(variable_name, value))
-        game_state['quest'][quest_id].decreaseValue(variable_name, value)
-DialogueAction.registerAction(DecreaseQuestVariableAction)
-
-
-class SetQuestVariableAction(QuestVariableAction):
-    """
-    L{QuestVariableAction} used to set the value of a quest variable.
-    """
-    keyword = 'set_quest_variable'
-    
-    def __call__(self, game_state):
-        """
-        Set the value of a quest variable.
-        
-        @param game_state: variables and functions that make up the current
-            game state.
-        @type game_state: dict of objects
-        """
-        quest_id = self.quest_id
-        variable_name = self.variable_name
-        value = self.value
-        print('Set {0} to {1}'.format(variable_name, value))
-        game_state['quest'][quest_id].setValue(variable_name, value)
-DialogueAction.registerAction(SetQuestVariableAction)
--- a/src/parpg/dialoguecontroller.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +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 <http://www.gnu.org/licenses/>.
-from controllerbase import ControllerBase
-
-class DialogueController(ControllerBase):
-    """Controller that takes over when a dialogue is started"""
-    def __init__(self, 
-                 engine, 
-                 view, 
-                 model, 
-                 application):
-        """
-        Constructor
-        @param engine: Instance of the active fife engine
-        @type engine: fife.Engine
-        @param view: Instance of a GameSceneView
-        @param type: parpg.GameSceneView
-        @param model: The model that has the current gamestate
-        @type model: parpg.GameModel
-        @param application: The application that created this controller
-        @type application: parpg.PARPGApplication
-        @param settings: The current settings of the application
-        @type settings: fife.extensions.fife_settings.Setting
-        """
-        super(DialogueController, self).__init__(engine,
-                                                  view,
-                                                  model,
-                                                  application)
-        self.dialogue = None
-        self.view = view
-        
-    def startTalk(self, npc):
-        if npc.dialogue is not None:
-            self.model.active_map.centerCameraOnPlayer()            
-            npc.fifeagent.behaviour.talk(
-                self.model.game_state.\
-                getObjectById("PlayerCharacter").fifeagent
-            )
-            self.dialogue = self.view.hud.showDialogue(npc)
-            self.dialogue.initiateDialogue()
-            self.model.pause(True)
-            self.view.hud.enabled = False
-
-            
-    def pump(self, dt):
-        ControllerBase.pump(self, dt)
-        if self.dialogue and not self.dialogue.active:
-            self.application.manager.pop_mode()
-            self.model.pause(False)
-            self.view.hud.enabled = True
-            
--- a/src/parpg/dialogueparsers.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,666 +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 <http://www.gnu.org/licenses/>.
-"""
-Contains classes for parsing and validating L{Dialogues<Dialogue>} and other
-dialogue-related data.
-
-@TODO Technomage 2010-11-13: Exception handling + validation needs work.
-    Currently YAML files are only crudely validated - the code assumes that
-    the file contains valid dialogue data, and if that assumption is
-    violated and causes the code to raise any TypeErrors, AttributeErrors or
-    ValueErrors the code then raises a DialogueFormatError with the
-    original (and mostly unhelpful) error message.
-@TODO Technomage 2010-11-13: Support reading and writing unicode.
-"""
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
-from collections import Sequence
-try:
-    from collections import OrderedDict
-except ImportError:
-    # Python version 2.4-2.6 doesn't have the OrderedDict
-    from parpg.common.ordereddict import OrderedDict
-import re
-import textwrap
-
-import yaml
-
-from parpg import COPYRIGHT_HEADER
-from parpg.dialogue import (Dialogue, DialogueSection, DialogueResponse,
-    DialogueGreeting)
-from parpg.dialogueactions import DialogueAction
-
-import logging
-logger = logging.getLogger('dialogueparser')
-
-class DialogueFormatError(Exception):
-    """Exception thrown when the DialogueParser has encountered an error."""
-
-
-class AbstractDialogueParser(object):
-    """
-    Abstract base class defining the interface for parsers responsible for
-    constructing a L{Dialogue} from its serialized representation.
-    """
-    def load(self, stream):
-        """
-        Parse a stream and attempt to construct a new L{Dialogue} instance from
-        its serialized representation.
-        
-        @param stream: open stream containing the serialized representation of
-            a Dialogue.
-        @type stream: BufferType
-        """
-        raise NotImplementedError('AbstractDialogueParser subclasses must '
-                                  'override the load method.')
-    
-    def dump(self, dialogue, stream):
-        """
-        Serialize a L{Dialogue} instance and dump it to an open stream.
-        
-        @param dialogue: dialogue to serialize.
-        @type dialogue: L{Dialogue}
-        @param stream: open stream into which the serialized L{Dialogue} should
-            be dumped.
-        @type stream: BufferType
-        """
-        raise NotImplementedError('AbstractDialogueParser subclasses must '
-                                  'override the dump method.')
-    
-    def validate(self, stream):
-        """
-        Parse a stream and verify that it contains a valid serialization of a
-        L{Dialogue instance}.
-        
-        @param stream: stream containing the serialized representation of a
-            L{Dialogue}
-        @type stream: BufferType
-        """
-        raise NotImplementedError('AbstractDialogueParser subclasses must '
-                                  'override the validate method.')
-
-
-class YamlDialogueParser(AbstractDialogueParser):
-    """
-    L{AbstractDialogueParser} subclass responsible for parsing dialogues
-    serialized in YAML.
-    """
-    logger = logging.getLogger('dialogueparser.OldYamlDialogueParser')
-    
-    def load(self, stream, loader_class=yaml.Loader):
-        """
-        Parse a YAML stream and attempt to construct a new L{Dialogue}
-        instance.
-        
-        @param stream: stream containing the serialized YAML representation of
-            a L{Dialogue}.
-        @type stream: BufferType
-        @param loader_class: PyYAML loader class to use for reading the
-            serialization.
-        @type loader_class: yaml.BaseLoader subclass
-        """
-        loader = loader_class(stream)
-        dialogue = self._constructDialogue(loader, loader.get_single_node())
-        return dialogue
-    
-    def dump(self, dialogue, output_stream, dumper_class=yaml.Dumper):
-        """
-        Serialize a L{Dialogue} instance as YAML and dump it to an open stream.
-        
-        @param dialogue: dialogue to serialize.
-        @type dialogue: L{Dialogue}
-        @param stream: open stream into which the serialized L{Dialogue} should
-            be dumped.
-        @type stream: BufferType
-        @param dumper_class: PyYAML dumper class to use for formatting the
-            serialization.
-        @type dumper_class: yaml.BaseDumper subclass
-        """
-        intermediate_stream = StringIO()
-        # KLUDE Technomage 2010-11-16: The "width" argument seems to be broken,
-        #     as it doesn't take into about current line indentation and fails
-        #     to correctly wrap at word boundaries.
-        dumper = dumper_class(intermediate_stream, default_flow_style=False,
-                              indent=4, width=99999, line_break='\n',
-                              allow_unicode=True, explicit_start=True,
-                              explicit_end=True, tags=False)
-        dialogue_node = self._representDialogue(dumper, dialogue)
-        dumper.open()
-        dumper.serialize(dialogue_node)
-        dumper.close()
-        file_contents = intermediate_stream.getvalue()
-        
-        file_contents = re.sub(r'(\n|\r|\r\n)(\s*)(GOTO: .*)', r'\1\2\3\1\2',
-                               file_contents)
-        lines = file_contents.splitlines()
-        max_line_length = 76 # 79 - 3 chars for escaping newlines
-        for i in range(len(lines)):
-            line = lines[i]
-            match = re.match(
-                r'^(\s*(?:-\s+)?)(SAY|REPLY|CONDITION):\s+"(.*)"$',
-                line
-            )
-            if (match and len(line) > max_line_length):
-                # Wrap long lines for readability.
-                initial_indent = len(match.group(1))
-                subsequent_indent = initial_indent + 4
-                text_wrapper = textwrap.TextWrapper(
-                    max_line_length,
-                    subsequent_indent=' ' * subsequent_indent,
-                    break_long_words=False,
-                    break_on_hyphens=False
-                )
-                new_lines = text_wrapper.wrap(line)
-                new_lines = (
-                    new_lines[:1] + [re.sub(r'^(\s*) (.*)$', r'\1\ \2', l)
-                                     for l in new_lines[1:]]
-                )
-                lines[i] = '\\\n'.join(new_lines)
-        
-        output_stream.write(COPYRIGHT_HEADER)
-        output_stream.write('\n'.join(lines))
-        
-    
-    def _representDialogue(self, dumper, dialogue):
-        dialogue_node = dumper.represent_dict({})
-        dialogue_dict = OrderedDict()
-        dialogue_dict['NPC_NAME'] = dialogue.npc_name
-        dialogue_dict['AVATAR_PATH'] = dialogue.avatar_path
-        dialogue_dict['DEFAULT_GREETING'] = \
-            self._representDialogueSection(dumper,
-                                           dialogue.default_greeting)
-        # NOTE Technomage 2010-11-16: Dialogue stores its sections in an
-        #     OrderedDict, so a round-trip load, dump, and load will preserve
-        #     the order of DialogueSections.
-        if (len(dialogue.greetings) > 0):
-            greetings_list_node = dumper.represent_list([])
-            greetings_list = greetings_list_node.value
-            for greeting in dialogue.greetings:
-                greeting_node = \
-                    self._representRootDialogueSection(dumper, greeting)
-                greetings_list.append(greeting_node)
-            dialogue_dict['GREETINGS'] = greetings_list_node
-        if (len(dialogue.setions) > 0):
-            sections_list_node = dumper.represent_list([])
-            sections_list = sections_list_node.value
-            for section in dialogue.sections.values():
-                section_node = self._representDialogueSection(dumper, section)
-                sections_list.append(section_node)
-            dialogue_dict['SECTIONS'] = sections_list_node
-        
-        for key, value in dialogue_dict.items():
-            if (isinstance(key, yaml.Node)):
-                key_node = key
-            else:
-                key_node = dumper.represent_data(key)
-            if (isinstance(value, yaml.Node)):
-                value_node = value
-            else:
-                value_node = dumper.represent_data(value)
-            dialogue_node.value.append((key_node, value_node))
-        return dialogue_node
-    
-    def _representRootDialogueSection(self, dumper, greeting):
-        greeting_node = dumper.represent_dict({})
-        greeting_dict = OrderedDict()
-        greeting_dict['ID'] = greeting.id
-        greeting_dict['CONDITION'] = dumper.represent_scalar(
-            'tag:yaml.org,2002:str',
-            greeting.condition,
-            style='"'
-        )
-        for key, value in greeting_dict.items():
-            if (isinstance(key, yaml.Node)):
-                key_node = key
-            else:
-                key_node = dumper.represent_data(key)
-            if (isinstance(value, yaml.Node)):
-                value_node = value
-            else:
-                value_node = dumper.represent_data(value)
-            greeting_node.value.append((key_node, value_node))
-        return greeting_node
-    
-    def _representDialogueSection(self, dumper, dialogue_section):
-        section_node = dumper.represent_dict({})
-        section_dict = OrderedDict() # OrderedDict is required to preserve
-                                     # the order of attributes.
-        section_dict['ID'] = dialogue_section.id
-        # KLUDGE Technomage 2010-11-16: Hard-coding the tag like this could be
-        #     a problem when writing unicode.
-        section_dict['SAY'] = dumper.represent_scalar('tag:yaml.org,2002:str',
-                                                      dialogue_section.text,
-                                                      style='"')
-        actions_list_node = dumper.represent_list([])
-        actions_list = actions_list_node.value
-        for action in dialogue_section.actions:
-            action_node = self._representDialogueAction(dumper, action)
-            actions_list.append(action_node)
-        if (actions_list):
-            section_dict['ACTIONS'] = actions_list_node
-        responses_list_node = dumper.represent_list([])
-        responses_list = responses_list_node.value
-        for response in dialogue_section.responses:
-            response_node = self._representDialogueResponse(dumper, response)
-            responses_list.append(response_node)
-        section_dict['RESPONSES'] = responses_list_node
-        
-        for key, value in section_dict.items():
-            if (isinstance(key, yaml.Node)):
-                key_node = key
-            else:
-                key_node = dumper.represent_data(key)
-            if (isinstance(value, yaml.Node)):
-                value_node = value
-            else:
-                value_node = dumper.represent_data(value)
-            section_node.value.append((key_node, value_node))
-        return section_node
-    
-    def _representDialogueResponse(self, dumper, dialogue_response):
-        response_node = dumper.represent_dict({})
-        response_dict = OrderedDict()
-        # KLUDGE Technomage 2010-11-16: Hard-coding the tag like this could be
-        #     a problem when writing unicode.
-        response_dict['REPLY'] = dumper.represent_scalar(
-            'tag:yaml.org,2002:str',
-            dialogue_response.text,
-            style='"')
-        if (dialogue_response.condition is not None):
-            response_dict['CONDITION']  = dumper.represent_scalar(
-                'tag:yaml.org,2002:str',
-                dialogue_response.condition,
-                style='"'
-            )
-        actions_list_node = dumper.represent_list([])
-        actions_list = actions_list_node.value
-        for action in dialogue_response.actions:
-            action_node = self._representDialogueAction(dumper, action)
-            actions_list.append(action_node)
-        if (actions_list):
-            response_dict['ACTIONS'] = actions_list_node
-        response_dict['GOTO'] = dialogue_response.next_section_id
-        
-        for key, value in response_dict.items():
-            if (isinstance(key, yaml.Node)):
-                key_node = key
-            else:
-                key_node = dumper.represent_data(key)
-            if (isinstance(value, yaml.Node)):
-                value_node = value
-            else:
-                value_node = dumper.represent_data(value)
-            response_node.value.append((key_node, value_node))
-        return response_node
-    
-    def _representDialogueAction(self, dumper, dialogue_action):
-        action_node = dumper.represent_dict({})
-        action_dict = OrderedDict()
-        args, kwargs = dialogue_action.arguments
-        if (args and not kwargs):
-            arguments = list(args)
-        elif (kwargs and not args):
-            arguments = kwargs
-        else:
-            arguments = [list(args), kwargs]
-        action_dict[dialogue_action.keyword] = arguments
-        
-        for key, value in action_dict.items():
-            if (isinstance(key, yaml.Node)):
-                key_node = key
-            else:
-                key_node = dumper.represent_data(key)
-            if (isinstance(value, yaml.Node)):
-                value_node = value
-            else:
-                value_node = dumper.represent_data(value)
-            action_node.value.append((key_node, value_node))
-        return action_node
-    
-    def _constructDialogue(self, loader, yaml_node):
-        npc_name = None
-        avatar_path = None
-        default_greeting = None
-        greetings = []
-        sections = []
-        
-        try:
-            for key_node, value_node in yaml_node.value:
-                key = key_node.value
-                if (key == u'NPC_NAME'):
-                    npc_name = loader.construct_object(value_node)
-                elif (key == u'AVATAR_PATH'):
-                    avatar_path = loader.construct_object(value_node)
-                elif (key == u'DEFAULT_GREETING'):
-                    default_greeting = \
-                        self._constructDialogueSection(loader, value_node)
-                elif (key == u'GREETINGS'):
-                    for greeting_node in value_node.value:
-                        greeting = self._constructRootDialogueSection(
-                                loader,
-                                greeting_node
-                        )
-                        greetings.append(
-                            greeting
-                        )
-                elif (key == u'SECTIONS'):
-                    for section_node in value_node.value:
-                        dialogue_section = self._constructDialogueSection(
-                            loader,
-                            section_node
-                        )
-                        sections.append(dialogue_section)
-        except (AttributeError, TypeError, ValueError,
-                yaml.scanner.ScannerError) as error:
-            raise DialogueFormatError(error)
-        
-        dialogue = Dialogue(npc_name=npc_name, avatar_path=avatar_path,
-                            default_greeting=default_greeting,
-                            greetings=greetings,
-                            sections=sections)
-        return dialogue
-    
-    def _constructRootDialogueSection(self, loader, greeting_node):
-        id = None
-        text = None
-        condition = None
-        responses = []
-        actions = []
-        greeting = None
-        
-        try:
-            for key_node, value_node in greeting_node.value:
-                key = key_node.value
-                if (key == u'ID'):
-                    id = loader.construct_object(value_node)
-                elif (key == u'SAY'):
-                    text = loader.construct_object(value_node)
-                elif (key == u'CONDITION'):
-                    condition = loader.construct_object(value_node)
-                elif (key == u'RESPONSES'):
-                    for response_node in value_node.value:
-                        dialogue_response = self._constructDialogueResponse(
-                            loader,
-                            response_node
-                        )
-                        responses.append(dialogue_response)
-                elif (key == u'ACTIONS'):
-                    for action_node in value_node.value:
-                        action = self._constructDialogueAction(loader,
-                                                             action_node)
-                        actions.append(action)
-        except (AttributeError, TypeError, ValueError) as e:
-            raise DialogueFormatError(e)
-        else:
-            greeting = DialogueSection(id=id, text=text,
-                                           condition=condition,
-                                           responses=responses,
-                                           actions=actions)
-        
-        return greeting
-    
-    def _constructDialogueSection(self, loader, section_node):
-        id_ = None
-        text = None
-        responses = []
-        actions = []
-        dialogue_section = None
-        
-        try:
-            for key_node, value_node in section_node.value:
-                key = key_node.value
-                if (key == u'ID'):
-                    id_ = loader.construct_object(value_node)
-                elif (key == u'SAY'):
-                    text = loader.construct_object(value_node)
-                elif (key == u'RESPONSES'):
-                    for response_node in value_node.value:
-                        dialogue_response = self._constructDialogueResponse(
-                            loader,
-                            response_node
-                        )
-                        responses.append(dialogue_response)
-                elif (key == u'ACTIONS'):
-                    for action_node in value_node.value:
-                        action = self._constructDialogueAction(loader,
-                                                             action_node)
-                        actions.append(action)
-        except (AttributeError, TypeError, ValueError) as e:
-            raise DialogueFormatError(e)
-        else:
-            dialogue_section = DialogueSection(id_=id_, text=text,
-                                               responses=responses,
-                                               actions=actions)
-        
-        return dialogue_section
-    
-    def _constructDialogueResponse(self, loader, response_node):
-        text = None
-        next_section_id = None
-        actions = []
-        condition = None
-        
-        try:
-            for key_node, value_node in response_node.value:
-                key = key_node.value
-                if (key == u'REPLY'):
-                    text = loader.construct_object(value_node)
-                elif (key == u'ACTIONS'):
-                    for action_node in value_node.value:
-                        action = self._constructDialogueAction(loader,
-                                                             action_node)
-                        actions.append(action)
-                elif (key == u'CONDITION'):
-                    condition = loader.construct_object(value_node)
-                elif (key == u'GOTO'):
-                    next_section_id = loader.construct_object(value_node)
-        except (AttributeError, TypeError, ValueError) as e:
-            raise DialogueFormatError(e)
-        
-        dialogue_response = DialogueResponse(text=text,
-                                             next_section_id=next_section_id,
-                                             actions=actions,
-                                             condition=condition)
-        return dialogue_response
-    
-    def _constructDialogueAction(self, loader, action_node):
-        mapping = loader.construct_mapping(action_node, deep=True)
-        keyword, arguments = mapping.items()[0]
-        if (isinstance(arguments, dict)):
-            # Got a dictionary of keyword arguments.
-            args = ()
-            kwargs = arguments
-        elif (not isinstance(arguments, Sequence) or
-              isinstance(arguments, basestring)):
-            # Got a single positional argument.
-            args = (arguments,)
-            kwargs = {}
-        elif (not len(arguments) == 2 or not isinstance(arguments[1], dict)):
-            # Got a list of positional arguments.
-            args = arguments
-            kwargs = {}
-        else:
-            self.logger.error(
-                '{0} is an invalid DialogueAction argument'.format(arguments)
-            )
-            return None
-        
-        action_type = DialogueAction.registered_actions.get(keyword)
-        if (action_type is None):
-            self.logger.error(
-                'no DialogueAction with keyword "{0}"'.format(keyword)
-            )
-            dialogue_action = None
-        else:
-            dialogue_action = action_type(*args, **kwargs)
-        return dialogue_action
-
-
-class OldYamlDialogueParser(YamlDialogueParser):
-    """
-    L{YAMLDialogueParser} that can read and write dialogues in the old
-    Techdemo1 dialogue file format.
-    
-    @warning: This class is deprecated and likely to be removed in a future
-        version.
-    """
-    logger = logging.getLogger('dialogueparser.OldYamlDialogueParser')
-    
-    def __init__(self):
-        self.response_actions = {}
-    
-    def load(self, stream):
-        dialogue = YamlDialogueParser.load(self, stream)
-        # Place all DialogueActions that were in DialogueSections into the
-        # DialogueResponse that led to the action's original section.
-        for section in dialogue.sections.values():
-            for response in section.responses:
-                actions = self.response_actions.get(response.next_section_id)
-                if (actions is not None):
-                    response.actions = actions
-        return dialogue
-    
-    def _constructDialogue(self, loader, yaml_node):
-        npc_name = None
-        avatar_path = None
-        start_section_id = None
-        sections = []
-        
-        try:
-            for key_node, value_node in yaml_node.value:
-                key = key_node.value
-                if (key == u'NPC'):
-                    npc_name = loader.construct_object(value_node)
-                elif (key == u'AVATAR'):
-                    avatar_path = loader.construct_object(value_node)
-                elif (key == u'START'):
-                    start_section_id = loader.construct_object(value_node)
-                elif (key == u'SECTIONS'):
-                    for id_node, section_node in value_node.value:
-                        dialogue_section = self._constructDialogueSection(
-                            loader,
-                            id_node,
-                            section_node
-                        )
-                        sections.append(dialogue_section)
-        except (AttributeError, TypeError, ValueError) as e:
-            raise DialogueFormatError(e)
-        
-        dialogue = Dialogue(npc_name=npc_name, avatar_path=avatar_path,
-                            start_section_id=start_section_id,
-                            sections=sections)
-        return dialogue
-    
-    def _constructDialogueSection(self, loader, id_node, section_node):
-        id = loader.construct_object(id_node)
-        text = None
-        responses = []
-        actions = []
-        dialogue_section = None
-        
-        try:
-            for node in section_node.value:
-                key_node, value_node = node.value[0]
-                key = key_node.value
-                if (key == u'say'):
-                    text = loader.construct_object(value_node)
-                elif (key == u'meet'):
-                    action = self._constructDialogueAction(loader, node)
-                    actions.append(action)
-                elif (key in [u'start_quest', u'complete_quest', u'fail_quest',
-                              u'restart_quest', u'set_value',
-                              u'decrease_value', u'increase_value',
-                              u'give_stuff', u'get_stuff']):
-                    action = self._constructDialogueAction(loader, node)
-                    if (id not in self.response_actions.keys()):
-                        self.response_actions[id] = []
-                    self.response_actions[id].append(action)
-                elif (key == u'responses'):
-                    for response_node in value_node.value:
-                        dialogue_response = self._constructDialogueResponse(
-                            loader,
-                            response_node
-                        )
-                        responses.append(dialogue_response)
-        except (AttributeError, TypeError, ValueError) as e:
-            raise DialogueFormatError(e)
-        else:
-            dialogue_section = DialogueSection(id=id, text=text,
-                                               responses=responses,
-                                               actions=actions)
-        
-        return dialogue_section
-    
-    def _constructDialogueResponse(self, loader, response_node):
-        text = None
-        next_section_id = None
-        actions = []
-        condition = None
-        
-        try:
-            text = loader.construct_object(response_node.value[0])
-            next_section_id = loader.construct_object(response_node.value[1])
-            if (len(response_node.value) == 3):
-                condition = loader.construct_object(response_node.value[2])
-        except (AttributeError, TypeError, ValueError) as e:
-            raise DialogueFormatError(e)
-        
-        dialogue_response = DialogueResponse(text=text,
-                                             next_section_id=next_section_id,
-                                             actions=actions,
-                                             condition=condition)
-        return dialogue_response
-    
-    def _constructDialogueAction(self, loader, action_node):
-        mapping = loader.construct_mapping(action_node, deep=True)
-        keyword, arguments = mapping.items()[0]
-        if (keyword == 'get_stuff'):
-            # Renamed keyword in new syntax.
-            keyword = 'take_stuff'
-        elif (keyword == 'set_value'):
-            keyword = 'set_quest_value'
-        elif (keyword == 'increase_value'):
-            keyword = 'increase_quest_value'
-        elif (keyword == 'decrease_value'):
-            keyword = 'decrease_quest_value'
-        if (isinstance(arguments, dict)):
-            # Got a dictionary of keyword arguments.
-            args = ()
-            kwargs = arguments
-        elif (not isinstance(arguments, Sequence) or
-              isinstance(arguments, basestring)):
-            # Got a single positional argument.
-            args = (arguments,)
-            kwargs = {}
-        elif (not len(arguments) == 2 or not isinstance(arguments[1], dict)):
-            # Got a list of positional arguments.
-            args = arguments
-            kwargs = {}
-        else:
-            self.logger.error(
-                '{0} is an invalid DialogueAction argument'.format(arguments)
-            )
-            return None
-        action_type = DialogueAction.registered_actions.get(keyword)
-        if (action_type is None):
-            self.logger.error(
-                'no DialogueAction with keyword "{0}"'.format(keyword)
-            )
-            dialogue_action = None
-        else:
-            dialogue_action = action_type(*args, **kwargs)
-        return dialogue_action
--- a/src/parpg/dialogueprocessor.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,378 +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 <http://www.gnu.org/licenses/>.
-"""
-Provides the core interface to the dialogue subsystem used to process player
-L{Dialogues<Dialogue>} with NPCs.
-"""
-import logging
-
-from parpg.common.utils import dedent_chomp
-
-if (__debug__):
-    from collections import Sequence, MutableMapping
-    from parpg.dialogue import Dialogue
-
-logger = logging.getLogger('dialogueprocessor')
-
-class DialogueProcessor(object):
-    """
-    Primary interface to the dialogue subsystem used to initiate and process a
-    L{Dialogue} with an NPC.
-    
-    To begin a dialogue with an NPC a L{DialogueProcessor} must first be
-    instantiated with the dialogue data to process and a dictionary of Python
-    objects defining the game state for testing of response conditionals. The
-    L{initiateDialogue} must be called to initialized the L{DialogueProcessor},
-    and once it is initialized processing of
-    L{DialogueSections<DialogueSection>} and
-    L{DialogueResponses<DialogueResponse>} can be initiated via the
-    L{continueDialogue} and L{reply} class methods.
-    
-    The state of dialogue processing is stored via the
-    L{dialogue_section_stack} class attribute, which stores a list of
-    L{DialogueSections<DialogueSection>} that have been or are currently being
-    processed. Each time L{reply} is called with a L{DialogueResponse} its
-    next_section_id attribute is used to select a new L{DialogueSection} from
-    the L{dialogue}. The selected L{DialogueSection} is then pushed
-    onto the end of the L{dialogue_section_stack}, ready to be processed via
-    L{continueDialogue}. The exception to this rule occurs when L{reply} is
-    called with a L{DialogueResponse} whose next_section_id attribute is "end"
-    or "back". "end" terminates the dialogue as described below, while "back"
-    removes the last L{DialogueSection} on the L{dialogue_section_stack}
-    effectively going back to the previous section of dialogue.
-    
-    The L{DialogueProcessor} terminates dialogue processing once L{reply} is
-    called with a L{DialogueResponse} whose next_section_id == 'end'.
-    Processing can also be manually terminated by calling the L{endDialogue}
-    class method.
-    
-    @note: See the dialogue_demo.py script for a complete example of how the
-        L{DialogueProcessor} can be used.
-    
-    @ivar dialogue: dialogue data currently being processed.
-    @type dialogue: L{Dialogue}
-    @ivar dialogue_section_stack: sections of dialogue that have been or are
-        currently being processed.
-    @type dialogue_section_stack: list of L{DialogueSections<DialogueSection>}
-    @ivar game_state: objects defining the game state that should be made
-        available for testing L{DialogueResponse} conditionals.
-    @type game_state: dict of Python objects
-    @ivar in_dialogue: whether a dialogue has been initiated.
-    @type in_dialogue: Bool
-    
-    Usage:
-    >>> game_state = {'pc': player_character, 'quest': quest_engine}
-    >>> dialogue_processor = DialogueProcessor(dialogue, game_state)
-    >>> dialogue_processor.initiateDialogue()
-    >>> while dialogue_processor.in_dialogue:
-    ...     valid_responses = dialogue_processor.continueDialogue()
-    ...     response = choose_response(valid_responses)
-    ...     dialogue_processor.reply(response)
-    """
-    _logger = logging.getLogger('dialogueengine.DialogueProcessor')
-    
-    def dialogue():
-        def fget(self):
-            return self._dialogue
-        
-        def fset(self, dialogue):
-            assert isinstance(dialogue, Dialogue), \
-                '{0} does not implement Dialogue interface'.format(dialogue)
-            self._dialogue = dialogue
-        
-        return locals()
-    dialogue = property(**dialogue())
-    
-    def dialogue_section_stack():
-        def fget(self):
-            return self._dialogue_section_stack
-        
-        def fset(self, new_value):
-            assert isinstance(new_value, Sequence) and not \
-                   isinstance(new_value, basestring), \
-                   'dialogue_section_stack must be a Sequence, not {0}'\
-                   .format(new_value)
-            self._dialogue_section_stack = new_value
-        
-        return locals()
-    dialogue_section_stack = property(**dialogue_section_stack())
-    
-    def game_state():
-        def fget(self):
-            return self._game_state
-        
-        def fset(self, new_value):
-            assert isinstance(new_value, MutableMapping),\
-                   'game_state must be a MutableMapping, not {0}'\
-                   .format(new_value)
-            self._game_state = new_value
-        
-        return locals()
-    game_state = property(**game_state())
-    
-    def in_dialogue():
-        def fget(self):
-            return self._in_dialogue
-        
-        def fset(self, value):
-            assert isinstance(value, bool), '{0} is not a bool'.format(value)
-            self._in_dialogue = value
-        
-        return locals()
-    in_dialogue = property(**in_dialogue())
-    
-    def __init__(self, dialogue, game_state):
-        """
-        Initialize a new L{DialogueProcessor} instance.
-        
-        @param dialogue: dialogue data to process.
-        @type dialogue: L{Dialogue}
-        @param game_state: objects defining the game state that should be made
-            available for testing L{DialogueResponse} conditions.
-        @type game_state: dict of objects
-        """
-        self._dialogue_section_stack = []
-        self._dialogue = dialogue
-        self._game_state = game_state
-        self._in_dialogue = False
-    
-    def getDialogueGreeting(self):
-        """
-        Evaluate the L{RootDialogueSections<RootDialogueSection>} conditions
-        and return the valid L{DialogueSection} which should be displayed
-        first.
-        
-        @return: Valid root dialogue section.
-        @rtype: L{DialogueSection}
-        
-        @raise: RuntimeError - evaluation of a DialogueGreeting condition fails
-            by raising an exception (e.g. due to a syntax error).
-        """
-        dialogue = self.dialogue
-        dialogue_greeting = None
-        for greeting in dialogue.greetings:
-            try:
-                condition_met = eval(greeting.condition, self.game_state)
-            except Exception as exception:
-                error_message = dedent_chomp('''
-                    exception raised in DialogueGreeting {id} condition:
-                    {exception}
-                ''').format(id=greeting.id, exception=exception)
-                self._logger.error(error_message)
-            if (condition_met):
-                dialogue_greeting = greeting
-        if (dialogue_greeting is None):
-            dialogue_greeting = dialogue.default_greeting
-        
-        return dialogue_greeting
-    
-    def initiateDialogue(self):
-        """
-        Prepare the L{DialogueProcessor} to process the L{Dialogue} by pushing
-        the starting L{DialogueSection} onto the L{dialogue_section_stack}.
-        
-        @raise RuntimeError: Unable to determine the root L{DialogueSection}
-            defined by the L{Dialogue}.
-        """
-        if (self.in_dialogue):
-            self.endDialogue()
-        dialogue_greeting = self.getDialogueGreeting()
-        self.dialogue_section_stack.append(dialogue_greeting)
-        self.in_dialogue = True
-        self._logger.info('initiated dialogue {0}'.format(self.dialogue))
-    
-    def continueDialogue(self):
-        """
-        Process the L{DialogueSection} at the top of the
-        L{dialogue_section_stack}, run any L{DialogueActions<DialogueActions>}
-        it contains and return a list of valid
-        L{DialogueResponses<DialogueResponses> after evaluating any response
-        conditionals.
-        
-        @returns: valid responses.
-        @rtype: list of L{DialogueResponses<DialogueResponse>}
-        
-        @raise RuntimeError: Any preconditions are not met.
-        
-        @precondition: dialogue has been initiated via L{initiateDialogue}.
-        """
-        if (not self.in_dialogue):
-            error_message = dedent_chomp('''
-                dialogue has not be initiated via initiateDialogue yet
-            ''')
-            raise RuntimeError(error_message)
-        current_dialogue_section = self.getCurrentDialogueSection()
-        self.runDialogueActions(current_dialogue_section)
-        valid_responses = self.getValidResponses(current_dialogue_section)
-        
-        return valid_responses
-    
-    def getCurrentDialogueSection(self):
-        """
-        Return the L{DialogueSection} at the top of the
-        L{dialogue_section_stack}.
-        
-        @returns: section of dialogue currently being processed.
-        @rtype: L{DialogueSection}
-        
-        @raise RuntimeError: Any preconditions are not met.
-        
-        @precondition: dialogue has been initiated via L{initiateDialogue} and
-            L{dialogue_section_stack} contains at least one L{DialogueSection}.
-        """
-        if (not self.in_dialogue):
-            error_message = dedent_chomp('''
-                getCurrentDialogueSection called but the dialogue has not been
-                initiated yet
-            ''')
-            raise RuntimeError(error_message)
-        try:
-            current_dialogue_section = self.dialogue_section_stack[-1]
-        except IndexError:
-            error_message = dedent_chomp('''
-                getCurrentDialogueSection called but no DialogueSections are in
-                the stack
-            ''')
-            raise RuntimeError(error_message)
-        
-        return current_dialogue_section
-    
-    def runDialogueActions(self, dialogue_node):
-        """
-        Execute all L{DialogueActions<DialogueActions>} contained by a
-        L{DialogueSection} or L{DialogueResponse}.
-        
-        @param dialogue_node: section of dialogue or response containing the
-            L{DialogueActions<DialogueAction>} to execute.
-        @type dialogue_node: L{DialogueNode}
-        """
-        self._logger.info('processing commands for {0}'.format(dialogue_node))
-        for command in dialogue_node.actions:
-            try:
-                command(self.game_state)
-            except (Exception,) as error:
-                self._logger.error('failed to execute DialogueAction {0}: {1}'
-                                   .format(command.keyword, error))
-                # TODO Technomage 2010-11-18: Undo previous actions when an
-                #     action fails to execute.
-            else:
-                self._logger.debug('ran {0} with arguments {1}'
-                                   .format(getattr(type(command), '__name__'),
-                                           command.arguments))
-    
-    def getValidResponses(self, dialogue_section):
-        """
-        Evaluate all L{DialogueResponse} conditions for a L{DialogueSection}
-        and return a list of valid responses.
-        
-        @param dialogue_section: section of dialogue containing the
-            L{DialogueResponses<DialogueResponse>} to process.
-        @type dialogue_section: L{DialogueSection}
-        
-        @return: responses whose conditions were met.
-        @rtype: list of L{DialogueResponses<DialogueResponse>}
-        """
-        valid_responses = []
-        for dialogue_response in dialogue_section.responses:
-            condition = dialogue_response.condition
-            try:
-                condition_met = condition is None or \
-                                eval(condition, self.game_state)
-            except (Exception,) as exception:
-                error_message = dedent_chomp('''
-                    evaluation of condition {condition} for {response} failed
-                    with error: {exception}
-                ''').format(condition=dialogue_response.condition,
-                            response=dialogue_response, exception=exception)
-                self._logger.error(error_message)
-            else:
-                self._logger.debug(
-                    'condition "{0}" for {1} evaluated to {2}'
-                    .format(dialogue_response.condition, dialogue_response,
-                            condition_met)
-                )
-                if (condition_met):
-                    valid_responses.append(dialogue_response)
-        
-        return valid_responses
-    
-    def reply(self, dialogue_response):
-        """
-        Reply with a L{DialogueResponse}, execute the
-        L{DialogueActions<DialogueAction>} it contains and push the next
-        L{DialogueSection} onto the L{dialogue_section_stack}.
-        
-        @param dialogue_response: response to reply with.
-        @type dialogue_response: L{DialogueReponse}
-        
-        @raise RuntimeError: Any precondition is not met.
-        
-        @precondition: L{initiateDialogue} must be called before this method
-            is used.
-        """
-        if (not self.in_dialogue):
-            error_message = dedent_chomp('''
-                reply cannot be called until the dialogue has been initiated
-                via initiateDialogue
-            ''')
-            raise RuntimeError(error_message)
-        self._logger.info('replied with {0}'.format(dialogue_response))
-        # FIXME: Technomage 2010-12-11: What happens if runDialogueActions
-        #     raises an error?
-        self.runDialogueActions(dialogue_response)
-        next_section_id = dialogue_response.next_section_id
-        if (next_section_id == 'back'):
-            if (len(self.dialogue_section_stack) == 1):
-                error_message = dedent_chomp('''
-                    attempted to run goto: back action but stack does not
-                    contain a previous DialogueSection
-                ''')
-                raise RuntimeError(error_message)
-            else:
-                try:
-                    self.dialogue_section_stack.pop()
-                except (IndexError,):
-                    error_message = dedent_chomp('''
-                        attempted to run goto: back action but the stack was
-                        empty
-                    ''')
-                    raise RuntimeError(error_message)
-                else:
-                    self._logger.debug(
-                        'ran goto: back action, restored last DialogueSection'
-                    )
-        elif (next_section_id == 'end'):
-            self.endDialogue()
-            self._logger.debug('ran goto: end action, ended dialogue')
-        else:
-            try:
-                next_dialogue_section = \
-                    self.dialogue.sections[next_section_id]
-            except KeyError:
-                error_message = dedent_chomp('''
-                    {0} is not a recognized goto: action or DialogueSection
-                    identifier
-                ''').format(next_section_id)
-                raise RuntimeError(error_message)
-            else:
-                self.dialogue_section_stack.append(next_dialogue_section)
-    
-    def endDialogue(self):
-        """
-        End the current dialogue and clean up any resources in use by the
-        L{DialogueProcessor}.
-        """
-        self.dialogue_section_stack = []
-        self.in_dialogue = False
--- a/src/parpg/entities/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +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 <http://www.gnu.org/licenses/>.
-
-import sys
-
-from general import General
-
-def createEntity(info, identifier, world, 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 world, which every game_obj needs.
-    extra = extra or {}
-
-    # add the extra info
-    for key, val in extra.items():
-        info[key].update(val)
-
-    # this is for testing purposes
-    new_ent = General(world, identifier)
-    for component, data in info.items():
-        comp_obj = getattr(new_ent, component)
-        for key, value in data.items():
-            setattr(comp_obj, key, value)
-    return new_ent
--- a/src/parpg/entities/action.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,630 +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 <http://www.gnu.org/licenses/>.
-
-#exceptions
-
-import logging
-
-logger = logging.getLogger('action')
-
-from parpg.gui import drag_drop_data as data_drag
-from parpg.dialoguecontroller import DialogueController
-from parpg.components import container, lockable
-
-
-class NoSuchQuestException(Exception):
-    """NoQuestException is used when there is no active quest with the id"""
-    pass
-
-#classes
-
-class Action(object):
-    """Base Action class, to define the structure"""
-
-
-    def __init__(self, controller, commands = None):
-        """Basic action constructor
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        """
-        self.commands = commands or ()
-        self.controller = controller
-        self.model = controller.model
-        self.executed = False
-    
-    def execute(self):
-        """To be overwritten"""        
-        #Check if there are special commands and execute them
-        for command_data in self.commands:
-            command = command_data["Command"]
-            if command == "SetQuestVariable":
-                quest_id = command_data["ID"]
-                variable = command_data["Variable"]
-                value = command_data["Value"]
-                quest_engine = self.model.game_state.quest_engine 
-                if quest_engine.hasQuest(quest_id):
-                    quest_engine[quest_id].setValue(variable, value)
-                else:
-                    raise NoSuchQuestException
-            elif command == "ResetMouseCursor":
-                self.controller.resetMouseCursor()
-            elif command == "StopDragging":
-                data_drag.dragging = False
-        self.executed = True
-                
-class ChangeMapAction(Action):
-    """A change map scheduled"""
-    def __init__(self, controller, target_map_name, target_pos, commands=None):
-        """Initiates a change of the position of the character
-        possibly flagging a new map to be loaded.
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        @type view: class derived from parpg.ViewBase
-        @param view: The view
-        @type target_map_name: String
-        @param target_map_name: Target map id 
-        @type target_pos: Tuple
-        @param target_pos: (X, Y) coordinates on the target map.
-        @return: None"""
-        super(ChangeMapAction, self).__init__(controller, commands)
-        self.view = controller.view
-        self.target_pos = target_pos
-        self.target_map_name = target_map_name
-
-    def execute(self):
-        """Executes the map change."""
-        self.model.changeMap(self.target_map_name,
-                              self.target_pos)
-        super(ChangeMapAction, self).execute()
-
-class OpenAction(Action):
-    """Open an lockable"""
-    def __init__(self, controller, lockable, commands=None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        @type view: class derived from parpg.ViewBase
-        @param view: The view
-        @param lockable: A reference to the lockable
-        """
-        Action.__init__(self, controller, commands)
-        self.view = controller.view
-        self.lockable = lockable
-    
-    def execute(self):
-        """Open the lockable."""
-        try:
-            lockable.open(self.lockable.lockable)
-            self.lockable.fifeagent.behaviour.animate("open")
-            self.lockable.fifeagent.behaviour.queue_animation("opened", 
-                                                              repeating=True)
-        except lockable.LockedError:
-            self.view.hud.createExamineBox(self.lockable.description.view_name,
-                                           "Locked")            
-        Action.execute(self)
-
-class CloseAction(Action):
-    """Close an lockable"""
-    def __init__(self, controller, lockable, commands=None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        @type view: class derived from parpg.ViewBase
-        @param view: The view
-        @param lockable: A reference to the lockable
-        """
-        Action.__init__(self, controller, commands)
-        self.lockable = lockable
-    
-    def execute(self):
-        """Close the lockable."""
-        lockable.close(self.lockable.lockable)
-        self.lockable.fifeagent.behaviour.animate("close")
-        self.lockable.fifeagent.behaviour.queue_animation("closed", 
-                                                          repeating=True)
-        Action.execute(self)
-        
-class UnlockAction(Action):
-    """Unlocks a lockable."""
-    def __init__(self, controller, lockable, commands = None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        @param lockable: A reference to the lockable
-        """
-        Action.__init__(self, controller, commands)
-        self.lockable = lockable
-    
-    def execute(self):
-        """Open the box."""
-        lockable.unlock(self.lockable.lockable)
-        Action.execute(self)
-        
-class LockAction(Action):
-    """Locks a lockable."""
-    def __init__(self, controller, lockable, commands = None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        @param lockable: A reference to the lockable
-        """
-        Action.__init__(self, controller, commands)
-        self.lockable = lockable
-        self.view = controller.view
-        
-    def execute(self):
-        """Lock the box."""
-        try:
-            lockable.lock(self.lockable.lockable)
-        except lockable.OpenError:
-            self.view.hud.createExamineBox(self.lockable.description.view_name,
-                                           "Is open")            
-            
-        Action.execute(self)
-
-
-class ExamineAction(Action):
-    """Examine an object."""
-    def __init__(self, controller, examine_id, examine_name, examine_desc=None, commands=None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param examine_id: An object id
-        @type examine_id: integer
-        @param examine_name: An object name
-        @type examine_name: string
-        @param examine_desc: A description of the object that will be displayed.
-        @type examine_desc: string
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        """
-        super(ExamineAction, self).__init__(controller, commands)
-        self.view = controller.view
-        self.examine_id = examine_id
-        self.examine_name = examine_name
-        if examine_desc is not None:
-            self.examine_desc = examine_desc
-        else:
-            self.examine_desc = "No Description"
-        
-    def execute(self):
-        """Display the text."""
-        action_text = self.examine_desc
-        self.view.hud.addAction(unicode(action_text))
-        logger.debug(action_text)
-        #this code will cut the line up into smaller lines that will be displayed
-        place = 25
-        while place < len(action_text):
-            if action_text[place] == ' ':
-                action_text = action_text[:place] +'\n'+action_text[place:]
-                place += 26 #plus 1 character to offset the new line
-            else: place += 1
-        self.view.displayObjectText(self.examine_id, unicode(action_text), time=3000)
-        Action.execute(self)
-
-class ExamineItemAction(Action):
-    """Examine an item."""
-    def __init__(self, controller, examine_name, examine_desc, commands = None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        @type view: class derived from parpg.ViewBase
-        @param view: The view
-        @type examine_name: String
-        @param examine_name: Name of the object to be examined.
-        @type examine_name: String
-        @param examine_name: Description of the object to be examined.
-        """
-        super(ExamineItemAction, self).__init__(controller, commands)
-        self.view = controller.view
-        self.examine_name = examine_name
-        self.examine_desc = examine_desc
-        
-    def execute(self):
-        """Display the text."""
-        action_text = unicode(self.examine_desc)
-        self.view.hud.addAction(action_text)
-        logger.debug(action_text)
-        Action.execute(self)
-
-class ExamineContentsAction(Action):
-    """Examine the contens of an container"""
-    def __init__(self, controller, container, commands=None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param container: The container
-        @type container: parpg.entities.General
-        @param commands: Special commands that are executed
-        @type commands: Dictionary         
-        """
-        Action.__init__(self, controller, commands)
-        self.view = controller.view
-        self.container = container
-        
-    def execute(self):
-        """Examine the contents"""
-        self.view.hud.createBoxGUI(self.container.description.view_name,
-                                   self.container.container)
-        Action.execute(self)
-
-class ReadAction(Action):
-    """Read a text."""
-    def __init__(self, controller, text_name, text, commands = None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        @param view: The view
-        @type view: class derived from parpg.ViewBase
-        @param text_name: Name of the object containing the text
-        @type text_name: String
-        @param text: Text to be displayied
-        @type text: String
-        """
-        super(ReadAction, self).__init__(controller, commands)
-        self.view = controller.view
-        self.text_name = text_name
-        self.text = text
-        
-    def execute(self):
-        """Examine the box."""
-        action_text = unicode('\n'.join(["You read " + self.text_name + ".", 
-                                         self.text]))
-        self.view.hud.addAction(action_text)
-        logger.debug(action_text)
-        super(ReadAction, self).execute()
-
-class TalkAction(Action):
-    """An action to represent starting a dialogue"""
-    def __init__(self, controller, npc, commands = None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        @type view: class derived from parpg.ViewBase
-        @param view: The view
-        @type npc: NonPlayerCharacter
-        @param npc: NPC to interact with.
-        """
-        super(TalkAction, self).__init__(controller, commands)
-        self.view = controller.view
-        self.npc = npc
-        
-    def execute(self):
-        """Talk with the NPC when close enough, otherwise move closer.
-           @return: None"""
-        player_char = self.model.game_state.\
-                    getObjectById("PlayerCharacter").fifeagent
-        player_char.behaviour.animate(
-            'stand', 
-            self.npc.fifeagent.behaviour.getLocation()
-        )
-
-        if self.npc.dialogue.dialogue is not None:
-            dialogue_controller = DialogueController(
-                self.controller.engine,
-                self.view,
-                self.model,
-                self.controller.application
-            )
-            self.controller.application.manager.push_mode(
-                dialogue_controller
-            )
-            dialogue_controller.startTalk(self.npc)
-        else:
-            self.npc.fifeagent.behaviour.agent.say("Leave me alone!", 1000)
-            
-        self.model.game_state.getObjectById("PlayerCharacter").\
-            fifeagent.behaviour.idle()
-        self.model.game_state.getObjectById("PlayerCharacter").\
-            fifeagent.behaviour.nextAction = None
-        super(TalkAction, self).execute()
-
-class UseAction(Action):
-    """Action for carryable items. It executes special commands that can be only
-    used on carryable utens"""
-
-
-    def __init__(self, controller, item, commands = None):
-        """
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param item: Item on which the action is called
-        @type item: CarryableItem
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        """
-        super(UseAction, self).__init__(controller, commands)
-        self.view = controller.view
-        self.item = item
-    
-    def execute(self):
-        #Check if there are special commands and execute them
-        for command_data in self.commands:
-            command = command_data["Command"]
-            if command == "ReplaceItem":
-                object_id = command_data["ID"]
-                object_type = command_data["ObjectType"]
-                containable = self.item.containable
-                new_item = self.model.createItemByType(object_type, 
-                                                       object_id, 
-                                                       self.item.world)
-                container.put_item(containable.container, 
-                                   new_item.containable,
-                                   containable.slot)
-                self.model.deleteObject(self.item.general.identifier)
-                self.item.delete()
-                self.view.hud.inventory.updateImages()
-        super(UseAction, self).execute()
-
-class PickUpAction(Action):
-    """Action for picking up items from a map"""
-
-    def __init__(self, controller, item, commands = None):
-        super(PickUpAction, self).__init__(controller, commands)
-        self.item = item
-        self.view = controller.view
-        
-    def execute(self):
-        real_item = self.item.containable
-        self.item.fifeagent = None
-        player = self.model.game_state.getObjectById("PlayerCharacter")
-        self.model.moveObject(self.item.general.identifier, None)
-        self.model.updateObjectDB(self.item.world)
-        container.put_item(player.container, real_item)
-        super(PickUpAction, self).execute()
-
-class DropItemAction(Action):
-    """Action for dropping an items on a map"""
-    def __init__(self, controller, item, commands = None):
-        super(DropItemAction, self).__init__(controller, commands)
-        self.item = item
-        
-    def execute(self):
-        map_name = self.model.game_state.current_map_name
-        identifier = self.item.entity.general.identifier
-        agent_values = self.model.items[identifier]
-        coords = (self.model.game_state.getObjectById("PlayerCharacter").
-                  fifeagent.behaviour.getLocation().getExactLayerCoordinates()
-                  )
-        agent_values["Position"] = (coords.x, coords.y)
-        agent_values["Rotation"] = 0
-        agent_values["Map"] = map_name
-        self.model.deleteObject(identifier)
-        self.model.addAgent(self.model.ALL_AGENTS_KEY, 
-                            {identifier: agent_values})
-        self.model.placeAgents(self.item.entity.world)
-        self.model.updateObjectDB(self.item.entity.world)
-        super(DropItemAction, self).execute()
-        
-class DropItemFromContainerAction(DropItemAction):
-    """Action for dropping an items from the Inventory to a map"""
-
-    def __init__(self, controller, item, container_gui, commands = None):
-        super(DropItemFromContainerAction, self).__init__(controller, item, commands)
-        self.container_gui = container_gui
-
-    def execute(self):
-        super(DropItemFromContainerAction, self).execute()
-        container.remove_item(self.item.container, self.item.slot)
-        self.container_gui.updateImages()
-
-class RunScriptAction(Action):
-    """Action that runs a specific script"""
-
-    def __init__(self, controller, script, commands = None):
-        """Basic action constructor
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param script: The name of the script to run.
-        @type script: string
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        """
-        Action.__init__(self, controller, commands)
-        self.script = script
-    
-    def execute(self):
-        self.controller.systems.scripting.runScript(self.script)
-        Action.execute(self)
-        
-class BrewBeerAction(Action):
-    """Action for brewing beer in a pot"""
-    def __init__(self, controller, pot, commands = None):
-        super(BrewBeerAction, self).__init__(controller, commands)
-        self.pot = pot.container
-        self.view = controller.view
-        
-    def execute(self):
-        """Brew the beer"""
-        has_water = False
-        has_yeast = False
-        has_fruit = False
-        has_wood = False
-        has_bottle = False
-        player_character = (self.model.game_state.
-                            getObjectById("PlayerCharacter").container)
-        for item in self.pot.children:
-            if not item:
-                continue
-            if item.item_type == "Questionable water":
-                if has_water:
-                    self.view.hud.addAction(unicode(\
-                        "Please put only 1 water in the pot"))
-                    return
-                has_water = True
-                water_type = 1 
-                water = item
-            elif item.item_type == "Pure water":
-                if has_water:
-                    self.view.hud.addAction(unicode(\
-                        "Please put only 1 water in the pot"))
-                    return
-                has_water = True
-                water_type = 2
-                water = item
-            elif item.item_type == "Grain":
-                if has_fruit:
-                    self.view.hud.addAction(unicode(\
-                        "Please put only 1 fruit in the pot"))
-                    return
-                has_fruit = True
-                fruit_type = 3
-                fruit = item
-            elif item.item_type == "Wild potato":
-                if has_fruit:
-                    self.view.hud.addAction(unicode(\
-                        "Please put only 1 fruit in the pot"))
-                    return
-                has_fruit = True
-                fruit_type = 2
-                fruit = item
-            elif item.item_type == "Rotten yam":
-                if has_fruit:
-                    self.view.hud.addAction(unicode(\
-                        "Please put only 1 fruit in the pot"))
-                    return
-                has_fruit = True
-                fruit_type = 1
-                fruit = item
-            elif item.item_type == "Yeast":
-                if has_yeast:
-                    self.view.hud.addAction(unicode(\
-                        "Please put only 1 yeast in the pot"))
-                    return
-                has_yeast = True
-                yeast = item 
-            else:
-                self.view.hud.addAction(unicode(
-                    "Item " + (item.entity.description.view_name) + 
-                    " is not needed for brewing beer"))
-                self.view.hud.addAction(unicode(\
-                    "Please put only ingredients for the beer in the pot.\
-                    Things like bottles and wood have to be in your inventory"))
-                return
-        wood = container.get_item(player_character, "Wood")
-        if wood:
-            has_wood = True        
-        bottle = container.get_item(player_character, "Empty beer bottle")
-        if bottle:
-            has_bottle = True        
-        if has_water and has_fruit and has_wood and has_bottle:
-            container.remove_item(self.pot, water.slot)
-            container.remove_item(self.pot, fruit.slot)
-            if has_yeast:
-                container.remove_item(self.pot, yeast.slot)
-            container.remove_item(player_character, wood.slot)
-            new_item = (self.model.createItemByType("Beer", "Beer", 
-                                                    self.pot.entity.world)
-                        )
-            container.put_item(player_character, new_item.containable)
-            self.view.hud.inventory.updateImages()
-            beer_quality = 0
-            if water_type == 1:
-                if fruit_type == 1:
-                    beer_quality = -1
-                elif fruit_type == 2:
-                    beer_quality = 2
-                elif fruit_type == 3:
-                    beer_quality = 3
-            if water_type == 2:
-                if fruit_type == 1:
-                    beer_quality = 1
-                elif fruit_type == 2:
-                    beer_quality = 3
-                elif fruit_type == 3:
-                    beer_quality = 4
-            if beer_quality > 0 and has_yeast:
-                beer_quality += 1
-            self.model.game_state.quest_engine.quests["beer"].\
-                    setValue("beer_quality", beer_quality)
-        else:
-            self.view.hud.addAction(unicode(
-            """For brewing beer you need at least:
-            In the pot:
-                Fruit (like grain, potato, yam)
-                Water
-                Optionally:
-                    Good quality yeast.
-                    Wild yeast will be used if none present.
-            In the inventory:
-                Wood
-                Empty bottle"""))
-        super(BrewBeerAction, self).execute()
-
-class SayAction(Action):
-    """Action that will display a short text over the entity and in the action
-    box."""
-
-    def __init__(self, controller, entity, text, commands = None):
-        """Basic action constructor
-        @param controller: A reference to the GameSceneController.
-        @type controller: parpg.GameSceneController
-        @param entity: The entity that says the text
-        @type script: parpg.entities.General
-        @param text: The text to be displayed
-        @type text: string
-        @param commands: Special commands that are executed
-        @type commands: Dictionary 
-        """
-        Action.__init__(self, controller, commands)
-        self.entity = entity
-        self.text = text
-    
-    def execute(self):
-        if self.entity.fifeagent:
-            self.entity.fifeagent.behaviour.agent.say(self.text);
-        if self.entity.description:
-            self.controller.view.hud.actions_box.addDialog(
-                self.entity.description.view_name,
-                self.text)
-        Action.execute(self)
-
-ACTIONS = {"ChangeMap":ChangeMapAction, 
-           "Open":OpenAction,
-           "Close":CloseAction,
-           "Unlock":UnlockAction,
-           "Lock":LockAction,
-           "ExamineItem":ExamineItemAction,
-           "Examine":ExamineAction,
-           "Look":ExamineItemAction,
-           "Read":ReadAction,
-           "Talk":TalkAction,
-           "Use":UseAction,
-           "PickUp":PickUpAction,
-           "DropFromInventory":DropItemFromContainerAction,
-           "BrewBeer":BrewBeerAction,
-           "ExamineContents": ExamineContentsAction,
-           "RunScript": RunScriptAction,
-           "Say" : SayAction,
-           "None": Action,
-           }
--- a/src/parpg/entities/general.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#   
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#   
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from parpg.bGrease import Entity
-
-class General(Entity):
-    
-    def __init__(self, world, identifier):
-        self.general.identifier = identifier
-        
-    def getID(self):
-        return self.general.identifier
\ No newline at end of file
--- a/src/parpg/font.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-import os
-
-from fife.extensions import pychan
-from fife.extensions.pychan.fonts import Font
-
-
-class PARPGFont(Font):
-    """ Font class for PARPG
-        This class behaves identical to PyChan's Font class except in
-        initialization. Ratherthan take a name and a get object, this class
-        takes a fontdef and settings object as explained below. This class is
-        necessary because the original Font class was too restrictive on how it
-        accepted objects
-
-        @param fontdef: defines the font's name, size, type, and optionally 
-                        row spacing as well as glyph spacing.
-        @type fontdef: dictionary
-        
-        @param settings: settings object used to dynamically determine the
-                         font's source location
-        @type settings: parpg.settings.Settings object
-    """
-    def __init__(self, fontdef, settings):
-        self.font = None
-        self.name = fontdef['name']
-        self.typename = fontdef['typename']
-
-        if self.typename == 'truetype':
-            self.filename = '{0}.ttf'.format(self.name.lower().split('_')[0])
-
-        self.source = '/'.join(['fonts', self.filename])
-        self.row_spacing = fontdef.get('row_spacing', 0)
-        self.glyph_spacing = fontdef.get('glyph_spacing', 0)
-
-        if self.typename == 'truetype':
-            self.size = fontdef['size']
-            self.antialias = fontdef['antialias']
-            self.color = fontdef.get('color', [255, 255, 255])
-            manager = pychan.manager.hook.guimanager
-            self.font = manager.createFont(self.source, self.size, '')
-
-            if not self.font:
-                raise InitializationError('Could not load font '
-                                          '{0}'.format(self.name))
-        
-            self.font.setAntiAlias(self.antialias)
-            self.font.setColor(*self.color)
-        else:
-            raise InitializationError('Unsupported font type '
-                                      '{0}'.format(self.typename))
-
-        self.font.setRowSpacing(self.row_spacing)
-        self.font.setGlyphSpacing(self.glyph_spacing)
--- a/src/parpg/gamemap.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +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 <http://www.gnu.org/licenses/>.
-
-from fife import fife
-from fife.extensions import pychan
-from fife.extensions.loaders import loadMapFile
-
-class GameMap(fife.MapChangeListener):
-    """Map class used to flag changes in the map"""
-    def __init__(self, engine, model):
-        # init mapchange listener
-        fife.MapChangeListener.__init__(self)
-        self.map = None
-        self.engine = engine
-        self.model = model
-        self.settings = self.model.settings
-
-        # init map attributes
-        self.my_cam_id = None
-        self.cameras = {}
-        self.agent_layer = None
-        self.top_layer = None
-        self.fife_model = engine.getModel()
-        self.transitions = []
-        self.cur_cam2_x = 0
-        self.initial_cam2_x = 0
-        self.cam2_scrolling_right = True
-        self.target_rotation = 0
-        self.outline_renderer = None
-        
-    def reset(self):
-        """Reset the model to default settings.
-           @return: None"""
-        # We have to delete the map in Fife.
-        if self.map:
-            self.model.deleteObjects()
-            self.model.deleteMap(self.map)
-
-        self.transitions = []
-        self.map = None
-        self.agent_layer = None        
-        self.top_layer = None
-        # We have to clear the cameras in the view as well, or we can't reuse
-        # camera names like 'main'
-        #self.view.clearCameras()
-        self.initial_cam2_x = 0
-        self.cam2_scrolling_right = True
-        #self.cameras = {}
-        self.cur_cam2_x = 0
-        self.target_rotation = 0
-        self.outline_renderer = None
-        
-    def makeActive(self):
-        """Makes this map the active one.
-           @return: None"""
-        self.cameras[self.my_cam_id].setEnabled(True)
-        
-    def load(self, filename):
-        """Load a map given the filename.
-           @type filename: String
-           @param filename: Name of map to load
-           @return: None"""
-        self.reset()
-
-        self.map = loadMapFile(filename, self.engine)
-
-        self.agent_layer = self.map.getLayer('ObjectLayer')
-        self.top_layer = self.map.getLayer('TopLayer')      
-            
-        # it's possible there's no transition layer
-        size = len('TransitionLayer')
-        for layer in self.map.getLayers():
-            # could be many layers, but hopefully no more than 3
-            if(layer.getId()[:size] == 'TransitionLayer'):
-                self.transitions.append(self.map.getLayer(layer.getId()))
-
-        """ Initialize the camera.
-        Note that if we have more than one camera in a map file
-        we will have to rework how self.my_cam_id works. To make sure
-        the proper camera is set as the 'main' camera.
-        At this point we also set the viewport to the current resolution."""
-        for cam in self.map.getCameras():
-            width = self.settings.fife.ScreenWidth
-            height = self.settings.fife.ScreenHeight
-            viewport = fife.Rect(0, 0, width, height)
-            cam.setViewPort(viewport)
-            self.my_cam_id = cam.getId()
-            self.cameras[self.my_cam_id] = cam
-            cam.resetRenderers()
-        
-        self.target_rotation = self.cameras[self.my_cam_id].getRotation()
-
-        self.outline_renderer = (
-            fife.InstanceRenderer.getInstance(self.cameras[self.my_cam_id])
-        )
-
-        # set the render text
-        rend = fife.FloatingTextRenderer.getInstance(
-            self.cameras[self.my_cam_id]
-        )
-        font = pychan.manager.hook.guimanager.createFont(
-            'fonts/rpgfont.png',
-            0,
-            self.settings.fife.FontGlyphs
-        )
-
-        rend.setFont(font)
-        rend.activateAllLayers(self.map)
-        rend.setEnabled(True)
-        
-        # Activate the grid renderer on all layers
-        rend = self.cameras['map_camera'].getRenderer('GridRenderer')
-        rend.activateAllLayers(self.map)
-         
-        # Activate the grid renderer on all layers
-        rend = fife.CoordinateRenderer.getInstance(
-            self.cameras[self.my_cam_id]
-        )
-        rend.setColor(0, 0, 0)
-        rend.addActiveLayer(self.map.getLayer("GroundLayer"))
-
-        # Make World aware that this is now the active map.
-        self.model.active_map = self
-
-    def addPC(self):
-        """Add the player character to the map
-           @return: None"""
-        # Update gamestate.player_character
-        player = self.model.game_state.getObjectById("PlayerCharacter")
-        player.fifeagent.behaviour.onNewMap(self.agent_layer)
-        self.centerCameraOnPlayer()
-
-    def toggleRenderer(self, r_name):
-        """Enable or disable a renderer.
-           @return: None"""
-        renderer = self.cameras[self.my_cam_id].getRenderer(str(r_name))
-        renderer.setEnabled(not renderer.isEnabled())
-
-    def isPaused(self):
-        """Returns wheter the map is currentply paused or not"""
-        # Time multiplier is a float, never do equals on floats
-        return not self.map.getTimeMultiplier() >= 1.0
-    
-    def pause(self, paused):
-        """ Pause/Unpause the game.
-        @return: nothing"""
-        if paused:
-            self.map.setTimeMultiplier(0.0)
-        if not paused and self.isPaused():
-            self.map.setTimeMultiplier(1.0)
-        
-    def togglePause(self):
-        """ Toggle paused state.
-        @return: nothing"""
-        self.pause(not self.isPaused())
-
-    def centerCameraOnPlayer(self):
-        """Center the camera on the player"""
-        camera = self.cameras[self.my_cam_id]
-        player = self.model.game_state.getObjectById("PlayerCharacter")
-        camera.setLocation(player.fifeagent.behaviour.getLocation())
--- a/src/parpg/gamemodel.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,868 +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 <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 parpg.bGrease.geometry import Vec2d
-from serializers import XmlSerializer
-
-from parpg import vfs
-from gamestate import GameState
-from gamemap import GameMap
-from common.utils import locateFiles
-from common.utils import parseBool
-from parpg.dialogueparsers import YamlDialogueParser, DialogueFormatError
-from parpg.entities import createEntity
-from parpg import behaviours
-from parpg import components
-from parpg.components import fifeagent, container, equip, character_statistics
-import characterstatistics as char_stats
-
-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
-    GENERIC_ITEM_GFX = "generic_item"
-    DEFAULT_STAT_VALUE = 50
-    
-    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 = 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.items = {}
-        self.engine = engine
-        self.fife_model = engine.getModel()
-
-        # set values from settings
-        maps_directory = settings.parpg.MapsPath
-        self.game_state.maps_file = '/'.join([maps_directory,
-                                              settings.parpg.MapsFile])
-        self.all_agents_file = '/'.join([maps_directory,
-                                         settings.parpg.AllAgentsFile])
-        objects_directory = self.settings.parpg.ObjectsPath
-        self.objects_directory = objects_directory
-        self.object_db_file = '/'.join([objects_directory,
-                                        settings.parpg.ObjectDatabaseFile])
-        self.dialogue_directory = settings.parpg.DialoguesPath
-        self.dialogues = {}
-        self.agent_import_files = {}
-        self.obj_loader = XMLObjectLoader(self.engine)
-        # FIXME M. George Hansen 2011-06-06: character stats scripts aren't
-        #     finished, unfortunately.
-        # NOTE Beliar 2011-11-05 Activated the stats. Testing needed if it 
-        # works correctly, or if they are still unfinished.
-        primary_stats_file = (
-            vfs.VFS.open('character_scripts/primary_stats.xml')
-        )
-        self.primary_stats = XmlSerializer.deserialize(primary_stats_file)
-        secondary_stats_file = (
-            vfs.VFS.open('character_scripts/secondary_stats.xml')
-        )
-        self.secondary_stats = XmlSerializer.deserialize(secondary_stats_file)        
-
-        
-    def create_stats(self, entity):
-        for primary_stat in self.primary_stats:
-            long_name = primary_stat.long_name
-            entity.characterstats.primary_stats[long_name] = (
-                char_stats.PrimaryStatisticValue(
-                    primary_stat, entity.characterstats, 
-                    self.DEFAULT_STAT_VALUE)
-            )
-        for secondary_stat in self.secondary_stats:
-            name = secondary_stat.name            
-            entity.characterstats.secondary_stats[name] = (
-                char_stats.SecondaryStatisticValue(secondary_stat, 
-                                                   entity.characterstats
-                                                   )
-            )
-            
-    def checkAttributes(self, attributes, template):
-        """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
-        @param template: Template from which the values will be used
-        @return: The modified attributes""" 
-        if self.object_db.has_key(template):
-            db_attributes = deepcopy(self.object_db[template])
-            for key in db_attributes.keys():
-                if attributes.has_key(key):                    
-                    tmp_attributes = db_attributes[key]
-                    tmp_attributes.update(attributes[key])
-                    attributes[key] = tmp_attributes
-                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 moveObject(self, object_id, new_map):
-        """Moves the object to a new map, or in a container
-        @param object_id: ID of the object
-        @type object_id: str 
-        @param new_map: ID of the new map, or None
-        @type object_id: str """
-        game_object = self.deleteObject(object_id)
-        self.game_state.addObject(object_id, new_map, game_object)
-
-    def deleteObject(self, object_id):
-        """Removes an object from the game
-        @param object_id: ID of the object
-        @type object_id: str """
-        if self.agents["All"].has_key(object_id):
-            del self.agents["All"][object_id]
-        else:
-            del self.items[object_id]
-        return 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"] = self.agents
-        save_state["Items"] = self.items
-        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)
-        self.items = save_state["Items"]               
-      
-        load_file.close()             
-         
-    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_file = vfs.VFS.open(self.game_state.maps_file)
-        self.map_files = yaml.load(maps_file)["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["Entity"].has_key("graphics") \
-           and agent_values["Entity"]["graphics"].has_key("gfx"): 
-            object_model = agent_values["Entity"]["graphics"]["gfx"]
-        elif agent_values.has_key("Template"):
-            template = self.object_db[agent_values["Template"]]
-            object_model = template["graphics"]["gfx"]
-        else:
-            object_model = self.GENERIC_ITEM_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 = vfs.VFS.open(map_agents_file)
-        agents = yaml.load_all(agents_data)
-        self.agents[map_name] = {}
-        for agent in agents:
-            if not agent == None:
-                self.addAgent(map_name, agent)  
-        
-    def readScriptsOfMap(self, map_name, world):
-        """Read the scripts of the map
-        @param map_name: Name of the map
-        @type map_name: str 
-        @param world: The current active world
-        @type world: parpg.world.World"""
-        map_scripts_file = (
-            self.map_files[map_name].replace(".xml", "_scripts.yaml")
-        )
-        if vfs.VFS.exists(map_scripts_file):
-            scripts_file = vfs.VFS.open(map_scripts_file)
-            scripts_data = yaml.load(scripts_file)
-            scripts = (scripts_data["Scripts"])
-            conditions = (
-                scripts_data["Conditions"] if 
-                scripts_data.has_key("Conditions") else ()
-            )
-            scripting = world.systems.scripting
-            for name, actions in scripts.iteritems():
-                scripting.setScript(name, actions)
-            for condition in conditions:
-                scripting.addCondition(*condition)            
-            
-    def readAllAgents(self):
-        """Read the agents of the all_agents_file and store them"""
-        agents_file = vfs.VFS.open(self.all_agents_file)
-        agents = yaml.load_all(agents_file)
-        for agent in agents:
-            if agent is not 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, world):
-        if self.game_state.hasObject(inst_id):
-            return None
-        entity_data = deepcopy(agent["Entity"])
-        entity_data["fifeagent"] = {}
-        template = None
-        if agent.has_key("Template"):
-            template = agent["Template"]
-            entity_data = self.checkAttributes(entity_data, template)
-        object_id = (entity_data["graphics"]["gfx"] 
-                     if entity_data.has_key("graphics") and 
-                     entity_data["graphics"].has_key("gfx") 
-                     else self.GENERIC_ITEM_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(object_id)))
-
-        x_pos = agent["Position"][0]
-        y_pos = agent["Position"][1]
-        z_pos = agent["Position"][2] if len(agent["Position"]) == 3 \
-                                        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)        
-
-        if entity_data.has_key("behaviour"):
-            entity_data["fifeagent"]["behaviour"] = \
-                getattr(behaviours, 
-                        entity_data["behaviour"]["behaviour_type"])()
-        else:
-            entity_data["fifeagent"]["behaviour"] = behaviours.Base()
-        if self.dialogues.has_key(inst_id):
-            entity_data["dialogue"] = {}
-            entity_data["dialogue"]["dialogue"] = self.dialogues[inst_id]
-        if (entity_data.has_key("containable") and not 
-            entity_data["containable"].has_key("item_type")
-            ):
-            entity_data["containable"]["item_type"] = template          
-                      
-        obj = self.createMapObject(self.active_map.agent_layer, 
-                                   entity_data, inst_id, world)
-
-        if agent.has_key("Statistics"):
-            self.create_stats(obj)
-            for name, val in agent["Statistics"].iteritems():
-                obj.characterstats.primary_stats[name].value = val
-
-        if agent.has_key("Inventory"):
-            inv = agent["Inventory"]
-            self.createInventoryItems(inv, obj, world)
-
-        if agent.has_key("Equipment"):
-            for slot, data in agent["Equipment"].iteritems():
-                item = None
-                if data.has_key("type"):
-                    item_type = data["type"]
-                    item_data = {}
-                    item_data = self.checkAttributes(item_data, item_type)
-                    if (item_data.has_key("containable") and 
-                        item_data.has_key("equipable")):
-                        item = self.createItem(
-                            self.createUniqueID(data["ID"]), 
-                            item_data, world, item_type)
-                    else:
-                        raise Exception(
-                            "Item %s is not containable or equipable." % 
-                            item_type
-                        )
-                else:
-                    identifier = data["ID"]
-                    if self.game_state.hasObject(identifier):
-                        item = self.game_state.getObjectById(identifier)
-                    else:
-                        item_data = self.items[identifier]["Entity"]
-                        item_type = item_data["containable"]["item_type"]
-                        item = self.createItem(identifier, item_data,
-                                                world, item_type)
-                equip.equip(obj.equip, item.equipable, slot)
-        if (obj.fifeagent and (obj.lockable and not obj.lockable.closed)):
-            obj.fifeagent.behaviour.animate("opened", repeating=True)
-        return obj
-
-    def createInventoryItems(self, inv, obj, world):
-        slots = inv["Slots"]
-        obj.container.children = list()
-        for x in xrange(slots):
-            obj.container.children.append(None)
-        items = inv["Items"] if inv.has_key("Items") else list()
-        for data in items:
-            item = None
-            slot = data["Slot"] if data.has_key("Slot") else -1
-            if data.has_key("type"):
-                item_type = data["type"]
-                item = self.createItemByType(item_type, data["ID"], world)
-            else:
-                identifier = data["ID"]
-                item = self.createItemByID(world, identifier)
-                    
-            container.put_item(obj.container, item.containable, slot)
-
-    def createItemByID(self, world, identifier):
-        if self.game_state.hasObject(identifier):
-            item = self.game_state.getObjectById(identifier)
-        else:
-            agent_data = self.items[identifier]
-            item_data = agent_data["Entity"]
-            item_type = item_data["containable"]["item_type"]
-            item = self.createItem(identifier, item_data,
-                                    world, item_type)
-            if item.container and agent_data.has_key("Inventory"):
-                self.createInventoryItems(agent_data["Inventory"],
-                                            item, world)
-        return item
-
-    def createItemByType(self, item_type, identifier, world):
-        item_data = {}
-        item_data = self.checkAttributes(item_data, item_type)
-        if item_data.has_key("containable"):
-            return self.createItem( self.createUniqueID(identifier), 
-                                    item_data, world, item_type)
-        else:
-            raise Exception("Item %s is not containable." % item_type)
-
-    def createItem(self, identifier, item_data, world, item_type):
-        if not item_data["description"].has_key("view_name"):
-            item_data["description"]["view_name"] = (
-             item_data["description"]["real_name"])
-        item = createEntity(item_data, identifier, world, None)
-        item.containable.item_type = item_type
-        self.game_state.addObject(identifier, None, item)
-        self.updateObjectDB(world)
-        return item
-
-    def placeAgents(self, world):
-        """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, world)
-
-    def placePC(self, world):
-        """Places the PlayerCharacter on the map"""
-        agent = self.agents[self.ALL_AGENTS_KEY]["PlayerCharacter"]
-        inst_id = "PlayerCharacter"
-        self.createAgent(agent, inst_id, world)
-        
-        # create the PlayerCharacter agent
-        self.active_map.addPC()
-        #self.game_state.getObjectById("PlayerCharacter").fifeagent.start()
-        if agent.has_key("PeopleKnown"):
-            player = self.game_state.getObjectById("PlayerCharacter")
-            player.fifeagent.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, world):
-        """Sets the active map that is to be rendered.
-           @type map_name: String
-           @param map_name: The name of the map to load
-           @param world: The active world
-           @type world: parpg.world.World
-           @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
-        if not self.agents.has_key(map_name):
-            self.readAgentsOfMap(map_name)
-
-    def createMapObject (self, layer, attributes, inst_id, world):
-        """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: The created object"""
-        # create the extra data
-        extra = {}
-        if layer is not None:
-            extra['fifeagent'] = {}
-            extra['fifeagent']['layer'] = layer
-        
-        obj = createEntity(attributes, inst_id, world, extra)
-        if obj:
-            self.addObject(layer, obj)
-        return 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
-        player = self.game_state.getObjectById("PlayerCharacter")
-        player.fifeagent = player_char
-        player.fifeagent.setup()        
-        player.fifeagent.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.general.identifier,
-                                            self.game_state.current_map_name) 
-        if ref is None:
-            # no, add it to the game state
-            self.game_state.addObject(obj.general.identifier, 
-                                      self.game_state.current_map_name, obj)
-        else:
-            # yes, use the current game state data
-            obj.fifeagent.pos.X = ref.X
-            obj.fifeagent.pos.Y = ref.Y
-            obj.fifeagent.gfx = ref.gfx
-             
-        if obj.fifeagent.behaviour:
-            obj.fifeagent.behaviour.parent = obj
-            fifeagent.setup_behaviour(obj.fifeagent)
-            obj.fifeagent.behaviour.speed = self.settings.parpg.PCSpeed
-            #Start the behaviour            
-            obj.fifeagent.behaviour.idle()
-            # create the agent
-            #obj.setup()
-            #obj.behaviour.speed = self.settings.parpg.PCSpeed
-            # 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.general.identifier == 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"""
-        player = self.game_state.getObjectById("PlayerCharacter")
-        if(self.pc_run == 1):
-            player.fifeagent.behaviour.run(position)
-        else:
-            player.fifeagent.behaviour.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 = vfs.VFS.open(self.object_db_file)
-        database = yaml.load_all(database_file)
-        for object_info in database:
-            self.object_db.update(object_info)
-
-    def updateObjectDB(self, world):
-        """Updates the values in the object database with the worlds values"""
-        
-        all_agents = self.agents[self.ALL_AGENTS_KEY]
-        for entity in world.entities:
-            identifier = entity.general.identifier
-            agent_data = {}
-            map_id = self.game_state.getMapOfObject(identifier)
-            if map_id:
-                if all_agents.has_key(identifier):
-                    agent_data = self.agents[self.ALL_AGENTS_KEY][identifier]
-                else:
-                    agent_data = self.agents[map_id][identifier]
-
-            else:
-                if not self.items.has_key(identifier):
-                    self.items[identifier] = {}
-                agent_data = self.items[identifier]
-            entity_data = {}
-            entity_data["general"] = {"identifier": identifier}
-            for name, component in components.components.iteritems():
-                if getattr(entity, name):
-                    comp_data = {}
-                    comp_vals = getattr(entity, name)
-                    #Items that are in containers will be saved with them.
-                    for field in component.saveable_fields:
-                        try:
-                            comp_data[field] = getattr(comp_vals, field)
-                        except AttributeError:                            
-                            #The entity doesn't have this specific value,
-                            #ignore it
-                            pass
-                    if comp_data:
-                        entity_data[name] = comp_data
-                    if name == "fifeagent":
-                        if entity.fifeagent.layer:
-                            layer = entity.fifeagent.layer
-                            inst = layer.getInstance(identifier)
-                            loc = inst.getLocation().getExactLayerCoordinates()
-                            agent_data["Position"] = (loc.x, loc.y, loc.z)
-                            if all_agents.has_key(identifier):
-                                agent_data["Map"] = map_id
-                            agent_data["Rotation"]  = inst.getRotation()
-                    elif name == "characterstats":
-                        agent_data["Statistics"] = (
-                            character_statistics.get_stat_values(
-                                entity.characterstats
-                            )["primary"]
-                        )
-                    elif name == "container" and hasattr(comp_vals, 
-                                                         "children"):
-                        inventory_data = {}
-                        inventory_data["Slots"] = len(comp_vals.children)
-                        items = []
-                        for child in comp_vals.children:
-                            if not child:
-                                continue
-                            items.append(
-                                {"ID": child.entity.general.identifier,
-                                 "Slot": child.slot}
-                            )
-                        inventory_data["Items"] = items
-                        agent_data["Inventory"] = inventory_data
-                    elif name == "equip":
-                        equip_data = {}
-                        for field in component.fields:
-                            if(hasattr(comp_vals, field)):
-                                equipable = getattr(comp_vals, field)
-                                if equipable:
-                                    equip_data[field] = {
-                                        "ID": 
-                                         equipable.entity.general.identifier
-                                    }
-                        agent_data["Equipment"] = equip_data
-            agent_data["Entity"] = entity_data           
-        
-    def getAgentImportFiles(self):
-        """Searches the agents directory for import files """
-        filepaths = locateFiles("*.xml", self.objects_directory)
-        for filepath in filepaths:
-            try:
-                xml_file = vfs.VFS.open(filepath)
-                root = ElementTree.parse(xml_file).getroot()
-                if root.tag == "object":
-                    self.agent_import_files[root.attrib["id"]] = filepath
-            except SyntaxError as error:
-                logging.error("Error parsing file {0}: {1}".format(filepath,
-                                                                   error))
-    
-    def getDialogues(self):
-        """Searches the dialogue directory for dialogues """
-        files = locateFiles("*.yaml", self.dialogue_directory)
-        dialogue_parser = YamlDialogueParser()
-        for dialogue_filepath in files:
-            # Note Technomage 2010-11-13: the new DialogueEngine uses its own
-            #     parser now, YamlDialogueParser.
-#            dialogues = yaml.load_all(file(dialogue_file, "r"))
-            dialogue_file = vfs.VFS.open(dialogue_filepath)
-            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
--- a/src/parpg/gamescenecontroller.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,581 +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 <http://www.gnu.org/licenses/>.
-"""This file contains the GameSceneController that handles input when the game
-   is exploring a scene"""
-
-
-from datetime import datetime
-import random
-import glob
-import os
-import logging
-
-from fife import fife
-from fife import extensions
-
-from controllerbase import ControllerBase
-from parpg.gui.hud import Hud
-from parpg.gui import drag_drop_data as data_drag
-from entities.action import (ChangeMapAction, ExamineAction, TalkAction,
-                            OpenAction, CloseAction, UnlockAction, LockAction, 
-                            PickUpAction, DropItemAction, 
-                            ExamineContentsAction,
-                            )
-
-from parpg.world import World
-
-#For debugging/code analysis
-if False:
-    from gamesceneview import GameSceneView
-    from gamemodel import GameModel
-    from parpg import PARPGApplication
-
-
-logger = logging.getLogger('gamescenecontroller')
-
-class GameSceneController(World, ControllerBase):
-    '''
-    This controller handles inputs when the game is in "scene" state.
-    "Scene" state is when the player can move around and interact
-    with objects. Like, talking to a npc or examining the contents of a box. 
-    '''
-
-
-    def __init__(self, engine, view, model, application):
-        '''
-        Constructor
-        @param engine: Instance of the active fife engine
-        @type engine: fife.Engine
-        @param view: Instance of a GameSceneView
-        @param type: parpg.GameSceneView
-        @param model: The model that has the current gamestate
-        @type model: parpg.GameModel
-        @param application: The application that created this controller
-        @type application: parpg.PARPGApplication
-        @param settings: The current settings of the application
-        @type settings: fife.extensions.fife_settings.Setting
-        '''
-        ControllerBase.__init__(self,
-                                engine,
-                                view,
-                                model,
-                                application)
-        World.__init__(self)
-        self.systems.scripting.game_state = self.model.game_state
-        
-        #this can be helpful for IDEs code analysis
-        if False:
-            assert(isinstance(self.engine, fife.Engine))
-            assert(isinstance(self.view, GameSceneView))
-            assert(isinstance(self.view, GameModel))
-            assert(isinstance(self.application, PARPGApplication))
-            assert(isinstance(self.event_manager, fife.EventManager))
-        
-        # Last saved mouse coords        
-        self.action_number = 1
-
-        self.has_mouse_focus = True
-        self.last_mousecoords = None
-        self.mouse_callback = None
-        self.original_cursor_id = self.engine.getCursor().getId()
-        self.scroll_data = {"mouse":[], "kb":[], "offset":[0,0]}
-        self.scroll_timer = extensions.fife_timer.Timer(
-            100,
-            lambda: self.view.moveCamera(self.scroll_data["offset"]),
-        )
-        
-        #this is temporary until we can set the native cursor
-        self.resetMouseCursor()
-        self.paused = False
-
-        if model.settings.fife.EnableSound:
-            if not self.view.sounds.music_init:
-                music_path = 'music'
-                music_file = random.choice(
-                    glob.glob('/'.join([music_path, '*.ogg']))
-                )
-                self.view.sounds.playMusic(music_file) 
-        self.initHud()
-                
-
-    def initHud(self):
-        """Initialize the hud member
-        @return: None"""
-        hud_callbacks = {
-            'saveGame': self.saveGame,
-            'loadGame': self.loadGame,
-            'quitGame': self.quitGame,
-        }
-        self.view.hud = Hud(self, 
-                            self.model.settings, 
-                            hud_callbacks)
-
-    def keyPressed(self, evt):
-        """Whenever a key is pressed, fife calls this routine.
-           @type evt: fife.event
-           @param evt: The event that fife caught
-           @return: None"""
-        key = evt.getKey()
-        key_val = key.getValue()
-
-        if(key_val == key.Q):
-            # we need to quit the game
-            self.view.hud.quitGame()
-        if(key_val == key.T):
-            self.model.active_map.toggleRenderer('GridRenderer')
-        if(key_val == key.F1):
-            # display the help screen and pause the game
-            self.view.hud.displayHelp()
-        if(key_val == key.F5):
-            self.model.active_map.toggleRenderer('CoordinateRenderer')
-        if(key_val == key.F7):
-            # F7 saves a screenshot to screenshots directory
-
-            settings = self.model.settings
-            # FIXME M. George Hansen 2011-06-06: Not sure that user_path is set
-            #     correctly atm.
-            screenshot_directory = os.path.join(settings.user_path,
-                                                'screenshots')
-            # try to create the screenshots directory
-            try:
-                os.mkdir(screenshot_directory)
-            #TODO: distinguish between already existing permissions error
-            except OSError:
-                logger.warning("screenshot directory wasn't created.")
-
-            screenshot_file = os.path.join(screenshot_directory,
-                                           'screen-{0}.png'.format(
-                                           datetime.now().strftime(
-                                           '%Y-%m-%d-%H-%M-%S')))
-            self.engine.getRenderBackend().captureScreen(screenshot_file)
-            logger.info("PARPG: Saved: {0}".format(screenshot_file))
-        if(key_val == key.F10):
-            # F10 shows/hides the console
-            self.engine.getGuiManager().getConsole().toggleShowHide()
-        if(key_val == key.C):
-            # C opens and closes the character screen.
-            self.view.hud.toggleCharacterScreen()
-        if(key_val == key.I):
-            # I opens and closes the inventory
-            self.view.hud.toggleInventory()
-        if(key_val == key.A):
-            # A adds a test action to the action box
-            # The test actions will follow this format: Action 1,
-            # Action 2, etc.
-            self.view.hud.addAction("Action " + str(self.action_number))
-            self.action_number += 1
-        if(key_val == key.ESCAPE):
-            # Escape brings up the main menu
-            self.view.hud.displayMenu()
-            # Hide the quit menu
-            self.view.hud.quit_window.hide()
-        if(key_val == key.M):
-            self.view.sounds.toggleMusic()
-        if(key_val == key.PAUSE):
-            # Pause pause/unpause the game 
-            self.model.togglePause()
-            self.pause(False)
-        if(key_val == key.SPACE):
-            self.model.active_map.centerCameraOnPlayer()
-        
-        #alter scroll data if a directional key is hit
-        if(key_val == key.UP):
-            if not "up" in self.scroll_data["kb"]:
-                self.scroll_data["kb"].append("up")
-
-        if(key_val == key.RIGHT):
-            if not "right" in self.scroll_data["kb"]:
-                self.scroll_data["kb"].append("right")
- 
-        if(key_val == key.DOWN): 
-            if not "down" in self.scroll_data["kb"]:
-                self.scroll_data["kb"].append("down")
-
-        if(key_val == key.LEFT):
-            if not "left" in self.scroll_data["kb"]:
-                self.scroll_data["kb"].append("left")
-    
-    def keyReleased(self, evt):
-        """Whenever a key is pressed, fife calls this routine.
-           @type evt: fife.event
-           @param evt: The event that fife caught
-           @return: None"""
-        key = evt.getKey()
-        key_val = key.getValue()
-
-        #alter scroll data if a directional key is released
-        if(key_val == key.UP):
-            if "up" in self.scroll_data["kb"]:
-                self.scroll_data["kb"].remove("up")
-
-        if(key_val == key.RIGHT):
-            if "right" in self.scroll_data["kb"]:
-                self.scroll_data["kb"].remove("right")
- 
-        if(key_val == key.DOWN): 
-            if "down" in self.scroll_data["kb"]:
-                self.scroll_data["kb"].remove("down")
-
-        if(key_val == key.LEFT):
-            if "left" in self.scroll_data["kb"]:
-                self.scroll_data["kb"].remove("left")
-        
-    def mouseReleased(self, evt):
-        """If a mouse button is released, fife calls this routine.
-           We want to wait until the button is released, because otherwise
-           pychan captures the release if a menu is opened.
-           @type evt: fife.event
-           @param evt: The event that fife caught
-           @return: None"""
-        self.view.hud.hideContextMenu()
-        scr_point = fife.ScreenPoint(evt.getX(), evt.getY())
-        if(evt.getButton() == fife.MouseEvent.LEFT):
-            if(data_drag.dragging):
-                coord = self.model.getCoords(scr_point)\
-                                    .getExactLayerCoordinates()
-                commands = ({"Command": "ResetMouseCursor"}, 
-                            {"Command": "StopDragging"})
-                player_char = (self.model.game_state.
-                               getObjectById("PlayerCharacter"))
-                action =  DropItemAction(self, 
-                                         data_drag.dragged_item, 
-                                         commands)
-                player_char.fifeagent.behaviour.approach([coord.x, coord.y], 
-                                                         action)
-            else:
-                self.model.movePlayer(self.model.getCoords(scr_point))
-        elif(evt.getButton() == fife.MouseEvent.RIGHT):
-            # is there an object here?
-            tmp_active_map = self.model.active_map
-            instances = tmp_active_map.cameras[tmp_active_map.my_cam_id].\
-                            getMatchingInstances(scr_point,
-                                                 tmp_active_map.agent_layer)
-            info = None
-            for inst in instances:
-                # check to see if this is an active item
-                if(self.model.objectActive(inst.getId())):
-                    # yes, get the model
-                    info = self.getItemActions(inst.getId())
-                    break
-
-            # take the menu items returned by the engine or show a
-            # default menu if no items
-            data = info or \
-                [["Walk", "Walk here", self.view.onWalk, 
-                  self.model.getCoords(scr_point)]]
-            # show the menu
-            self.view.hud.showContextMenu(data, (scr_point.x, scr_point.y))
-    
-        
-    def updateMouse(self):
-        """Updates the mouse values"""
-        if self.paused:
-            return
-        cursor = self.engine.getCursor()
-        #this can be helpful for IDEs code analysis
-        if False:
-            assert(isinstance(cursor, fife.Cursor))
-        self.last_mousecoords = fife.ScreenPoint(cursor.getX(), cursor.getY())
-        self.view.highlightFrontObject(self.last_mousecoords)
-        
-        #set the trigger area in pixles
-        pixle_edge = 20
-        
-        mouse_x = self.last_mousecoords.x
-        screen_width = self.model.engine.getSettings().getScreenWidth()
-        mouse_y = self.last_mousecoords.y
-        screen_height = self.model.engine.getSettings().getScreenHeight()
-        
-        image = None
-        settings = self.model.settings
-        
-        
-        #edge logic
-        if self.has_mouse_focus:
-            direction = self.scroll_data["mouse"] = []
-            
-            #up
-            if mouse_y <= pixle_edge:
-                direction.append("up")
-                image = '/'.join(['gui/cursors', settings.parpg.CursorUp])
-                
-            #right
-            if mouse_x >= screen_width - pixle_edge:
-                direction.append("right")
-                image = '/'.join(['gui/cursors', settings.parpg.CursorRight])
-                
-            #down
-            if mouse_y >= screen_height - pixle_edge:
-                direction.append("down")
-                image = '/'.join(['gui/cursors', settings.parpg.CursorDown])
-                
-            #left
-            if mouse_x <= pixle_edge:
-                direction.append("left")
-                image = '/'.join(['gui/cursors', settings.parpg.CursorLeft])
-                
-            if image is not None and not data_drag.dragging:
-                self.setMouseCursor(image, image)
-       
-
-    def handleCommands(self):
-        """Check if a command is to be executed
-        """
-        if self.model.map_change:
-            self.pause(True)
-            if self.model.active_map:
-                self.model.updateObjectDB(self)
-                player_char = self.model.game_state.\
-                    getObjectById("PlayerCharacter").fifeagent
-                pc_agent = self.model.agents\
-                    [self.model.ALL_AGENTS_KEY]["PlayerCharacter"]
-                pc_agent["Map"] = self.model.target_map_name 
-                pc_agent["Position"] = (self.model.target_position or 
-                                        pc_agent["Position"])
-                player_agent = self.model.active_map.\
-                                    agent_layer.getInstance("PlayerCharacter")
-                self.model.game_state.deleteObject("PlayerCharacter").delete()
-                deleted = self.model.game_state.deleteObjectsFromMap(
-                    self.model.game_state.current_map_name
-                )
-                deleted.extend(
-                    self.model.game_state.deleteObjectsFromMap(None)
-                )
-                for obj in deleted:
-                    obj.delete()
-            self.model.loadMap(self.model.target_map_name)
-            self.setupScripts(self.model.target_map_name)
-            
-            self.model.setActiveMap(self.model.target_map_name, self)          
-            
-            self.model.placeAgents(self)
-            self.model.placePC(self)
-            self.model.updateObjectDB(self)
-            self.model.map_change = False
-            # The PlayerCharacter has an inventory, and also some 
-            # filling of the ready slots in the HUD. 
-            # At this point we sync the contents of the ready slots 
-            # with the contents of the inventory.
-            self.view.hud.inventory = None
-            self.view.hud.initializeInventory()         
-            self.pause(False)
-
-    def setupScripts(self, map_name):
-        """Read scripts for the current map"""
-        self.systems.scripting.reset()
-        self.model.readScriptsOfMap(map_name, self)
-
-    def handleScrolling(self):
-        """
-        Merge kb and mouse related scroll data, limit the speed and
-        move the camera.
-        """
-        #this is how many pxls the camera is moved in one time frame
-        scroll_offset = self.scroll_data["offset"] = [0,0]
- 
-        mouse = self.scroll_data["mouse"]
-        keyboard = self.scroll_data["kb"]
-        speed = self.model.settings.parpg.ScrollSpeed
-
-        #adds a value to the offset depending on the contents of each
-        #  of the controllers: set() removes doubles
-        scroll_direction = set(mouse+keyboard)
-        for direction in scroll_direction:
-            if direction == "up":
-                scroll_offset[0] +=1
-                scroll_offset[1] -=1
-            elif direction == "right":
-                scroll_offset[0] +=1
-                scroll_offset[1] +=1
-            elif direction == "down":
-                scroll_offset[0] -=1
-                scroll_offset[1] +=1
-            elif direction == "left":
-                scroll_offset[0] -=1
-                scroll_offset[1] -=1
-
-        #keep the speed within bounds
-        if scroll_offset[0] > 0: scroll_offset[0] = speed
-        if scroll_offset[0] < 0: scroll_offset[0] = -speed
-        
-        if scroll_offset[1] > 0: scroll_offset[1] = speed
-        if scroll_offset[1] < 0: scroll_offset[1] = -speed
-        
-        #de/activate scrolling
-        if scroll_offset != [0, 0]:
-            self.scroll_timer.start()
-        else: 
-            self.scroll_timer.stop()
-            if not data_drag.dragging:
-                self.resetMouseCursor()
-
-    def nullFunc(self, userdata):
-        """Sample callback for the context menus."""
-        logger.info(userdata)
-
-    def initTalk(self, npc_info):
-        """ Starts the PlayerCharacter talking to an NPC. """
-        # TODO: work more on this when we get NPCData and HeroData straightened
-        # out
-        npc = self.model.game_state.getObjectById(
-            npc_info.general.identifier, 
-            self.model.game_state.current_map_name
-        )
-        npc_behaviour = npc.fifeagent.behaviour
-        npc_pos = npc_behaviour.getLocation().getLayerCoordinates()
-        self.model.game_state.getObjectById("PlayerCharacter").fifeagent.\
-            behaviour.approach(npc_behaviour.agent,
-                               TalkAction(self, npc))
-
-    def getItemActions(self, obj_id):
-        """Given the objects ID, return the text strings and callbacks.
-           @type obj_id: string
-           @param obj_id: ID of object
-           @rtype: list
-           @return: List of text and callbacks"""
-        actions = []
-        obj = self.model.game_state.\
-                        getObjectById(obj_id,
-                                      self.model.game_state.current_map_name)
-        #obj_pos = obj.fifeagent.behaviour.getLocation().getLayerCoordinates()
-        agent = obj.fifeagent.behaviour.agent
-        player = self.model.game_state.getObjectById("PlayerCharacter")
-        is_player = obj.general.identifier == player.general.identifier
-        
-        
-        #TODO: Check all actions to be compatible with the grease components
-        if obj is not None:
-            if obj.dialogue and not is_player:
-                actions.append(["Talk", "Talk", self.initTalk, obj])
-            if obj.characterstats and not is_player:
-                actions.append(["Attack", "Attack", self.nullFunc, obj])
-            if obj.description and obj.description.desc:
-                actions.append(["Examine", "Examine",
-                                player.fifeagent.behaviour.approach, 
-                                agent,
-                                ExamineAction(self, 
-                                              obj_id, obj.description.view_name, 
-                                              obj.description.desc)])
-
-            if obj.change_map:
-                actions.append(["Change Map", "Change Map",
-                   player.fifeagent.behaviour.approach, 
-                   agent,
-                   ChangeMapAction(self, obj.change_map.target_map,
-                                   obj.change_map.target_position)])
-            
-            if obj.lockable:
-                if obj.lockable.closed:
-                    if not obj.lockable.locked:
-                        actions.append(["Open", "Open", 
-                                        player.fifeagent.behaviour.approach,
-                                        agent,
-                                        OpenAction(self, obj)])
-                else:
-                    actions.append(["Close", "Close", 
-                                    player.fifeagent.behaviour.approach,
-                                    agent,
-                                    CloseAction(self, obj)])
-                if obj.lockable.locked:
-                    actions.append(["Unlock", "Unlock", 
-                                    player.fifeagent.behaviour.approach,
-                                    agent,
-                                    UnlockAction(self, obj)])
-                else:
-                    if obj.lockable.closed:
-                        actions.append(["Lock", "Lock", 
-                                        player.fifeagent.behaviour.approach,
-                                        agent,
-                                        LockAction(self, obj)])
-            if obj.container:
-                if obj.characterstats:
-                    #TODO: This is reserved for a possible "Steal" action.
-                    pass                
-                elif not obj.lockable or not obj.lockable.closed:
-                    actions.append(["Examine contents", "Examine Contents",
-                                    player.fifeagent.behaviour.approach,
-                                    agent,
-                                    ExamineContentsAction(self, obj)])
-            if obj.containable:
-                actions.append(["Pick Up", "Pick Up", 
-                                player.fifeagent.behaviour.approach,
-                                agent,
-                                PickUpAction(self, obj)])
-
-        return actions
-    
-    def saveGame(self, *args, **kwargs):
-        """Saves the game state, delegates call to gamemodel.GameModel
-           @return: None"""
-        self.model.pause(False)
-        self.pause(False)
-        self.view.hud.enabled = True
-        self.model.updateObjectDB(self)
-        self.model.save(*args, **kwargs)
-
-    def loadGame(self, *args, **kwargs):
-        """Loads the game state, delegates call to gamemodel.GameModel
-           @return: None"""
-        # Remove all currently loaded maps so we can start fresh
-        self.model.pause(False)
-        self.pause(False)
-        self.view.hud.enabled = True
-        self.model.deleteMaps()
-        for entity in self.entities.copy():
-            entity.delete()
-        self.view.hud.inventory = None
-
-        self.model.load(*args, **kwargs)
-        # Load the current map
-        if self.model.game_state.current_map_name:
-            self.model.loadMap(self.model.game_state.current_map_name)   
-        self.model.placeAgents(self)
-        self.model.placePC(self)
-        self.setupScripts(self.model.game_state.current_map_name)
-        self.view.hud.initializeInventory()          
-
-    def quitGame(self):
-        """Quits the game
-           @return: None"""
-        self.application.listener.quitGame()
-    
-    def pause(self, paused):
-        """Pauses the controller"""
-        super(GameSceneController, self).pause(paused)
-        self.paused = paused
-        if paused:
-            self.scroll_timer.stop()
-    
-    def onCommand(self, command):
-        if(command.getCommandType() == fife.CMD_MOUSE_FOCUS_GAINED):
-            self.has_mouse_focus = True
-        elif(command.getCommandType() == fife.CMD_MOUSE_FOCUS_LOST):
-            self.has_mouse_focus = False
-   
-    def pump(self, dt):
-        """Routine called during each frame. Our main loop is in ./run.py"""
-        # uncomment to instrument
-        # t0 = time.time()
-        if self.paused: 
-            return
-        ControllerBase.pump(self, dt)
-        World.pump(self, dt)
-        self.updateMouse()
-        if self.model.active_map:
-            self.view.highlightFrontObject(self.last_mousecoords)
-            self.view.refreshTopLayerTransparencies()
-            self.handleScrolling()
-        self.handleCommands()
-        # print "%05f" % (time.time()-t0,)
--- a/src/parpg/gamesceneview.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +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 <http://www.gnu.org/licenses/>.
-
-from sounds import SoundEngine
-from viewbase import ViewBase
-from fife import fife
-
-class GameSceneView(ViewBase):
-    """GameSceneView is responsible for drawing the scene"""
-    def __init__(self, engine, model):
-        """Constructor for GameSceneView
-           @param engine: A fife.Engine instance
-           @type engine: fife.Engine
-           @param model: a script.GameModel instance
-           @type model: script.GameModel 
-           """
-        super(GameSceneView, self).__init__(engine, model)
-
-        # init the sound
-        self.sounds = SoundEngine(engine)
-
-        self.hud = None        
-
-        # The current highlighted object
-        self.highlight_obj = None
-     
-        # faded objects in top layer
-        self.faded_objects = set()
-
-    def displayObjectText(self, obj_id, text, time=1000):
-        """Display on screen the text of the object over the object.
-           @type obj_id: id of fife.instance
-           @param obj: id of object to draw over
-           @type text: String
-           @param text: text to display over object
-           @return: None"""
-        try:
-            if obj_id:
-                obj = self.model.active_map.agent_layer.getInstance(obj_id)
-            else:
-                obj = None
-        except RuntimeError as error:
-            if error.args[0].split(',')[0].strip() == "_[NotFound]_":
-                obj = None
-            else:
-                raise
-        if obj:
-            obj.say(str(text), time)
-
-    def onWalk(self, click):
-        """Callback sample for the context menu."""
-        self.hud.hideContainer()
-        self.model.game_state.getObjectById("PlayerCharacter").fifeagent.behaviour.run(click)
-
-    def refreshTopLayerTransparencies(self):
-        """Fade or unfade TopLayer instances if the PlayerCharacter 
-        is under them."""
-        if not self.model.active_map:
-            return
-
-        # get the PlayerCharacter's screen coordinates
-        camera = self.model.active_map.cameras[self.model.active_map.my_cam_id]
-        point = self.model.game_state.getObjectById("PlayerCharacter").fifeagent.\
-                                        behaviour.agent.getLocation()
-        scr_coords = camera.toScreenCoordinates(point.getMapCoordinates())
-
-        # find all instances on TopLayer that fall on those coordinates
-        instances = camera.getMatchingInstances(scr_coords,
-                        self.model.active_map.top_layer)
-        instance_ids = [ instance.getId() for instance in instances ]
-        faded_objects = self.faded_objects
-
-        # fade instances
-        for instance_id in instance_ids:
-            if instance_id not in faded_objects:
-                faded_objects.add(instance_id)
-                self.model.active_map.top_layer.getInstance(instance_id).\
-                        get2dGfxVisual().setTransparency(128)
-
-        # unfade previously faded instances
-        for instance_id in faded_objects.copy():
-            if instance_id not in instance_ids:
-                faded_objects.remove(instance_id)
-                self.model.active_map.top_layer.getInstance(instance_id).\
-                        get2dGfxVisual().setTransparency(0)
-
-
-    #def removeHighlight(self):
-        
-    
-    def highlightFrontObject(self, mouse_coords):
-        """Highlights the object that is at the 
-        current mouse coordinates"""        
-        if not self.model.active_map:
-            return
-        if mouse_coords:
-            front_obj = self.model.getObjectAtCoords(mouse_coords)
-            if front_obj != None:
-                if self.highlight_obj == None \
-                                    or front_obj.getId() != \
-                                    self.highlight_obj:
-                    if self.model.game_state.hasObject(front_obj.getId()):
-                        self.displayObjectText(self.highlight_obj, "")
-                    self.model.active_map.outline_renderer.removeAllOutlines()
-                    self.highlight_obj = front_obj.getId()
-                    self.model.active_map.outline_renderer.addOutlined(
-                                                    front_obj, 
-                                                    0,
-                                                    137, 255, 2)
-                    # get the text
-                    item = self.model.objectActive(self.highlight_obj)
-                    if item is not None:
-                        self.displayObjectText(self.highlight_obj, 
-                                                    item.description.view_name)
-            else:
-                self.model.active_map.outline_renderer.removeAllOutlines()
-                self.highlight_obj = None  
-           
-
-    def moveCamera(self, direction):
-        """Move the camera in the given direction.
-        @type direction: list of two integers
-        @param direction: the two integers can be 1, -1, or 0
-        @return: None """  
-        
-        if 'cameras' in dir(self.model.active_map):
-            cam = self.model.active_map.cameras[self.model.active_map.my_cam_id]
-            location = cam.getLocation()
-            position = location.getMapCoordinates()
-            
-            #how many pixls to move by each call
-            move_by = 1
-            #create a new DoublePoint3D and add it to position DoublePoint3D
-            new_x, new_y = move_by * direction[0], move_by * direction[1]
-
-            position_offset = fife.DoublePoint3D(int(new_x), int(new_y))
-            position += position_offset
-            
-            #give location the new position
-            location.setMapCoordinates(position)
-
-            #detach the camera from any objects
-            cam.detach()
-            #move the camera to the new location
-            cam.setLocation(location)
-            
-            
--- a/src/parpg/gamestate.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +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 <http://www.gnu.org/licenses/>.
-
-from parpg.quest_engine import QuestEngine
-
-class GameState(object):
-    """This class holds the current state of the game."""
-    def __init__(self, quests_dir = None):
-        self.player_character = None
-        self.quest_engine = QuestEngine(quests_dir)
-        self.quest_engine.readQuests()
-        self.objects = {}
-        self.object_ids = {}
-        self.current_map_name = None
-        self.maps = {}
-        self.npcs_met = set()
-        self.funcs = {
-            "meet":self.meet,
-            "met":self.met
-        }
-        
-        
-    def addObject(self, object_id, map_id, game_object):
-        """Adds an object to the objects and object_ids
-        dictionaries.
-        @param object_id: ID of the object
-        @type object_id: str
-        @param map_id: ID of the map the object is on. 
-        If the object is in a container this has to be None
-        @type map_id: str or None
-        @param object: object to be added
-        @type object: GameObject
-        """
-        if not self.object_ids.has_key(object_id):
-            if not self.objects.has_key(map_id):
-                self.objects[map_id] = {}
-            self.objects[map_id][object_id] = game_object
-            self.object_ids[object_id] = map_id
-    
-    def deleteObject(self, object_id):
-        """Removes an object from the dictionaries
-        @param object_id: ID of the object
-        @type object_id: str
-        @returns The deleted object
-        """
-        if self.hasObject(object_id):
-            map_id = self.getMapOfObject(object_id)
-            if map_id:
-                inst = self.maps[map_id].agent_layer.getInstance(object_id)
-                self.maps[map_id].agent_layer.deleteInstance(inst)
-            obj = self.objects[map_id][object_id]
-            del self.objects[map_id][object_id]
-            del self.object_ids[object_id]
-            return obj
-        return None
-            
-            
-    def getObjectsFromMap(self, map_id):
-        """Gets all objects that are currently on the given map.
-           @type map: String
-           @param map: The map name.
-           @returns: The list of objects on this map. Or an empty list"""
-        return [i for i in self.getObjectDictOfMap(map_id).values()
-                                    if map_id in self.objects]
-    
-    
-    def getObjectDictOfMap(self, map_id):
-        if map_id in self.objects:
-            return self.objects[map_id]
-        return {}
-    
-    def deleteObjectsFromMap(self, map_id):
-        """Deletes all objects of the given map.
-           @type map: String
-           @param map: The map name.
-           @returns: None"""
-        deleted_objs = []
-        if map_id in self.objects:
-            for obj in self.objects[map_id].copy():
-                deleted_objs.append(self.deleteObject(obj))
-        return deleted_objs
-    
-    def hasObject(self, object_id):
-        """Check if an object with the given id is present 
-        @param object_id: ID of the object
-        @type object_id: str
-        @return: True if there is an object False if not
-        """
-        return self.object_ids.has_key(object_id)
-    
-    def getMapOfObject(self, object_id):
-        """Returns the map the object is on.
-        @param object_id: ID of the object
-        @type object_id: str
-        @return: Name of the map the object is on. 
-        If there is no such object or the object is in a container None is returned
-        """
-        if self.object_ids.has_key(object_id):
-            return self.object_ids[object_id]
-        return None
-    
-    def getObjectById(self, obj_id, map_id = None):
-        """Gets an object by its object id and map id
-           @type obj_id: String
-           @param obj_id: The id of the object.
-           @type map_id: String
-           @param map_id: It id of the map containing the object.
-           @returns: The object or None."""
-        if not map_id:
-            map_id = self.getMapOfObject(obj_id)
-        if not map_id in self.objects:
-            self.objects[map_id] = {}
-        if obj_id in self.objects[map_id]:
-            return self.objects[map_id][obj_id]
-    
-    def clearObjects(self):
-        """Delete all objects from the state
-        """
-        self.objects = {}
-        self.object_ids = {}
-        
-    def getStateForSaving(self):
-        """Prepares state for saving
-        @type state: dictionary
-        @param state: State of the object  
-        """
-        ret_dict = {}
-        ret_dict["CurrentMap"] = self.current_map_name
-        ret_dict["Quests"] = self.quest_engine.getStateForSaving()
-        ret_dict["NPCsMet"] = self.npcs_met
-        return ret_dict
-
-    def restoreFromState(self, state):
-        """Restores the state"""
-        self.current_map_name = state["CurrentMap"]
-        self.npcs_met = state["NPCsMet"]
-        self.quest_engine.readQuests()
-        self.quest_engine.restoreFromState(state["Quests"])
-
-    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.npcs_met:
-            # we could raise an error here, but should probably be a warn
-            # raise RuntimeError("I already know %s" % npc)
-            return
-        self.npcs_met.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.npcs_met
\ No newline at end of file
--- a/src/parpg/gui/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-from fife.extensions import pychan
-
-from .inventorygui import EquipmentSlot, InventoryGrid
-from .spinners import Spinner, IntSpinner
-from .tabwidget import TabWidget
-
-pychan.registerWidget(EquipmentSlot)
-pychan.registerWidget(InventoryGrid)
-pychan.registerWidget(Spinner)
-pychan.registerWidget(IntSpinner)
-pychan.registerWidget(TabWidget)
\ No newline at end of file
--- a/src/parpg/gui/actionsbox.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +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 <http://www.gnu.org/licenses/>.
-
-"""Widget for displaying actions"""
-
-from fife.extensions import pychan
-from fife.extensions.pychan import ScrollArea
-from fife.extensions.pychan import VBox
-
-class ActionsBox(ScrollArea):
-    def __init__(self, **kwargs):
-        ScrollArea.__init__(self, **kwargs)
-        self.ContentBox = VBox(name = "ActionsContentBox", is_focusable=False)
-        self.addChild(self.ContentBox)
-    
-    def refresh(self):
-        """Refresh the actions box so that it displays the contents of
-        self.actions_text
-        @return: None"""
-        self.adaptLayout()
-        self.vertical_scroll_amount = self.getVerticalMaxScroll()
-
-    def addAction(self, action):
-        """Add an action to the actions box.
-        @type action: (unicode) string
-        @param action: The text that you want to display in the actions box
-        @return: None"""      
-      
-        if not type(action) is unicode:
-            action = unicode(action)
-        action_label = pychan.widgets.Label(text = action, wrap_text = True)
-        action_label.max_width = self.ContentBox.width
-        self.ContentBox.addChild(action_label)
-        self.refresh()
-    
-    def addDialog(self, name, text):
-        """Add a dialog text to the actions box. Prints first the name and then, indented to the right, the text.
-        @type name: (unicode) string
-        @param action: The name of the character that spoke
-        @type text:: (unicode) string
-        @param text: The text that was said
-        @return: None"""        
-        if not type(name) is unicode:
-            name = unicode(name)
-        if not type(text) is unicode:
-            text = unicode(text)
-        
-        
-        name_label = pychan.widgets.Label(text = name, wrap_text = True)
-        self.ContentBox.addChild(name_label)
-        text_box = pychan.widgets.HBox()
-        spacer = pychan.widgets.Label()
-        spacer.min_width = int(self.ContentBox.width * 0.05)
-        spacer.max_width = int(self.ContentBox.width * 0.05)
-        text_box.addChild(spacer)
-        text_label = pychan.widgets.Label(text = text, wrap_text = True)
-        text_label.max_width = int(self.ContentBox.width * 0.95)
-        text_box.addChild(text_label)
-        self.ContentBox.addChild(text_box)
-        self.refresh()
-        
--- a/src/parpg/gui/charactercreationview.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-from fife.extensions import pychan
-from fife.extensions.pychan.widgets import Label, HBox
-
-from parpg import vfs
-from parpg.gui.spinner import IntSpinner
-
-class CharacterCreationView(object):
-    def __init__(self, xml_script_path='gui/character_creation.xml'):
-        xml_file = vfs.VFS.open(xml_script_path)
-        self.gui = pychan.loadXML(xml_file)
-    
-    def createStatisticList(self, statistics):
-        statistics_list = self.gui.findChild(name='statisticsList')
-        # Start with an empty list.
-        statistics_list.removeAllChildren()
-        for statistic in statistics:
-            name = statistic.long_name
-            hbox = HBox()
-            hbox.opaque = 0
-            label = Label(text=name)
-            spinner = IntSpinner(lower_limit=0, upper_limit=100)
-            hbox.addChildren(label, spinner)
-            statistics_list.addChildren(hbox)
-    
-    def createTraitsList(self, traits):
-        pass
-    
-    def updateMessageArea(self, message):
-        message_area = self.gui.findChild(name='messageArea')
-        message_area.text = unicode(message)
\ No newline at end of file
--- a/src/parpg/gui/containergui.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-from fife.extensions.pychan.tools import callbackWithArguments as cbwa
-
-from parpg.gui.containergui_base import ContainerGUIBase
-from parpg.gui import drag_drop_data as data_drag
-from parpg.components import container
-
-class ContainerGUI(ContainerGUIBase):
-    def __init__(self, controller, title, container):
-        """A class to create a window showing the contents of a container.
-           @param controller: The current Controller
-           @type controller: Class derived from ControllerBase
-           @param title: The title of the window
-           @type title: string
-           @param container: A container to represent
-           @type container: parpg.components.Container
-           @return: None"""
-        super(ContainerGUI, self).__init__(controller, "gui/container_base.xml")
-        self.gui.findChild(name="topWindow").title = title
-        
-        self.empty_images = dict()
-        self.container = container
-        self.events_to_map = {}        
-        self.buttons = ("Slot1", "Slot2", "Slot3",
-                        "Slot4", "Slot5", "Slot6",
-                        "Slot7", "Slot8", "Slot9")         
-    
-    def updateImages(self):
-        for index, button in enumerate(self.buttons):
-            widget = self.gui.findChild(name=button)            
-            widget.item = container.get_item(self.container, index)
-            self.updateImage(widget) 
-               
-    def updateImage(self, button):
-        if (button.item == None):
-            image = self.empty_images[button.name]
-        else:
-            image = button.item.image
-        button.up_image = image
-        button.down_image = image
-        button.hover_image = image
-
-    def dragObject(self, obj):
-        """Drag the selected object.
-           @type obj: string
-           @param obj: The name of the object within
-                       the dictionary 'self.buttons'
-           @return: None"""
-        # get the widget from the gui with the name obj
-        drag_widget = self.gui.findChild(name = obj)
-        drag_item = drag_widget.item
-        # only drag if the widget is not empty
-        if (drag_item != None):
-            # get the item that the widget is 'storing'
-            data_drag.dragged_item = drag_widget.item
-            # get the up and down images of the widget
-            up_image = drag_widget.up_image
-            down_image = drag_widget.down_image
-            self.setDragData(drag_widget.item, down_image, up_image)
-            container.take_item(self.container, drag_widget.item.slot)
-            
-            # after dragging the 'item', set the widgets' images
-            # so that it has it's default 'empty' images
-            drag_widget.item = None
-            self.updateImage(drag_widget)
-            
-    def dropObject(self, obj):
-        """Drops the object being dropped
-           @type obj: string
-           @param obj: The name of the object within
-                       the dictionary 'self.buttons' 
-           @return: None"""
-        try:
-            drop_widget = self.gui.findChild(name = obj)
-            drop_index = drop_widget.index
-            replace_item = None
-    
-            if data_drag.dragging:
-                drag_item = data_drag.dragged_item
-                #this will get the replacement item and the data for drag_drop if
-                ## there is an item all ready occupying the slot
-                replace_item = (
-                    container.put_item(self.container, drag_item, drop_index)
-                )
-                
-            #if there was no item the stop dragging and reset cursor
-            if replace_item:
-                up_image = drop_widget.up_image
-                down_image = drop_widget.down_image
-                self.setDragData(replace_item, down_image, up_image)
-            else:
-                data_drag.dragging = False
-                #reset the mouse cursor to the normal cursor
-                self.controller.resetMouseCursor()
-            drop_widget.item = drag_item
-            self.updateImage(drop_widget)
-        except (container.BulkLimitError):
-            #Do we want to notify the player why the item can't be dropped?
-            pass
-        
-    def showContainer(self):
-        """Show the container
-           @return: None"""
-        # Prepare slots 1 through 9
-        empty_image = "gui/inv_images/inv_backpack.png"
-        slot_count = 9
-        for counter in range(1, slot_count+1):
-            slot_name = "Slot%i" % counter
-            index = counter - 1
-            self.empty_images[slot_name] = empty_image
-            widget = self.gui.findChild(name=slot_name)
-            widget.item = container.get_item(self.container, index)
-            widget.index = index
-            self.updateImage(widget)
-            self.events_to_map[slot_name] = cbwa(self.dragDrop, slot_name)
-            self.events_to_map[slot_name + "/mouseReleased"] = \
-                                            self.showContextMenu
-
-        self.gui.mapEvents(self.events_to_map)
-        self.gui.show()
-        
-    def hideContainer(self):
-        """Hide the container
-           @return: None"""
-        if self.gui.isVisible():
-            self.gui.hide()      
--- a/src/parpg/gui/containergui_base.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-from copy import deepcopy
-from types import StringTypes
-
-from fife import fife
-from fife.extensions import pychan
-
-from parpg import vfs
-from parpg.gui import drag_drop_data as data_drag
-from parpg.entities.action import ACTIONS
-from parpg.entities import General
-
-class ContainerGUIBase(object):
-    """
-    Base class for windows that show the content of a container
-    """
-
-
-    def __init__(self, controller, gui_file):
-        self.controller = controller
-        if isinstance(gui_file, pychan.Widget):
-            self.gui = gui_file
-        elif isinstance(gui_file, StringTypes):
-            xml_file = vfs.VFS.open(gui_file)
-            self.gui = pychan.loadXML(xml_file)
-        else:
-            self.gui = pychan.loadXML(gui_file)
-
-    def dragDrop(self, obj):
-        """Decide whether to drag or drop the image.
-           @type obj: string
-           @param obj: The name of the object within 
-                       the dictionary 'self.buttons'
-           @return: None"""
-        if(data_drag.dragging == True):
-            self.dropObject(obj)
-        elif(data_drag.dragging == False):
-            self.dragObject(obj)
-                
-    def dragObject(self, obj):
-        """Drag the selected object.
-           @type obj: string
-           @param obj: The name of the object within
-                       the dictionary 'self.buttons'
-           @return: None"""           
-        pass
-       
-    def dropObject(self, obj):
-        """Drops the object being dropped
-           @type obj: string
-           @param obj: The name of the object within
-                       the dictionary 'self.buttons' 
-           @return: None"""
-        pass    
-    
-
-    def setDragData(self, drag_item, down_image, up_image):
-        """Set the dragging data"""
-        # set the mouse cursor to be the widget's image
-        self.controller.setMouseCursor(up_image.source, down_image.source)
-        data_drag.dragged_item = drag_item
-        data_drag.dragged_image = up_image.source
-        data_drag.dragging = True
-        
-    def createMenuItems(self, item, actions):
-        """Creates context menu items for all classes based on ContainerGUI"""
-        assert(isinstance(actions, dict))
-        assert(isinstance(item, General))
-        menu_actions = []
-        item_name = item.description.view_name
-        if not actions.has_key("Look"):
-            look_action = actions["Look"] = {}
-            look_action["text"] = item.description.desc
-        if item.container and not actions.has_key("ExamineContents"):
-            actions["ExamineContents"] = {}
-        for action_name in actions:
-            display_name = action_name
-            if action_name in ACTIONS:
-                param_dict = {}
-                param_dict["controller"] = self.controller
-                param_dict["commands"] = {}
-                if action_name == "Look":
-                    param_dict["examine_name"] = item_name
-                    param_dict["examine_desc"] = actions[action_name].\
-                                                                pop("text")
-                if action_name == "Read":
-                    param_dict["text_name"] = item_name
-                    param_dict["text"] = ""
-                if action_name == "Use":
-                    param_dict["item"] = item
-                    display_name = actions[action_name].pop("text")
-                if action_name == "ExamineContents":
-                    param_dict["container"] = item
-                    display_name = "Examine Contents"
-                if action_name == "BrewBeer":
-                    param_dict["pot"] = item
-                    display_name = "Brew beer"
-                if actions[action_name]:
-                    param_dict.update(actions[action_name])
-                menu_actions.append([action_name, 
-                                     display_name, 
-                                     self.executeMenuItem, 
-                                     ACTIONS[action_name]\
-                                                (**param_dict)])        
-        return menu_actions
-
-    def showContextMenu(self, event, widget):
-        """Decide whether to drag or drop the image.
-           @type obj: string
-           @param obj: The name of the object within 
-                       the dictionary 'self.buttons'
-           @return: None"""
-        if event.getButton() == event.RIGHT:
-            item = widget.item
-            if item:
-                if not isinstance(item, General):
-                    item = item.entity
-                actions = {}
-                if item.usable:
-                    actions = deepcopy(item.usable.actions)
-                x_pos, y_pos = widget.getAbsolutePos()
-                x_pos += event.getX()
-                y_pos += event.getY()
-                menu_actions = self.createMenuItems(item, actions)
-                self.controller.view.hud.hideContextMenu()
-                self.controller.view.hud.showContextMenu(menu_actions,
-                                                 (x_pos, 
-                                                  y_pos)
-                                                  )
-
-    def executeMenuItem(self, action):
-        """Executes the items action
-        @param action: The action to run
-        @type action: Class derived from parpg.entities.action.Action
-        """
-        action.execute()
-    
-    def updateImages(self):
-        pass
--- a/src/parpg/gui/dialogs.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +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 <http://www.gnu.org/licenses/>.
-from fife.extensions import pychan
-
-from parpg import vfs
-
-class RestartDialog(object):
-    def __init__(self, settings):
-        self.settings = settings
-        xml_file = vfs.VFS.open('gui/restart_dialog.xml')
-        self.window = pychan.loadXML(xml_file)
-        self.window.mapEvents({'closeButton': self.hide})
-
-    def hide(self):
-        self.window.hide()
-
-    def show(self):
-        self.window.show()
--- a/src/parpg/gui/dialoguegui.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +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 <http://www.gnu.org/licenses/>.
-import logging
-
-from fife import fife
-from fife.extensions import pychan
-from fife.extensions.pychan import widgets
-
-from parpg import vfs
-from parpg.dialogueprocessor import DialogueProcessor
-
-logger = logging.getLogger('dialoguegui')
-
-class DialogueGUI(object):
-    """Window that handles the dialogues."""
-    _logger = logging.getLogger('dialoguegui.DialogueGUI')
-    
-    def __init__(self, controller, npc, quest_engine, met_fnc, meet_fnc, 
-                 has_fnc, player_character):
-        self.active = False
-        self.controller = controller
-        xml_file = vfs.VFS.open('gui/dialogue.xml')
-        self.dialogue_gui = pychan.loadXML(xml_file)
-        self.npc = npc
-        # TODO Technomage 2010-11-10: the QuestEngine should probably be
-        #     a singleton-like object, which would avoid all of this instance
-        #     handling.
-        self.quest_engine = quest_engine
-        self.player_character = player_character
-        self.met_fnc = met_fnc
-        self.meet_fnc = meet_fnc
-        self.pc_has_fnc = lambda slot_or_type:\
-            has_fnc(player_character.container, slot_or_type)
-        self.npc_has_fnc = lambda slot_or_type:\
-            has_fnc(npc.container, slot_or_type)
-    
-    def initiateDialogue(self):
-        """Callback for starting a quest"""
-        self.active = True
-        stats_label = self.dialogue_gui.findChild(name='stats_label')
-        stats_label.text = u'Name: John Doe\nAn unnamed one'
-        events = {
-            'end_button': self.handleEnd
-        }
-        self.dialogue_gui.mapEvents(events)
-        self.dialogue_gui.show()
-        self.setNpcName(self.npc.description.view_name)
-        self.setAvatarImage(self.npc.dialogue.dialogue.avatar_path)
-        
-        game_state = {'npc': self.npc, 'pc': self.player_character,
-                      'quest': self.quest_engine, 
-                      'met': self.met_fnc, 'meet': self.meet_fnc, 
-                      'pc_has': self.pc_has_fnc, 'npc_has': self.npc_has_fnc,
-                      'model': self.controller.model,
-                      }
-        try:
-            self.dialogue_processor = DialogueProcessor(self.npc.dialogue.dialogue,
-                                                        game_state)
-            self.dialogue_processor.initiateDialogue()
-        except (TypeError) as error:
-            self._logger.error(str(error))
-        else:
-            self.continueDialogue()
-    
-    def setDialogueText(self, text):
-        """Set the displayed dialogue text.
-           @param text: text to display."""
-        text = unicode(text)
-        speech = self.dialogue_gui.findChild(name='speech')
-        # to append text to npc speech box, uncomment the following line
-        #speech.text = speech.text + "\n-----\n" + unicode(say)
-        speech.text = text
-        self._logger.debug('set dialogue text to "{0}"'.format(text))
-    
-    def continueDialogue(self):
-        """Display the dialogue text and responses for the current
-           L{DialogueSection}."""
-        dialogue_processor = self.dialogue_processor
-        dialogue_text = dialogue_processor.getCurrentDialogueSection().text
-        self.setDialogueText(dialogue_text)
-        self.responses = dialogue_processor.continueDialogue()
-        self.setResponses(self.responses)
-    
-    def handleEntered(self, *args):
-        """Callback for when user hovers over response label."""
-        pass
-    
-    def handleExited(self, *args):
-        """Callback for when user hovers out of response label."""
-        pass
-    
-    def handleClicked(self, *args):
-        """Handle a response being clicked."""
-        response_n = int(args[0].name.replace('response', ''))
-        response = self.responses[response_n]
-        dialogue_processor = self.dialogue_processor
-        dialogue_processor.reply(response)
-        if (not dialogue_processor.in_dialogue):
-            self.handleEnd()
-        else:
-            self.continueDialogue()
-    
-    def handleEnd(self):
-        """Handle the end of the conversation being reached, either from the
-           GUI or from within the conversation itself."""
-        self.dialogue_gui.hide()
-        self.responses = []
-        self.npc.fifeagent.behaviour.state = 1
-        self.npc.fifeagent.behaviour.idle()
-        self.active = False
-    
-    def setNpcName(self, name):
-        """Set the NPC name to display on the dialogue GUI.
-           @param name: name of the NPC to set
-           @type name: basestring"""
-        name = unicode(name)
-        stats_label = self.dialogue_gui.findChild(name='stats_label')
-        try:
-            (first_name, desc) = name.split(" ", 1)
-            stats_label.text = u'Name: ' + first_name + "\n" + desc
-        except ValueError:
-            stats_label.text = u'Name: ' + name
-        
-        self.dialogue_gui.title = name
-        self._logger.debug('set NPC name to "{0}"'.format(name))
-    
-    def setAvatarImage(self, image_path):
-        """Set the NPC avatar image to display on the dialogue GUI
-           @param image_path: filepath to the avatar image
-           @type image_path: basestring"""
-        avatar_image = self.dialogue_gui.findChild(name='npc_avatar')
-        avatar_image.image = image_path
-    
-    def setResponses(self, dialogue_responses):
-        """Creates the list of clickable response labels and sets their
-           respective on-click callbacks.
-           @param responses: list of L{DialogueResponses} from the
-               L{DialogueProcessor}
-           @type responses: list of L{DialogueResponses}"""
-        choices_list = self.dialogue_gui.findChild(name='choices_list')
-        choices_list.removeAllChildren()
-        for index, response in enumerate(dialogue_responses):
-            button = widgets.Label(
-                name="response{0}".format(index),
-                text=unicode(response.text),
-                hexpand="1",
-                min_size=(100,16),
-                max_size=(490,48),
-                position_technique='center:center'
-            )
-            button.margins = (5, 5)
-            button.background_color = fife.Color(0, 0, 0)
-            button.color = fife.Color(0, 255, 0)
-            button.border_size = 0
-            button.wrap_text = 1
-            button.capture(lambda button=button: self.handleEntered(button),
-                           event_name='mouseEntered')
-            button.capture(lambda button=button: self.handleExited(button),
-                           event_name='mouseExited')
-            button.capture(lambda button=button: self.handleClicked(button),
-                           event_name='mouseClicked')
-            choices_list.addChild(button)
-            self.dialogue_gui.adaptLayout(True)
-            self._logger.debug(
-                'added {0} to response choice list'.format(response)
-            )
--- a/src/parpg/gui/drag_drop_data.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +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 <http://www.gnu.org/licenses/>.
-
-"""
-This contains the data that tells the GUI whether something is being dragged, dropped etc.
-It is in one place to allow communication between multiple windows
-"""
-dragging = False
-dragged_image = None
-dragged_item = None
--- a/src/parpg/gui/filebrowser.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-import sys
-import os
-import logging
-
-from fife.extensions import pychan
-from fife.extensions.pychan import widgets
-
-from parpg import vfs
-
-logger = logging.getLogger('filebrowser')
-
-def u2s(string):
-    # TODO: cryptic function name
-    return string.encode(sys.getfilesystemencoding())
-
-class FileBrowser(object):
-    """FileBrowser displays directory and file listings from the vfs.
-       The file_selected parameter is a callback invoked when a file selection
-       has been made; its signature must be file_selected(path,filename). If
-       select_dir is set, file_selected's filename parameter should be optional.
-       The save_file option provides a box for supplying a new filename that
-       doesn't exist yet. The select_dir option allows directories to be
-       selected as well as files."""
-    def __init__(self, engine, settings, file_selected, gui_xml_path,
-                 close_callback=None, save_file=False, select_dir=False, 
-                 extensions=('.dat',)):
-        self.engine = engine
-        self.settings = settings
-        self.file_selected = file_selected
-
-        self._widget = None
-        self.save_file = save_file
-        self.select_dir = select_dir
-        self.close_callback = close_callback
-        self.gui_xml_path = gui_xml_path 
-        
-        self.extensions = extensions
-        # FIXME M. George Hansen 2011-06-06: Not sure that user_path is set
-        #     correctly atm. Plus, I don't think that this should be
-        #     hard-coded.
-        self.path = os.path.join(self.settings.user_path, 'saves')
-        self.dir_list = []
-        self.file_list = []
-        
-    def close(self):
-        """Closes the browser"""        
-        self._widget.hide()
-        if self.close_callback:
-            self.close_callback()
-    
-    def showBrowser(self):
-        """Shows the file dialog browser"""
-        if self._widget:
-            self._widget.show()
-            return
-        xml_file = vfs.VFS.open(self.gui_xml_path)
-        self._widget = pychan.loadXML(xml_file)
-        self._widget.mapEvents({
-            'dirList'       : self._setPath,
-            'selectButton'  : self._selectFile,
-            'closeButton'   : self.close
-        })
-        self._setPath()
-        if self.save_file:
-            self._file_entry = widgets.TextField(name='saveField', text=u'')    
-            self._widget.findChild(name="fileColumn").\
-                addChild(self._file_entry)
-        self._widget.show()
-
-    def _setPath(self):
-        """Path change callback."""
-        selection = self._widget.collectData('dirList')
-        if not (selection < 0):
-            new_dir = u2s(self.dir_list[selection])
-            lst = self.path.split('/')
-            if new_dir == '..' and lst[-1] != '..' and lst[-1] != '.':
-                lst.pop()
-            else:
-                lst.append(new_dir)
-            self.path = '/'.join(lst)
-            
-        def decodeList(list):
-            fs_encoding = sys.getfilesystemencoding()
-            if fs_encoding is None: fs_encoding = "ascii"
-        
-            new_list = []
-            for i in list:
-                try:
-                    new_list.append(unicode(i, fs_encoding))
-                except:
-                    new_list.append(unicode(i, fs_encoding, 'replace'))
-                    logger.debug("WARNING: Could not decode item:\n"
-                                        "{0}".format(i))
-            return new_list
-            
-        
-
-        self.dir_list = []
-        self.file_list = []
-        
-        dir_list = ('..',) + filter(lambda d: not d.startswith('.'), \
-                                    self.engine.getVFS().\
-                                    listDirectories(self.path))
-        file_list = filter(lambda f: f.split('.')[-1] in self.extensions, \
-                           self.engine.getVFS().listFiles(self.path))
-                
-        self.dir_list = decodeList(dir_list)
-        self.file_list = decodeList(file_list)
-        self._widget.distributeInitialData({
-            'dirList'  : self.dir_list,
-            'fileList' : self.file_list
-        })
-
-    def _selectFile(self):
-        """ File selection callback. """
-        self._widget.hide()
-        selection = self._widget.collectData('fileList')
-
-        if self.save_file:
-            data = self._widget.collectData('saveField')
-            if data:
-                if (data.endswith(".dat")):
-                    self.file_selected(self.path, \
-                                u2s(self._widget.collectData('saveField')))
-                else:
-                    self.file_selected(self.path, 
-                                       u2s(self._widget.collectData('saveField')) + '.dat')
-                return
-            
-
-        if selection >= 0 and selection < len(self.file_list):
-            self.file_selected(self.path, u2s(self.file_list[selection]))
-            return
-        
-        if self.select_dir:
-            self.file_selected(self.path)
-            return
-
-        logger.error('no selection')
-
-    def _warningMessage(self):
-        """Shows the warning message dialog when a file with a
-           faulty extension was selected."""
-        window = widgets.Window(title="Warning")
-        text = "Please save the file as a .dat"
-        label = widgets.Label(text=text)
-        ok_button = widgets.Button(name="ok_button", text="Ok")
-        window.addChildren([label, ok_button])
-        window.mapEvents({'ok_button':window.hide})
-        window.show()
--- a/src/parpg/gui/hud.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,514 +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 <http://www.gnu.org/licenses/>.
-
-import os
-import logging
-
-from fife.extensions import pychan
-from fife.extensions.pychan.tools import callbackWithArguments as cbwa
-
-from parpg import vfs
-from parpg.gui.filebrowser import FileBrowser
-from parpg.gui.menus import ContextMenu, SettingsMenu
-from parpg.gui.popups import ExaminePopup
-from parpg.gui.containergui import ContainerGUI
-from parpg.gui.dialoguegui import DialogueGUI
-from parpg.gui import drag_drop_data as data_drag
-from parpg.gui.inventorygui import CharacterGUI
-from actionsbox import ActionsBox
-from parpg.entities.action import DropItemAction
-from parpg.components import container
-
-logger = logging.getLogger('hud')
-class Hud(object):
-    """Main Hud class"""
-    def __init__(self, controller, settings, callbacks):
-        """Initialise the instance.
-           @type controller: Class derived from ControllerBase
-           @param controller: The current controller
-           @type settings: settings.Setting
-           @param settings: The settings
-           @type inv_model: dict
-           @type callbacks: dict
-           @param callbacks: a dict of callbacks
-               saveGame: called when the user clicks on Save
-               loadGame: called when the user clicks on Load
-               quitGame: called when the user clicks on Quit
-           @return: None"""
-
-        # TODO: perhaps this should not be hard-coded here
-        self.settings = settings
-        pychan.registerWidget(ActionsBox)
-        
-        xml_file = vfs.VFS.open('gui/hud.xml')
-        self.hud = pychan.loadXML(xml_file)
-
-        self.controller = controller
-        self.engine = controller.engine
-        self.model = controller.model
-        self.inventory = None
-        self.character_screen = None
-
-        self.save_game_callback = callbacks['saveGame']
-        self.load_game_callback = callbacks['loadGame']
-        self.quit_callback      = callbacks['quitGame']
-
-        self.box_container = None
-        self.examine_box = None
-        self.context_menu = None
-        self.help_dialog = None
-        self.events_to_map = None
-        self.main_menu = None
-        self.menu_events = None
-        self.quit_window = None
-        self.bottom_panel = self.hud.findChild(name="mainHudWindow")
-        
-        self.actions_box = self.hud.findChild(name="actionsBox")
-        self.menu_displayed = False
-        self.inventory_storage = None
-        self.initializeHud()
-        self.initializeMainMenu()
-        self.initializeContextMenu()
-        self.initializeHelpMenu()
-        self.initializeEvents()
-        self.initializeQuitDialog()
-        self.initializeSettingsMenu()
-    
-    def _getEnabled(self):
-        """"Returns whether the gui widget is enabled or not"""
-        return self.hud.real_widget.isEnabled()
-    
-    def _setEnabled(self, enabled):
-        """"Sets whether the gui widget is enabled or not"""
-        self.hud.real_widget.setEnabled(enabled)
-        childs = self.hud.getNamedChildren()
-        for child_list in childs.itervalues():
-            for child in child_list:
-                child.real_widget.setEnabled(enabled)
-    
-    enabled = property(_getEnabled, _setEnabled)
-        
-    def initializeHud(self):
-        """Initialize and show the main HUD
-           @return: None"""
-        self.events_to_map = {"menuButton":self.displayMenu, }
-        self.hud.mapEvents(self.events_to_map) 
-        # set HUD size according to screen size
-        screen_width = self.engine.getSettings().getScreenWidth()
-        self.hud.findChild(name="mainHudWindow").size = (screen_width, 65)
-        self.hud.findChild(name="inventoryButton").position = \
-                                                    (screen_width-59, 7)
-        # add ready slots
-        ready1 = self.hud.findChild(name='hudReady1')
-        ready2 = self.hud.findChild(name='hudReady2')
-        ready3 = self.hud.findChild(name='hudReady3')
-        ready4 = self.hud.findChild(name='hudReady4')
-
-        if (screen_width <=800) :
-            gap = 0
-        else :
-            gap = 40
-        ready1.position = (160+gap, 7)
-        ready2.position = (220+gap, 7)
-        ready3.position = (screen_width-180-gap, 7)
-        ready4.position = (screen_width-120-gap, 7)
-        self.actions_box.position = (280+gap, 5)
-        actions_width = screen_width - 470 - 2*gap
-
-        self.actions_box.ContentBox.min_width = actions_width
-        self.actions_box.ContentBox.max_width = actions_width
-        
-        # and finally add an actions box
-        self.actions_box.min_size = (actions_width, 55)
-        self.actions_box.max_size = (actions_width, 55)
-        # now it should be OK to display it all
-        self.showHUD()
-        
-    def addAction(self, action):
-        """Add an action to the actions box.
-           @type action: (unicode) string
-           @param action: The text that you want to display in the actions box
-           @return: None"""    
-        self.actions_box.addAction(action)
-
-    def showHUD(self):
-        """Show the HUD.
-           @return: None"""
-        self.hud.show()
-        self.enabled = True
-
-    def hideHUD(self):
-        """Hide the HUD.
-           @return: None"""
-        self.hud.hide()
-        self.enabled = False
-
-    def initializeInventory(self):
-        """Initialize the inventory"""
-        if not self.inventory:
-            xml_file = vfs.VFS.open('gui/inventory.xml')
-            player = self.model.game_state.getObjectById("PlayerCharacter")
-            self.inventory = CharacterGUI(self.controller, xml_file, 
-                                          player.container, player.equip, None)
-#        inv_callbacks = {
-#            'refreshReadyImages': self.refreshReadyImages,
-#            'toggleInventoryButton': self.toggleInventoryButton,
-#        }
-#        self.inventory_storage = \
-#            self.model.game_state.getObjectById("PlayerCharacter").fifeagent.inventory
-#        if self.inventory == None:
-#            self.inventory = inventorygui.InventoryGUI(self.controller,
-#                                                       self.inventory_storage,
-#                                                       inv_callbacks)
-#        else:
-#            self.inventory.inventory_storage = self.inventory_storage
-#        self.refreshReadyImages()
-    
-    def initializeCharacterScreen(self):
-        """Initialize the character screen."""
-        # TODO Technomage 2010-12-24: 
-        if not self.character_screen:
-            xml_file = vfs.VFS.open('gui/character_screen.xml')
-            self.character_screen = pychan.loadXML(xml_file)
-    
-    def initializeContextMenu(self):
-        """Initialize the Context Menu
-           @return: None"""
-        self.context_menu = ContextMenu(self.engine, [], (0, 0))
-
-    def showContextMenu(self, data, pos):
-        """Display the Context Menu with model at pos
-           @type model: list
-           @param model: model to pass to context menu
-           @type pos: tuple
-           @param pos: tuple of x and y coordinates
-           @return: None"""
-        self.context_menu = ContextMenu(self.engine, data, pos)
-        self.context_menu.show()
-
-    def hideContextMenu(self):
-        """Hides the context menu
-           @return: None"""
-        self.context_menu.hide()
-
-    def initializeMainMenu(self):
-        """Initalize the main menu.
-           @return: None"""
-        
-        xml_file = vfs.VFS.open('gui/hud_pause_menu.xml')
-        self.main_menu = pychan.loadXML(xml_file)
-
-        #TODO: find more suitalbe place for onOptilonsPress implementation
-        self.menu_events = {"resumeButton": self.hideMenu, 
-                            "settingsButton": self.displaySettings,
-                            "helpButton": self.displayHelp}
-        self.main_menu.mapEvents(self.menu_events)
-
-    def displayMenu(self):
-        """Displays the main in-game menu.
-           @return: None"""
-        self.stopActions()
-        if (self.menu_displayed == False):
-            self.main_menu.show()
-            self.menu_displayed = True
-            self.model.pause(True)
-            self.controller.pause(True)
-            self.enabled = False
-        elif (self.menu_displayed == True):
-            self.hideMenu()
-
-    def hideMenu(self):
-        """Hides the main in-game menu.
-           @return: None"""
-        self.main_menu.hide()
-        self.menu_displayed = False
-        self.model.pause(False)
-        self.controller.pause(False)
-        self.enabled = True
-
-    def initializeSettingsMenu(self):
-        self.settings_menu = SettingsMenu(self.engine, self.settings)
-
-    def displaySettings(self):
-        self.settings_menu.show()
-
-    def initializeHelpMenu(self):
-        """Initialize the help menu
-           @return: None"""
-
-        xml_file = vfs.VFS.open('gui/help.xml')
-        self.help_dialog = pychan.loadXML(xml_file)
-
-        help_events = {"closeButton":self.help_dialog.hide}
-        self.help_dialog.mapEvents(help_events)
-        main_help_text = u"Welcome to Post-Apocalyptic RPG or PARPG![br][br]"\
-        "This game is still in development, so please expect for there to be "\
-        "bugs and[br]feel free to tell us about them at "\
-        "http://www.forums.parpg.net.[br]This game uses a "\
-        "\"Point 'N' Click\" interface, which means that to move around,[br]"\
-        "just click where you would like to go and your character will move "\
-        "there.[br]PARPG also utilizes a context menu. To access this, just "\
-        "right click anywhere[br]on the screen and a menu will come up. This "\
-        "menu will change depending on[br]what you have clicked on, hence "\
-        "it's name \"context menu\".[br][br]"
-        
-        k_text = u" Keybindings" 
-        k_text += "[br] A : Add a test action to the actions display"
-        k_text += "[br] I : Toggle the inventory screen"
-        k_text += "[br] F7 : Take a screenshot"
-        k_text += "[br]      (Saves to screenshots directory)"
-        k_text += "[br] F10 : Toggle console"
-        k_text += "[br] PAUSE : (Un)Pause the game"
-        k_text += "[br] Q : Quit the game"
-        self.help_dialog.distributeInitialData({
-                "MainHelpText":main_help_text,
-                "KeybindText":k_text
-                })
-
-    def displayHelp(self):
-        """Display the help screen.
-           @return: None"""
-        self.help_dialog.show()
-
-    def saveGame(self):
-        """ Called when the user wants to save the game.
-            @return: None"""
-        self.stopActions()
-        xml_path = 'gui/savebrowser.xml'
-        save_browser = FileBrowser(self.engine,
-                                   self.settings,
-                                   self.save_game_callback,
-                                   xml_path,
-                                   self.loadsave_close,
-                                   save_file=True,
-                                   extensions=('.dat'))
-        save_browser.showBrowser()
-        self.controller.pause(True)
-        self.model.pause(True)
-        self.enabled = False
-
-    def stopActions(self):
-        """This method stops/resets actions that are currently performed 
-        like dragging an item.
-        This is done to be able to savely perform other actions that might 
-        interfere with current running ones."""
-        #Reset dragging - move item back to its old container
-        if data_drag.dragging:
-            drag_item = data_drag.dragged_item 
-            data_drag.dragging = False
-            data_drag.dragged_item = None
-            DropItemAction(self.controller, drag_item).execute()
-        if self.inventory:
-            self.inventory.closeInventory()
-        
-    def newGame(self):
-        """Called when user request to start a new game.
-           @return: None"""
-        self.stopActions()
-        logger.info('new game')
-    
-    def loadsave_close(self):
-        """Called when the load/save filebrowser was closed without a file selected"""
-        if not self.menu_displayed:
-            self.enabled = True
-            self.model.pause(False)
-            self.controller.pause(False)
-            
-    def loadGame(self):
-        """ Called when the user wants to load a game.
-            @return: None"""
-        self.stopActions()
-        xml_path = 'gui/loadbrowser.xml'
-        load_browser = FileBrowser(self.engine,
-                                   self.settings,
-                                   self.load_game_callback,
-                                   xml_path,
-                                   close_callback = self.loadsave_close,
-                                   save_file=False,
-                                   extensions=('.dat'))
-        load_browser.showBrowser()
-        self.model.pause(True)
-        self.controller.pause(True)
-        self.enabled = False
-    
-    def initializeQuitDialog(self):
-        """Creates the quit confirmation dialog
-           @return: None"""
-        self.quit_window = pychan.widgets.Window(title=unicode("Quit?"), \
-                                                 min_size=(200,0))
-
-        hbox = pychan.widgets.HBox()
-        are_you_sure = "Are you sure you want to quit?"
-        label = pychan.widgets.Label(text=unicode(are_you_sure))
-        yes_button = pychan.widgets.Button(name="yes_button", 
-                                           text=unicode("Yes"),
-                                           min_size=(90,20),
-                                           max_size=(90,20))
-        no_button = pychan.widgets.Button(name="no_button",
-                                          text=unicode("No"),
-                                          min_size=(90,20),
-                                          max_size=(90,20))
-
-        self.quit_window.addChild(label)
-        hbox.addChild(yes_button)
-        hbox.addChild(no_button)
-        self.quit_window.addChild(hbox)
-
-        events_to_map = { "yes_button": self.quit_callback,
-                          "no_button":  self.quit_window.hide }
-        
-        self.quit_window.mapEvents(events_to_map)
-
-
-    def quitGame(self):
-        """Called when user requests to quit game.
-           @return: None"""
-        self.stopActions()
-        self.quit_window.show()
-
-    def toggleInventoryButton(self):
-        """Manually toggles the inventory button.
-           @return: None"""
-        button = self.hud.findChild(name="inventoryButton")
-        if button.toggled == 0:
-            button.toggled = 1
-        else:
-            button.toggled = 0
-
-    def toggleInventory(self, toggle_image=True):
-        """Displays the inventory screen
-           @return: None"""
-        if self.inventory is None:
-            self.initializeInventory()
-
-        self.inventory.toggleInventory(toggle_image)
-    
-    def toggleCharacterScreen(self):
-        if self.characcter_screen is None:
-            self.initializeCharacterScreen()
-
-        if not self.character_screen.isVisible():
-            self.character_screen.show()
-        else:
-            self.character_screen.hide()
-    
-    def refreshReadyImages(self):
-        """Make the Ready slot images on the HUD be the same as those 
-           on the inventory
-           @return: None"""
-        for ready in range(1, 5):
-            button = self.hud.findChild(name=("hudReady%d" % ready))
-            if self.inventory_storage == None :
-                origin = None
-            else:
-                origin = self.inventory_storage.getItemsInSlot('ready', ready-1)
-            if origin == None:
-                self.setImages(button, 
-                               self.inventory.slot_empty_images['ready'])
-            else:
-                self.setImages(button, origin.getInventoryThumbnail())
-
-    def setImages(self, widget, image):
-        """Set the up, down, and hover images of an Imagebutton.
-           @type widget: pychan.widget
-           @param widget: widget to set
-           @type image: string
-           @param image: image to use
-           @return: None"""
-        widget.up_image = image
-        widget.down_image = image
-        widget.hover_image = image
-
-    def initializeEvents(self):
-        """Intialize Hud events
-           @return: None"""
-        events_to_map = {}
-
-        # when we click the toggle button don't change the image
-        events_to_map["inventoryButton"] = cbwa(self.toggleInventory, False)
-        events_to_map["saveButton"] = self.saveGame
-        events_to_map["loadButton"] = self.loadGame
-
-        hud_ready_buttons = ["hudReady1", "hudReady2", \
-                             "hudReady3", "hudReady4"]
-
-        for item in hud_ready_buttons:
-            events_to_map[item] = cbwa(self.readyAction, item)
-
-        self.hud.mapEvents(events_to_map)
-
-        menu_events = {}
-        menu_events["newButton"] = self.newGame
-        menu_events["quitButton"] = self.quitGame
-        menu_events["saveButton"] = self.saveGame
-        menu_events["loadButton"] = self.loadGame
-        self.main_menu.mapEvents(menu_events)
-
-    def readyAction(self, ready_button):
-        """ Called when the user selects a ready button from the HUD """
-        text = "Used the item from %s" % ready_button        
-        self.addAction(text)
-        
-    def createBoxGUI(self, title, container):
-        """Creates a window to display the contents of a box
-           @type title: string
-           @param title: The title for the window
-           @param items: The box to display
-           @return: A new ContainerGui"""
-        events = {'takeAllButton':self.hideContainer,
-                  'closeButton':self.hideContainer}
-        #hide previous container if any, to avoid orphaned dialogs
-        self.hideContainer()
-
-        self.box_container = ContainerGUI(self.controller,
-                                              unicode(title), container)
-        self.box_container.gui.mapEvents(events)
-        self.box_container.showContainer()
-        return self.box_container
-
-    def hideContainer(self):
-        """Hide the container box
-           @return: None"""
-        if self.box_container:
-            self.box_container.hideContainer()
-            self.box_container = None
-
-    def createExamineBox(self, title, desc):
-        """Create an examine box. It displays some textual description of an
-           object
-           @type title: string
-           @param title: The title of the examine box
-           @type desc: string
-           @param desc: The main body of the examine box
-           @return: None"""
-        if self.examine_box is not None:
-            self.examine_box.closePopUp()
-        self.examine_box = ExaminePopup(self.engine, title, desc)
-        self.examine_box.showPopUp()
-
-    def showDialogue(self, npc):
-        """Show the NPC dialogue window
-           @type npc: actors.NonPlayerCharacter
-           @param npc: the npc that we are having a dialogue with
-           @return: The dialogue"""
-        self.stopActions()
-        dialogue = DialogueGUI(
-                    self.controller,
-                    npc,
-                    self.model.game_state.quest_engine,
-                    self.model.game_state.met, self.model.game_state.meet,
-                    container.get_item,
-                    self.model.game_state.getObjectById("PlayerCharacter"))
-        return dialogue
--- a/src/parpg/gui/inventorygui.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,391 +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 <http://www.gnu.org/licenses/>.
-import logging
-from types import StringTypes
-
-from fife.extensions.pychan.tools import callbackWithArguments as cbwa
-from fife.extensions import pychan
-from fife.extensions.pychan.attrs import UnicodeAttr
-
-from parpg.gui import drag_drop_data as data_drag
-from parpg.gui.containergui_base import ContainerGUIBase
-from parpg.entities.action import ACTIONS
-from parpg.components import equip, equipable, container
-from parpg.entities import General
-
-logger = logging.getLogger('action')
-
-class EquipmentSlot(pychan.VBox):
-    def __init__(self, min_size=(50, 50),
-                 max_size=(50, 50), margins=None,
-                 **kwargs):
-        pychan.VBox.__init__(self, min_size=min_size, max_size=max_size,
-                             **kwargs)
-        self.background_image = 'gui/inv_images/inv_background.png'
-        icon = pychan.Icon(name="Icon")
-        self.addChild(icon)
-        self.adaptLayout()
-        if self.parent is not None:
-            self.beforeShow()
-
-    @property
-    def image(self):
-        icon = self.findChildByName("Icon")
-        return icon.image
-    
-    @image.setter
-    def image(self, image):
-        icon = self.findChildByName("Icon")
-        icon.image = image        
-
-class InventoryGrid(pychan.VBox):
-    ATTRIBUTES = pychan.VBox.ATTRIBUTES + [pychan.attrs.PointAttr('grid_size')]
-    
-    def _setNColumns(self, n_columns):
-        n_rows = self.grid_size[1]
-        self.grid_size = (n_columns, n_rows)
-    
-    def _getNColumns(self):
-        n_columns = self.grid_size[0]
-        return n_columns
-    n_columns = property(fget=_getNColumns, fset=_setNColumns)
-    
-    def _setNRows(self, n_rows):
-        n_columns = self.grid_size[0]
-        self.grid_size = (n_columns, n_rows)
-    
-    def _getNRows(self):
-        n_rows = self.grid_size[1]
-        return n_rows
-    n_rows = property(fget=_getNRows, fset=_getNColumns)
-    
-    def _setGridSize(self, grid_size):
-        n_columns, n_rows = grid_size
-        self.removeAllChildren()
-        for row_n in xrange(n_rows):
-            row_size = (n_columns * 50, 50)
-            row = pychan.HBox(min_size=row_size, max_size=row_size,
-                              padding=self.padding)
-            row.border_size = 1
-            row.opaque = 0
-            for column_n in xrange(n_columns):
-                index = (row_n * n_columns + column_n)
-                slot = pychan.Icon(min_size=(50, 50), max_size=(50, 50))
-                slot.border_size = 1
-                slot.name = "Slot_%d" % index
-                slot.index = index
-                row.addChild(slot)
-            self.addChild(row)
-        self.min_size = ((n_columns * 50) + 2, (n_rows * 50) + 2)
-        self.max_size = self.min_size
-    
-    def _getGridSize(self):
-        n_rows = len(self.children)
-        n_columns = len(self.children[0].children)
-        return (n_rows, n_columns)
-    grid_size = property(fget=_getGridSize, fset=_setGridSize)
-    
-    def getSlot(self, row_or_index, col=None):
-        if col:
-            index = row * self.n_columns + col
-        else:
-            index = row_or_index
-        return self.findChildByName("Slot_%d" % index)
-    
-    def __init__(self, grid_size=(2, 2), padding=0, **kwargs):
-        pychan.VBox.__init__(self, padding=padding, **kwargs)
-        self.opaque = 0
-        self.grid_size = grid_size
-        self.border_size = 1
-
-
-class EquipmentGUI(ContainerGUIBase):
-    def __init__(self, controller, gui, equip, callbacks):
-        ContainerGUIBase.__init__(self, controller, gui)
-        self.equip = equip
-        self.equip_to_gui = {
-            "head": "headSlot",
-            "neck": "neckSlot",
-            "body": "shirtSlot",
-            "belt": "beltSlot",
-            "leg": "pantsSlot",
-            "feet": "bootsSlot",
-            "l_arm": "leftHandSlot",
-            "r_arm": "rightHandSlot",
-        }
-        self.setSlotEvents()
-        
-    def updateImages(self):
-        for eq_slot, gui_slot in self.equip_to_gui.iteritems():
-            widget = self.gui.findChildByName(gui_slot)            
-            equipable = equip.get_equipable(self.equip, eq_slot)
-            widget.item = equipable.entity if equipable else None
-            self.updateImage(widget) 
-               
-    def updateImage(self, slot):
-        assert(isinstance(slot, EquipmentSlot))
-        if (slot.item):
-            image = slot.item.containable.image
-        else:
-            image = None
-        slot.image = image
-                
-    def dragObject(self, obj):
-        """Drag the selected object.
-           @type obj: string
-           @param obj: The name of the object
-           @return: None"""
-        # get the widget from the gui with the name obj
-        drag_widget = self.gui.findChildByName(obj)
-        drag_item = drag_widget.item
-        # only drag if the widget is not empty
-        if (drag_item != None):
-            if isinstance(drag_item, General):
-                drag_item = drag_item.containable
-            elif isinstance(drag_item, equipable):
-                drag_item = drag_item.entity.containable
-            drag_eq = drag_item.entity.equipable
-            # get the image of the widget
-            image = drag_widget.image
-            self.setDragData(drag_item, image, image)
-            equip.take_equipable(self.equip, drag_eq.in_slot)
-            
-            # after dragging the 'item', set the widgets' images
-            # so that it has it's default 'empty' images
-            drag_widget.item = None
-            self.updateImage(drag_widget)
-
-    def dropObject(self, obj):
-        """Drops the object being dropped
-           @type obj: string
-           @param obj: The name of the object
-           @return: None"""
-        try:
-            drop_widget = self.gui.findChildByName(obj)
-            drop_slot = drop_widget.slot
-            replace_item = None
-    
-            if data_drag.dragging:
-                drag_item = data_drag.dragged_item.entity
-                if drag_item.equipable:
-                    drag_item = drag_item.equipable
-                else:
-                    return                
-                #this will get the replacement item and the data for drag_drop
-                #if there is an item all ready occupying the slot
-                replace_item = (
-                    equip.equip(self.equip, drag_item, drop_slot)
-                )
-                
-            #if there was no item the stop dragging and reset cursor
-            if replace_item:
-                image = drop_widget.image
-                self.setDragData(replace_item.entity.containable, image, image)
-            else:
-                data_drag.dragging = False
-                #reset the mouse cursor to the normal cursor
-                self.controller.resetMouseCursor()
-            drop_widget.item = drag_item.entity
-            self.updateImage(drop_widget)
-        except (equip.AlreadyEquippedError, equip.CannotBeEquippedInSlot):
-            #Do we want to notify the player why the item can't be dropped?
-            pass
-
-    def mousePressedOnSlot(self, event, widget):
-        if event.getButton() == event.LEFT:
-            self.dragDrop(widget.name)
-
-    def setSlotEvents(self):
-        events_to_map = {}
-        for eq_slot, gui_slot in self.equip_to_gui.iteritems():
-            widget = self.gui.findChildByName(gui_slot)
-            slot_name = widget.name
-            widget.slot = eq_slot
-            events_to_map[slot_name + "/mousePressed"] = (
-                self.mousePressedOnSlot
-            )
-            events_to_map[slot_name + "/mouseReleased"] = self.showContextMenu
-
-        self.gui.mapEvents(events_to_map)            
-        
-class InventoryGUI(ContainerGUIBase):
-    def __init__(self, controller, gui, container, callbacks):
-        ContainerGUIBase.__init__(self, controller, gui)
-        self.grid = self.gui.findChildByName("Grid")
-        assert(isinstance(self.grid, InventoryGrid))
-        self.container = container
-        self.setSlotEvents()
-
-    def setSlotEvents(self):
-        slot_count = self.grid.n_rows * self.grid.n_columns
-        events_to_map = {}
-        for counter in xrange(0, slot_count):
-            widget = self.grid.getSlot(counter)
-            slot_name = widget.name
-            widget.index = counter
-            events_to_map[slot_name + "/mousePressed"] = (
-                self.mousePressedOnSlot
-            )
-            events_to_map[slot_name + "/mouseReleased"] = self.showContextMenu
-
-        self.grid.mapEvents(events_to_map)
-
-    def updateImages(self):
-        for index, child in enumerate(self.container.children):
-            slot = self.grid.getSlot(index)
-            if child:
-                slot.item = child.entity
-            else:
-                slot.item = None
-            self.updateImage(slot)
-            
-    def updateImage(self, slot):
-        assert(isinstance(slot, pychan.Icon))
-        if (slot.item):
-            image = slot.item.containable.image
-        else:
-            image = None
-        slot.image = image
-        
-    def mousePressedOnSlot(self, event, widget):
-        if event.getButton() == event.LEFT:
-            self.dragDrop(widget.name)
-
-    def dragObject(self, obj):
-        """Drag the selected object.
-           @type obj: string
-           @param obj: The name of the object
-           @return: None"""
-        # get the widget from the gui with the name obj
-        drag_widget = self.gui.findChild(name = obj)
-        drag_item = drag_widget.item
-        # only drag if the widget is not empty
-        if (drag_item != None):
-            if isinstance(drag_item, General):
-                drag_item = drag_item.containable
-            # get the image of the widget
-            image = drag_widget.image
-            self.setDragData(drag_item, image, image)
-            container.take_item(self.container, drag_item.slot)
-            
-            # after dragging the 'item', set the widgets' images
-            # so that it has it's default 'empty' images
-            drag_widget.item = None
-            self.updateImage(drag_widget)
-            
-    def dropObject(self, obj):
-        """Drops the object being dropped
-           @type obj: string
-           @param obj: The name of the object
-           @return: None"""
-        try:
-            drop_widget = self.gui.findChildByName(obj)
-            drop_index = drop_widget.index
-            replace_item = None
-    
-            if data_drag.dragging:
-                drag_item = data_drag.dragged_item
-                #this will get the replacement item and the data for drag_drop if
-                ## there is an item all ready occupying the slot
-                replace_item = (
-                    container.put_item(self.container, drag_item, drop_index)
-                )
-                
-            #if there was no item the stop dragging and reset cursor
-            if replace_item:
-                image = drop_widget.image
-                self.setDragData(replace_item, image, image)
-            else:
-                data_drag.dragging = False
-                #reset the mouse cursor to the normal cursor
-                self.controller.resetMouseCursor()
-            drop_widget.item = drag_item.entity
-            self.updateImage(drop_widget)
-        except (container.BulkLimitError):
-            #Do we want to notify the player why the item can't be dropped?
-            pass
-        
-    def createMenuItems(self, item, actions):
-        """Creates context menu items for the InventoryGUI"""
-        menu_actions = ContainerGUIBase.createMenuItems(self, item, actions)
-        param_dict = {}
-        param_dict["controller"] = self.controller
-        param_dict["commands"] = {}
-        param_dict["item"] = item.containable
-        param_dict["container_gui"] = self
-        menu_actions.append(["Drop",
-                             "Drop", 
-                             self.executeMenuItem, 
-                             ACTIONS["DropFromInventory"](**param_dict)])        
-        return menu_actions
-    
-class CharacterGUI(object):
-    def __init__(self, controller, gui, container, equip, callbacks):
-        self.engine = controller.engine
-        self.inventory_shown = False
-        if isinstance(gui, pychan.Widget):
-            self.gui = gui
-        elif isinstance(gui, StringTypes):
-            xml_file = vfs.VFS.open(gui)
-            self.gui = pychan.loadXML(xml_file)
-        else:
-            self.gui = pychan.loadXML(gui)
-        
-        render_backend = self.engine.getRenderBackend()
-        screen_mode = render_backend.getCurrentScreenMode()
-        screen_width, screen_height = (screen_mode.getWidth(),
-                                       screen_mode.getHeight())
-        widget_width, widget_height = self.gui.size
-        self.gui.position = ((screen_width - widget_width) / 2,
-                             (screen_height - widget_height) / 2)
-        self.equip_gui = EquipmentGUI(
-            controller,
-            self.gui.findChildByName("equipmentPage"),
-            equip, callbacks
-        )
-        self.inv_gui = InventoryGUI(
-            controller,
-            self.gui.findChildByName("inventoryPage"),
-            container, callbacks
-        )
-    
-    def toggleInventory(self, toggleImage=True):
-        """Pause the game and enter the inventory screen, or close the
-           inventory screen and resume the game.
-           @type toggleImage: bool
-           @param toggleImage:
-               Call toggleInventoryCallback if True. Toggling via a
-               keypress requires that we toggle the Hud inventory image
-               explicitly. Clicking on the Hud inventory button toggles the
-               image implicitly, so we don't change it.
-           @return: None"""
-        if not self.inventory_shown:
-            self.showInventory()
-            self.inventory_shown = True
-        else:
-            self.closeInventory()
-            self.inventory_shown = False
-            
-    def updateImages(self):
-        self.equip_gui.updateImages()
-        self.inv_gui.updateImages()
-    
-    def showInventory(self):
-        self.updateImages()
-        self.gui.show()
-    
-    def closeInventory(self):
-        self.gui.hide()
-        
\ No newline at end of file
--- a/src/parpg/gui/menus.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +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 <http://www.gnu.org/licenses/>.
-
-import logging
-
-from fife.extensions import pychan
-
-from parpg import vfs
-from dialogs import RestartDialog
-
-logger = logging.getLogger('menus')
-
-class ContextMenu(object):
-    def __init__(self, engine, menu_items, pos):
-        """@type engine: engine.Engine
-           @param engine: An instance of the class Engine from engine.py 
-           @type menu_items: list
-           @param menu_items: A list of items containing the name and 
-                              text for the menu item and callback
-                              i.e. [["menu", "Some text",  Callback]
-           @type pos: (int, int)
-           @param pos: Screen position to use 
-           @return: None"""
-        self.vbox = pychan.widgets.VBox(position=pos)
-        events_to_map = {}
-        for item in menu_items:
-            p = pychan.widgets.Button(name=item[0], text=unicode(item[1]))
-            self.vbox.addChild(p)
-            events_to_map [item[0]] = self.actionDecorator(*item[2:])
-        self.vbox.mapEvents(events_to_map)
-    
-    def show(self):
-        """Shows the context menu"""
-        self.vbox.show()
-    def hide(self):
-        """Hides the context menu"""
-        self.vbox.hide()
-        
-    def actionDecorator (self,func, *args, **kwargs):
-        """This function is supposed to add some generic that should be
-        executed before and/or after an action is fired through the
-        context menu.
-        
-        @type func: Any callable
-        @param func: The original action function
-        @param args: Unpacked list of positional arguments
-        @param kwargs: Unpacked list of keyword arguments
-        @return: A wrapped version of func"""
-        def decoratedFunc ():
-            """ This is the actual wrapped version of func, that is returned.
-            It takes no external arguments, so it can safely be passed around
-            as a callback."""
-            # some stuff that we do before the actual action is executed
-            self.hide()
-            # run the action function, and record the return value
-            ret_val = func (*args,**kwargs)
-            # we can eventually add some post-action code here, if needed (e.g. logging)
-            pass        
-            # return the value, as if the original function was called
-            return ret_val
-        return decoratedFunc
-        
-class SettingsMenu(object):
-    def __init__(self, engine, settings):
-        self.engine = engine
-        self.settings = settings
-
-        width = self.settings.fife.ScreenWidth
-        height = self.settings.fife.ScreenHeight
-
-        # available options
-        screen_modes = self.engine.getDeviceCaps().getSupportedScreenModes()
-        resolutions = list(set([(mode.getWidth(), mode.getHeight())
-                                for mode in screen_modes]))
-        self.resolutions = ["{0}x{1}".format(item[0], item[1])
-                            for item in sorted(resolutions)[1:]]
-
-        self.render_backends = ['OpenGL', 'SDL']
-        self.lighting_models = range(3)
-        
-        # selected options
-        self.resolution = "{0}x{1}".format(width, height)
-        self.render_backend = self.settings.fife.RenderBackend
-        self.lighting_model = self.settings.fife.Lighting
-        self.fullscreen = self.settings.fife.FullScreen
-        self.sound = self.settings.fife.EnableSound
-        self.scroll_speed = self.settings.parpg.ScrollSpeed
-        
-        xml_file = vfs.VFS.open('gui/settings_menu.xml')
-        self.window = pychan.loadXML(xml_file)
-        self.restart_dialog = RestartDialog(self.settings)
-        self.window.mapEvents({'okButton': self.save,
-                               'cancelButton': self.hide,
-                               'defaultButton': self.reset,
-                               'scroll_speed': self.update})
-        self.initializeWidgets()
-        self.fillWidgets()
-
-    def initializeWidgets(self):
-        scroll_speed = unicode(self.scroll_speed)
-        initial_data = {'screen_resolution': self.resolutions,
-                        'render_backend': self.render_backends,
-                        'lighting_model': self.lighting_models,
-                        'scroll_speed_value': scroll_speed}
-
-        self.window.distributeInitialData(initial_data)
-
-
-    def fillWidgets(self):
-        resolution = self.resolutions.index(self.resolution)
-        backend = self.render_backends.index(self.render_backend)
-        lighting = self.lighting_models.index(self.lighting_model)
-        
-        self.window.distributeData({'screen_resolution': resolution,
-                                    'render_backend': backend,
-                                    'lighting_model': lighting,
-                                    'enable_fullscreen': self.fullscreen,
-                                    'enable_sound': self.sound})
-
-    def update(self):
-        """updates lables to show realtime data"""
-        #collects the data from the widgets
-        (scroll_speed) = self.window.collectData('scroll_speed')
-
-        #alter the data note:pychan insists that all lables be given
-        #  unicode text
-        #the slice rounds the number displayed
-        scroll_speed = unicode(scroll_speed)[:3]
-
-        #adds the data to the proper widgets
-        self.window.distributeInitialData({'scroll_speed_value': scroll_speed})
-
-    def show(self):
-        self.window.show()
-
-    def hide(self):
-        self.window.hide()
-
-    def reset(self):
-        self.settings.read(self.settings.system_path)
-        self.fillWidgets()
-
-    def save(self):
-        (resolution, backend, lighting, fullscreen, sound, scroll_speed) = \
-            self.window.collectData('screen_resolution', 'render_backend',
-                                    'lighting_model', 'enable_fullscreen',
-                                    'enable_sound', 'scroll_speed')
-        
-        width, height = self.resolutions[resolution].split('x')
-        self.settings.fife.ScreenWidth = width
-        self.settings.fife.ScreenHeight = height
-        self.settings.fife.RenderBackend = self.render_backends[backend]
-        self.settings.fife.Lighting = self.lighting_models[lighting]
-        self.settings.fife.FullScreen = fullscreen
-        self.settings.fife.EnableSound = sound
-        self.settings.parpg.ScrollSpeed = scroll_speed
-        self.settings.write()
-       
-        self.restart_dialog.show()
-        self.hide()
--- a/src/parpg/gui/popups.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-#/usr/bin/python
-
-#   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/>.
-
-from fife.extensions import pychan
-
-class ExaminePopup():
-    """Create a popup for when you click examine on an object"""
-    def __init__(self, engine, object_title, desc):
-        """Initialize the popup  
-           @type engine: fife.Engine
-           @param engine: an instance of the fife engine
-           @type object_title: string
-           @param object_title: The title for the window, probably should just
-                                be the name of the object
-           @type desc: string
-           @param desc: The description of the object
-           @return: None"""
-        self.engine = engine
-
-        self.examine_window = pychan.widgets.\
-                                Window(title=unicode(object_title),
-                                       position_technique="center:center",
-                                       min_size=(175,175))
-
-        self.scroll = pychan.widgets.ScrollArea(name='scroll', size=(150,150))
-        self.description = pychan.widgets.Label(name='descText',
-                                                text=unicode(desc),
-                                                wrap_text=True)
-        self.description.max_width = 170
-        self.scroll.addChild(self.description)
-        self.examine_window.addChild(self.scroll)
-        
-        self.close_button = pychan.widgets.Button(name='closeButton',
-                                                  text=unicode('Close'))
-        self.examine_window.addChild(self.close_button)
-
-        self.examine_window.mapEvents({'closeButton':self.examine_window.hide})
-
-    def closePopUp(self):
-        # TODO: missing function information
-        if self.examine_window.isVisible():
-            self.examine_window.hide()
-    
-    def showPopUp(self):
-        # TODO: missing function information
-        self.examine_window.show()
--- a/src/parpg/gui/spinners.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-from fife.extensions.pychan.widgets import (ImageButton, TextField, HBox,
-    Spacer)
-from fife.extensions.pychan.attrs import Attr, IntAttr, BoolAttr
-
-class ListAttr(Attr):
-    def parse(self, value):
-        list_ = value.split(',')
-        return list_
-
-
-class Spinner(HBox):
-    ATTRIBUTES = HBox.ATTRIBUTES + [
-        ListAttr('items'),
-        IntAttr('default_item_n'),
-        BoolAttr('circular'),
-    ]
-    
-    def default_item_n():
-        def fget(self):
-            return self._default_item_n
-        
-        def fset(self, index):
-            if len(self.items) -1 >= index:
-                self._default_item_n = index
-                self.text_field.text = self.items[index]
-            else:
-                error_message = \
-                    'default_item_n exceeds number of items in spinner'
-                raise ValueError(error_message)
-        
-        return locals()
-    default_item_n = property(**default_item_n())
-    
-    def items():
-        def fget(self):
-            return self._items
-        
-        def fset(self, items):
-            self._items = map(unicode, items)
-            if self.default_item_n > len(items) - 1:
-                self.default_item_n = 0
-            self.text_field.text = self.items[self.default_item_n] if \
-                                   len(self.items) > 0 else u''
-        
-        return locals()
-    items = property(**items())
-    
-    def background_color():
-        def fget(self):
-            return self.text_field.background_color
-        
-        def fset(self, background_color):
-            self.text_field.background_color = background_color
-        
-        return locals()
-    background_color = property(**background_color())
-    
-    def font():
-        def fget(self):
-            return self.text_field.font
-        
-        def fset(self, font):
-            self.text_field.font = font
-        
-        return locals()
-    font = property(**font())
-    
-    def background_color():
-        def fget(self):
-            return self.text_field.background_color
-        
-        def fset(self, background_color):
-            self.text_field.background_color = background_color
-        
-        return locals()
-    background_color = property(**background_color())
-    
-    def min_size():
-        def fget(self):
-            return self._min_size
-        
-        def fset(self, min_size):
-            self._min_size = min_size
-            self.decrease_button.capture(self.previousItem)
-            increase_button_width, increase_button_height = \
-                self.increase_button.size
-            decrease_button_width, decrease_button_height = \
-                self.decrease_button.size
-            text_field_width = min_size[0] - (2 * self.padding) - \
-                               (increase_button_width + decrease_button_width)
-            self.text_field.min_width = text_field_width
-            self.text_field.max_width = text_field_width
-            self.text_field.min_height = min_size[1]
-        
-        return locals()
-    min_size = property(**min_size())
-    
-    
-    def max_size():
-        def fget(self):
-            return self._max_size
-        
-        def fset(self, max_size):
-            self._max_size = max_size
-            self.decrease_button.capture(self.previousItem)
-            increase_button_width, increase_button_height = \
-                self.increase_button.size
-            decrease_button_width, decrease_button_height = \
-                self.decrease_button.size
-            text_field_width = max_size[0] - (2 * self.padding) - \
-                               (increase_button_width + decrease_button_width)
-            self.text_field.max_width = text_field_width
-            self.text_field.max_height = max_size[1]
-        
-        return locals()
-    max_size = property(**max_size())
-    
-    def __init__(self, items=None, default_item_n=0, circular=True,
-                 min_size=(50, 14), max_size=(50, 14), font=None, background_color=None, **kwargs):
-        self._current_index = 0
-        self._items = map(unicode, items) if items is not None else []
-        self._default_item_n = default_item_n
-        self._min_size = min_size
-        self.circular = circular
-        padding = 1
-        self.text_field = TextField(background_color=background_color)
-        self.decrease_button = ImageButton(
-            up_image='gui/buttons/left_arrow_up.png',
-            down_image='gui/buttons/left_arrow_down.png',
-            hover_image='gui/buttons/left_arrow_hover.png',
-        )
-        # FIXME Technomage 2011-03-05: This is a hack to prevent the button
-        #     from expanding width-wise and skewing the TextField orientation.
-        #     Max size shouldn't be hard-coded like this though...
-        self.decrease_button.max_size = (12, 12)
-        self.decrease_button.capture(self.previousItem)
-        self.increase_button = ImageButton(
-            up_image='gui/buttons/right_arrow_up.png',
-            down_image='gui/buttons/right_arrow_down.png',
-            hover_image='gui/buttons/right_arrow_hover.png',
-        )
-        self.increase_button.capture(self.nextItem)
-        increase_button_width, increase_button_height = \
-            self.increase_button.size
-        decrease_button_width, decrease_button_height = \
-            self.decrease_button.size
-        self.text_field = TextField(font=font)
-        text_field_width = min_size[0] - (2 * padding) - \
-                           (increase_button_width + decrease_button_width)
-        self.text_field.min_width = text_field_width
-        self.text_field.max_width = text_field_width
-        self.text_field.min_height = min_size[1]
-        self.text_field.text = self.items[default_item_n] if \
-                               len(self.items) > 0 else u''
-        HBox.__init__(self, **kwargs)
-        self.opaque = 0
-        self.padding = padding
-        self.margins = (0, 0)
-        self.addChildren(self.decrease_button, self.text_field,
-                         self.increase_button)
-    
-    def nextItem(self, event, widget):
-        if self.circular:
-            if self._current_index < len(self.items) - 1:
-                self._current_index += 1
-            else:
-                self._current_index = 0
-            self.text_field.text = self.items[self._current_index]
-        elif self._current_index < len(self.items) - 1:
-            self._current_index += 1
-            self.text_field.text = self.items[self._current_index]
-    
-    def previousItem(self, event, widget):
-        if self.circular:
-            if self._current_index > 0:
-                self._current_index -= 1
-            else:
-                self._current_index = len(self.items) - 1
-            self.text_field.text = self.items[self._current_index]
-        elif self._current_index > 0:
-            self._current_index -= 1
-            self.text_field.text = self.items[self._current_index]
-
-
-class IntSpinner(Spinner):
-    ATTRIBUTES = Spinner.ATTRIBUTES + [
-        IntAttr('lower_limit'),
-        IntAttr('upper_limit'),
-        IntAttr('step_size'),
-    ]
-    
-    def lower_limit():
-        def fget(self):
-            return self._lower_limit
-        
-        def fset(self, lower_limit):
-            self._lower_limit = lower_limit
-            integers = range(lower_limit, self.upper_limit + 1, self.step_size)
-            self.items = integers
-        
-        return locals()
-    lower_limit = property(**lower_limit())
-    
-    def upper_limit():
-        def fget(self):
-            return self._upper_limit
-        
-        def fset(self, upper_limit):
-            self._upper_limit = upper_limit
-            integers = range(self.lower_limit, upper_limit + 1, self.step_size)
-            self.items = integers
-        
-        return locals()
-    upper_limit = property(**upper_limit())
-    
-    def step_size():
-        def fget(self):
-            return self._step_size
-        
-        def fset(self, step_size):
-            self._step_size = step_size
-            integers = range(self.lower_limit, self.upper_limit + 1, step_size)
-            self.items = integers
-        
-        return locals()
-    step_size = property(**step_size())
-    
-    def __init__(self, lower_limit=0, upper_limit=100, step_size=1, **kwargs):
-        self._lower_limit = lower_limit
-        self._upper_limit = upper_limit
-        self._step_size = step_size
-        integers = range(lower_limit, upper_limit + 1, step_size)
-        Spinner.__init__(self, items=integers, **kwargs)
-
--- a/src/parpg/gui/tabwidget.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-from fife.extensions.pychan.widgets import VBox, HBox, ScrollArea, Button
-from fife.extensions.pychan.tools import callbackWithArguments
-
-class TabWidget(VBox):
-    def min_size():
-        def fget(self):
-            return self._min_size
-        
-        def fset(self, min_size):
-            self._min_size = min_size
-            self.view.min_size = min_size
-            self.adaptLayout()
-        
-        return locals()
-    min_size = property(**min_size())
-    
-    def max_size():
-        def fget(self):
-            return self._max_size
-        
-        def fset(self, max_size):
-            self._max_size = max_size
-            self.view.max_size = max_size
-            self.adaptLayout()
-        
-        return locals()
-    max_size = property(**max_size())
-    
-    def opaque():
-        def fget(self):
-            return self._getOpaque()
-        
-        def fset(self, opaque):
-            self._setOpaque(opaque)
-            self.view.opaque = opaque
-            base_color = self.view.base_color
-            base_red = base_color.r
-            base_green = base_color.g
-            base_blue = base_color.b
-            background_color = self.view.background_color
-            background_red = background_color.r
-            background_green = background_color.g
-            background_blue = background_color.b
-            alpha = 255 if opaque else 0
-            self.view.base_color = (base_red, base_green, base_blue, alpha)
-            self.view.background_color = (background_red, background_green,
-                                          background_blue, alpha)
-        
-        return locals()
-    opaque = property(**opaque())
-    
-    def border_size():
-        def fget(self):
-            frame = self.findChild(name='frame')
-            return frame.border_size
-        
-        def fset(self, border_size):
-            frame = self.findChild(name='frame')
-            frame.border_size = border_size
-        
-        return locals()
-    border_color = property(**border_size())
-    
-    def __init__(self, min_size=(0, 0), max_size=(9999, 9999), border_size=1,
-                 **kwargs):
-        self._min_size = min_size
-        self._max_size = max_size
-        self.views = {}
-        tab_bar = HBox(name='tabBar')
-        tab_bar.min_size = (0, 20)
-        tab_bar.max_size = (9999, 20)
-        self.view = ScrollArea(name='view')
-        self.view.min_size = self._min_size
-        self.view.max_size = self._max_size
-        self.view.border_size = border_size
-        frame = VBox(name='frame')
-        frame.border_size = border_size
-        frame.opaque = 0
-        frame.addChild(self.view)
-        VBox.__init__(self, **kwargs)
-        self.padding = 0
-        VBox.addChild(self, tab_bar)
-        VBox.addChild(self, frame)
-        self.adaptLayout()
-    
-    def addTab(self, text):
-        text = unicode(text)
-        tab = Button(text=text)
-        tab_bar = self.findChild(name='tabBar')
-        tab_bar.addChild(tab)
-        tab.capture(callbackWithArguments(self.showView, text))
-        self.adaptLayout()
-    
-    def addChild(self, child):
-        name = child.name or unicode(str(child))
-        self.addTab(name)
-        self.views[name] = child
-        if len(self.views) == 1:
-            # Show the first view by default.
-            self.showView(name)
-    
-    def showView(self, name):
-        view = self.views[name]
-        self.view.content = view
-        self.adaptLayout()
--- a/src/parpg/inventory.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +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 <http://www.gnu.org/licenses/>.
-
-import copy
-
-# TODO: many missing function definitions in this code
-
-class Inventory(Container):
-    """The class to represent inventory 'model': allow operations with
-       inventory contents, perform weight/bulk calculations, etc"""
-    def __init__(self, **kwargs):
-        """Initialise instance"""
-        Container.__init__(self,  **kwargs)
-        self.items = {"head": Slot(), "neck": Slot(),
-                      "shoulders": Slot(), "chest": Slot(),
-                      "abdomen": Slot(), "left_arm": Slot(),
-                      "right_arm": Slot(),"groin": Slot(),
-                      "hips": Slot(), "left_leg": Slot(),
-                      "right_leg": Slot(), "left_hand": Slot(),
-                      "right_hand": Slot(), "ready": Container(),
-                      "backpack": Container()}
-        for key, item in self.items.iteritems():
-            item.name = key
-            kwargs = {}
-            kwargs["container"] = item
-            item.setScript("onPlaceItem", self.onChildPlaceItem, kwargs = kwargs)
-        self.item_lookup = {}
-        
-    def onChildPlaceItem(self, container):
-        for item in container.items.itervalues():
-            self.item_lookup[item.ID] = container.name  
-
-    def placeItem(self, item, index=None):
-        self.items["backpack"].placeItem(item, index)
-        #self.item_lookup[item.ID] = "backpack"
-        
-    def takeItem(self, item):
-        if not item.ID in self.item_lookup:
-            raise ValueError ('I do not contain this item: %s' % item)
-        self.items[self.item_lookup[item.ID]].takeItem(item)
-        del self.item_lookup[item.ID]
-
-    def removeItem(self, item):
-        if not item.ID in self.item_lookup:
-            raise ValueError ('I do not contain this item: %s' % item)
-        self.items[self.item_lookup[item.ID]].removeItem(item)
-        del self.item_lookup[item.ID]
-
-    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
-        """
-        if not old_item.ID in self.item_lookup:
-            raise ValueError ('I do not contain this item: %s' % old_item)
-        self.items[self.item_lookup[old_item.ID]]\
-            .replaceItem(old_item, new_item)
-
-    def getWeight(self):
-        """Total weight of all items in container + container's own weight"""
-        return sum((item.weight for item in self.items.values()))
-
-    def setWeightDummy(self, weight):
-        pass
-
-    weight = property(getWeight, setWeightDummy, "Total weight of container")
-
-
-    def count(self, item_type = ""):
-        return sum(item.count(item_type) for item in self.items.values())
-    
-    def takeOff(self, item):
-        return self.moveItemToSlot(item, "backpack")
-
-    def moveItemToSlot(self,item,slot,index=None):
-        if not slot in self.items:
-            raise(ValueError("%s: No such slot" % slot))
-
-        if item.ID in self.item_lookup:
-            self.items[self.item_lookup[item.ID]].takeItem(item)
-        try:
-            self.items[slot].placeItem(item, index)
-        except Container.SlotBusy:
-            if index == None :
-                offending_item = self.items[slot].items[0]
-            else :
-                offending_item = self.items[slot].items[index]
-            self.items[slot].takeItem(offending_item)
-            self.items[slot].placeItem(item, index)
-            self.placeItem(offending_item)
-        self.item_lookup[item.ID] = slot
-     
-    def getItemsInSlot(self, slot, index=None):
-        if not slot in self.items:
-            raise(ValueError("%s: No such slot" % slot))
-        if index != None:
-            return self.items[slot].items.get(index)
-        else:
-            return copy.copy(self.items[slot].items)
-
-    def isSlotEmpty(self, slot, index=None):
-        if not slot in self.items:
-            raise(ValueError("%s: No such slot" % slot))
-        if index == None:
-            return self.items[slot].count() == 0
-        else:
-            return not index in self.items[slot].items
-                 
-
-    def has(self, item_ID):
-        return item_ID in self.item_lookup
-
-    def findItemByID(self, ID):
-        if ID not in self.item_lookup:
-            return None
-        return self.items[self.item_lookup[ID]].findItemByID(ID)
-
-    def findItem(self, **kwargs):
-        """Find an item in inventory by various attributes. All parameters 
-           are optional.
-           @type name: String
-           @param name: Object name. If the name is non-unique, 
-                        first matching object is returned
-           @type kind: String
-           @param kind: One of the possible object kinds like "openable" or 
-                        "weapon" (see base.py)
-           @return: The item matching criteria or None if none was found"""
-        for slot in self.items:
-            item_found = self.items[slot].findItem(**kwargs)
-            if item_found != None:
-                return item_found
-        return None
-
-    def __repr__(self):
-        return "[Inventory contents: " + \
-                            reduce((lambda a,b: str(a) 
-                                    + ', ' + str(b)), 
-                                    self.items.values()) + " ]"
-
-    def serializeInventory(self):
-        """Returns the inventory items as a list"""
-        inventory = []
-        inventory.extend(self.items["backpack"].serializeItems())
-        for key, slot in self.items.iteritems():
-            if key == "ready" or key == "backpack":
-                continue
-            elif len(slot.items) > 0:
-                item = slot.items[0]
-                item_dict = item.getStateForSaving()
-                item_dict["slot"] = key                                
-                item_dict["type"] = type(item).__name__ 
-                inventory.append(item_dict)
-        return inventory
-            
-    def getStateForSaving(self):
-        """Returns state for saving
-        """
-        state = {}
-        state["Inventory"] = self.serializeInventory()
-        return state
--- a/src/parpg/main.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-#!/usr/bin/env python2 
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-import logging
-import sys
-from os.path import abspath
-
-from parpg.settings import Settings
-
-      
-def main(args, opts):
-    settings = Settings(*args)
-    
-    settings.parpg.DataPath = abspath(settings.parpg.DataPath)
-    
-    levels = {'debug': logging.DEBUG,
-              'info': logging.INFO,
-              'warning': logging.WARNING,
-              'error': logging.ERROR,
-              'critical': logging.CRITICAL}
-    
-    #TODO: setup formating
-    logging.basicConfig(filename=opts.logfile, level=levels[opts.loglevel])
-    logger = logging.getLogger('parpg')
-    
-    try:
-        old_path = sys.path
-        sys.path = [settings.parpg.FifePath]
-        import fife
-    except AttributeError:
-        logger.warning('[parpg] section has no FifePath option')
-    except ImportError:
-        logger.critical("Could not import fife module. Please install fife or add "
-                        "'FifePath' to the [parpg] section of your settings file")
-        sys.exit(1)
-    finally:
-        sys.path = old_path
-    
-    from parpg.application import PARPGApplication
-    from parpg.common import utils
-    
-    # enable psyco if available and in settings file
-    try:
-        import psyco
-        psyco_available = True
-    except ImportError:
-        logger.warning('Psyco Acceleration unavailable')
-        psyco_available = False
-    
-    if settings.fife.UsePsyco:
-        if psyco_available:
-            psyco.full()
-            logger.info('Psyco Acceleration enabled')
-        else:
-            logger.warning('Please install psyco before attempting to use it'
-                            'Psyco Acceleration disabled')
-    else:
-        logger.info('Psycho Acceleration disabled')
-    
-    # run the game
-    app = PARPGApplication(settings)
-    app.run()
--- a/src/parpg/mainmenucontroller.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +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 <http://www.gnu.org/licenses/
-
-from controllerbase import ControllerBase
-from charactercreationview import CharacterCreationView
-from charactercreationcontroller import CharacterCreationController
-from gamescenecontroller import GameSceneController
-from gamesceneview import GameSceneView
-
-#For debugging/code analysis
-if False:
-    from parpg.mainmenuview import MainMenuView
-    from fife import fife
-    from gamemodel import GameModel
-    from parpg import PARPGApplication
-
-class MainMenuController(ControllerBase):
-    """Controller for handling the main menu state"""
-
-    def __init__(self, engine, view, model, application):
-        """Constructor"""
-        super(MainMenuController, self).__init__(engine, view, model, 
-                                                 application)
-    
-        #this can be helpful for IDEs code analysis
-        if False:
-            assert(isinstance(self.engine, fife.Engine))
-            assert(isinstance(self.view, MainMenuView))
-            assert(isinstance(self.model, GameModel))
-            assert(isinstance(self.application, PARPGApplication))
-            assert(isinstance(self.event_manager, fife.EventManager))
-        
-        self.view.quit_callback = self.quitGame
-        self.view.new_game_callback = self.newGame
-        self.view.initalizeMainMenu(self.newGame, self.loadGame, self.quitGame)
-        self.view.showMenu()
-        self.resetMouseCursor()
-    
-    def newGame(self):
-        """Start a new game and switch to the character creation controller."""
-        view = CharacterCreationView(self.engine, self.model,
-                                     self.model.settings)
-        controller = CharacterCreationController(self.engine, view, self.model,
-                                                 self.application)
-        self.application.view = view
-        self.application.manager.swap_modes(controller)
-    
-#    def newGame(self):
-#        """Starts a new game"""
-#        view = GameSceneView(self.engine,
-#                             self.model)
-#        controller = GameSceneController(self.engine,
-#                                         view,
-#                                         self.model,
-#                                         self.application)        
-#        self.application.view = view
-#        self.application.manager.swap_modes(controller)
-#        start_map = self.model.settings.get("PARPG", "Map")
-#        self.model.changeMap(start_map)
-
-    def loadGame(self, *args, **kwargs):
-        """Loads the game state
-           @return: None"""
-
-        view = GameSceneView(self.engine,
-                             self.model)
-        controller = GameSceneController(self.engine,
-                                         view,
-                                         self.model,
-                                         self.application)        
-        self.application.view = view
-        self.application.manager.swap_modes(controller)
-        controller.loadGame(*args, **kwargs)
-        
-    def on_deactivate(self):
-        """Called when the controller is removed from the list"""
-        self.view.hideMenu()
-                                         
-    
-    def quitGame(self):
-        """Quits the game
-           @return: None"""
-        self.application.listener.quitGame()
--- a/src/parpg/mainmenuview.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +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 <http://www.gnu.org/licenses/
-
-from fife.extensions import pychan
-
-from parpg import vfs
-from viewbase import ViewBase
-from parpg.gui.filebrowser import FileBrowser
-from parpg.gui.menus import SettingsMenu
-
-class MainMenuView(ViewBase):
-    """View that is used to display the main menu"""
-
-    def __init__(self, engine, model):
-        """Constructor for MainMenuView
-           @param engine: A fife.Engine instance
-           @type engine: fife.Engine
-           @param model: a script.GameModel instance
-           @type model: script.GameModel 
-           """        
-        ViewBase.__init__(self, engine, model)
-        self.quit_window = None
-        self.new_game_callback = None
-        self.load_game_callback = None
-        self.quit_callback = None
-        self.main_menu = None
-        self.character_screen = None
-    
-    def showMenu(self):
-        """"Shows the main menu"""
-        self.main_menu_background.show()
-        self.main_menu.show()
-        
-    def hideMenu(self):
-        """"Hides the main menu"""
-        self.main_menu.hide()
-        self.main_menu_background.hide()
-
-    def initalizeMainMenu(self, new_game, load_game, quit_game):
-        """Initialized the main menu and sets the callbacks"""
-        # Set a simple background to display the main screen.
-        xml_file = vfs.VFS.open('gui/main_menu_background.xml')
-        self.main_menu_background = pychan.loadXML(xml_file)
-        
-        # Initialize the main menu screen.
-        screen_mode = self.engine.getRenderBackend().getCurrentScreenMode()
-        self.main_menu_background.width = screen_mode.getWidth()
-        self.main_menu_background.height = screen_mode.getHeight()
-
-        xml_file = vfs.VFS.open('gui/main_menu.xml')
-        self.main_menu = pychan.loadXML(xml_file)
-
-        self.main_menu.adaptLayout()
-        self.new_game_callback = new_game
-        self.load_game_callback = load_game
-        self.quit_callback = quit_game
-        menu_events = {}
-        menu_events["newButton"] = self.newGame
-        menu_events["loadButton"] = self.loadGame
-        menu_events["settingsButton"] = self.displaySettings
-        menu_events["quitButton"] = self.quitGame
-        self.main_menu.mapEvents(menu_events)
-        
-        self.initializeQuitDialog()
-        self.initializeSettingsMenu()
-    
-    def newGame(self):
-        """Called when user request to start a new game.
-           @return: None"""
-        self.new_game_callback()
-    
-    def loadGame(self):
-        """ Called when the user wants to load a game.
-            @return: None"""
-        load_browser = FileBrowser(self.engine,
-                                   self.model.settings,
-                                   self.load_game_callback,
-                                   gui_xml_path='gui/loadbrowser.xml',
-                                   save_file=False,
-                                   extensions=('.dat'))
-        load_browser.showBrowser()
-    
-    def initializeQuitDialog(self):
-        """Creates the quit confirmation dialog
-           @return: None"""
-        
-        self.quit_window = pychan.widgets.Window(title=unicode("Quit?"), \
-                                                 min_size=(200,0))
-
-        hbox = pychan.widgets.HBox()
-        are_you_sure = "Are you sure you want to quit?"
-        label = pychan.widgets.Label(text=unicode(are_you_sure))
-        yes_button = pychan.widgets.Button(name="yes_button", 
-                                           text=unicode("Yes"),
-                                           min_size=(90,20),
-                                           max_size=(90,20))
-        no_button = pychan.widgets.Button(name="no_button",
-                                          text=unicode("No"),
-                                          min_size=(90,20),
-                                          max_size=(90,20))
-
-        self.quit_window.addChild(label)
-        hbox.addChild(yes_button)
-        hbox.addChild(no_button)
-        self.quit_window.addChild(hbox)
-
-        events_to_map = { "yes_button": self.quit_callback,
-                          "no_button":  self.quit_window.hide }
-        
-        self.quit_window.mapEvents(events_to_map)
-
-
-    def quitGame(self):
-        """Called when user requests to quit game.
-           @return: None"""
-        self.quit_window.show()
-
-    def initializeSettingsMenu(self):
-        self.settings_menu = SettingsMenu(self.engine, self.model.settings)
-
-    def displaySettings(self):
-        self.settings_menu.show()
--- a/src/parpg/mode.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-
-from parpg.bGrease.mode import *
-import abc
-
-class FifeManager(BaseManager):
-
-        def __init__(self):
-                self.modes = []
-
-        def _pump(self):
-                if self.current_mode:
-                        self.current_mode.pump(self.current_mode.engine.getTimeManager().getTimeDelta() / 1000.0)
-
-class FifeMode(BaseMode):
-
-        def __init__(self):
-                BaseMode.__init__(self)
-
-        @abc.abstractmethod
-        def pump(self, dt):
-                """Performs actions every frame"""
\ No newline at end of file
--- a/src/parpg/quest_engine.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,260 +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 <http://www.gnu.org/licenses/>.
-
-import yaml
-
-from parpg.common.utils import locateFiles
-from parpg import vfs
-
-class Quest(object):
-    """Class that holds the information for a quest"""
-    def __init__(self, quest_id, quest_giver_id, quest_name, description,
-                 variables):
-        self.quest_id = quest_id
-        self.quest_giver_id = quest_giver_id
-        self.quest_name = quest_name
-        self.description = description
-        self.quest_variables = variables
-    
-    def setValue(self, variable_name, value):
-        """Set the value of a quest variable
-           @param variable_name: the name of the variable to set
-           @param value: the value you want to assign to the variable
-           @return: True on success
-           @return: False when it failes"""
-
-        if self.quest_variables.has_key(variable_name):
-            self.quest_variables[variable_name]["value"] = value
-            return True
-        else:
-            return False
-
-    def getValue(self, variable_name):
-        """Get the value of a quest_variable
-           @param variable_name: the name of the variable to set
-           @return: the value of the quest_variable"""
-        if self.quest_variables.has_key(variable_name):
-            return self.quest_variables[variable_name]["value"]
-        else:
-            return False
-
-    def getGoalValue(self, variable_name):
-        """Get the goal value of a quest_variable
-           @param variable_name: the name of the variable to set
-           @return: the goal value of the quest variable"""
-        if self.quest_variables.has_key(variable_name):
-            return self.quest_variables[variable_name]["goal_value"]
-        else:
-            return False
-
-    def increaseValue(self, variable_name, value):
-        """Increase a variable by a specified value
-           @param variable_name: the name of the variable to set
-           @param value: the value you want to increase the variable with
-           @return: True on success
-           @return: False when it fails"""
-        if self.quest_variables.has_key(variable_name):
-            self.quest_variables[variable_name]["value"] += value
-            return True
-        else:
-            return False
-
-    def decreaseValue(self, variable_name, value):
-        """Decrease a variable by a specified value
-           @param variable_name: the name of the variable to set
-           @param value: the value you want to decrease the variable with
-           @return: True on success
-           @return: False when it failes"""
-        if self.quest_variables.has_key(variable_name):
-            self.quest_variables[variable_name]["value"] -= value
-            return True
-        else:
-            return False
-
-    def isGoalValue(self, variable_name):
-        """Check if the variable has reached it's goal value
-           @param variable_name: the name of the variable to check
-           @return: True when the variable has reached the goal value
-           @return: False when it has not reached the goal value"""
-        if self.quest_variables.has_key(variable_name):
-            return self.quest_variables[variable_name]["value"] == \
-                    self.quest_variables[variable_name]["goal_value"]
-        else:
-            return False
-
-    def isEqualOrBiggerThanGoalValue(self, variable_name):
-        """Check if the variable is equil or bigger then it's goal value
-           @param variable_name: the name of the variable to set
-           @return: True when it has reached or exceeded the goal value
-           @return: False when it has not reached or exceeded the goal value """
-        if variable_name in self.quest_variables:
-            return self.quest_variables[variable_name]["value"] >= \
-                             self.quest_variables[variable_name]["goal_value"]
-        else:
-            return False
-    
-    def restartQuest(self):
-        """Restarts the quest. This sets all values to the reset values,
-        if there is a reset value present """
-        for variable in self.quest_variables.itervalues():
-            if variable.has_key("reset_value"):
-                variable["value"] = variable["reset_value"]
-
-class QuestEngine(dict):
-    def __init__(self, quest_dir):
-        """Create a quest engine object"""
-        dict.__init__(self)
-        self.empty_quest = Quest(None, None, None, None, {})
-        self.quests = {}
-        self.active_quests = []
-        self.finished_quests = []
-        self.failed_quests = []
-        self.quest_dir = quest_dir
-
-    def __str__(self):
-        return self.quests.__str__()
-
-    def __getitem__(self, key):
-        try:
-            return self.quests.__getitem__(key)
-        except KeyError:
-            return self.empty_quest
-
-    def items(self):
-        return self.quests.items()
-
-    def values(self):
-        return self.quests.values()
-
-    def keys(self):
-        return self.quests.keys()
-    
-    def readQuests(self):
-        """Reads in the quests in the quest directory"""
-        filepaths = locateFiles("*.yaml", self.quest_dir)
-        self.quests = {}
-        self.active_quests = []
-        self.finished_quests = []
-        self.failed_quests = []
-        for filepath in filepaths:
-            quest_file = vfs.VFS.open(filepath)
-            tree = yaml.load(quest_file)
-            quest_properties = tree["QUEST_PROPERTIES"]
-            variable_defines = tree["DEFINES"]
-    
-            self.quests[quest_properties["quest_id"]] = \
-                                  Quest(quest_properties["quest_id"],
-                                        quest_properties["quest_giver_id"],
-                                        quest_properties["quest_name"],
-                                        quest_properties["description"],
-                                        variable_defines)
-
-    def activateQuest(self, quest_id):
-        """Add a quest to the quest log
-           @param quest: the quest id of the quest to add to the quest log
-           @return: True if succesfully added
-           @return: False if failed to add"""
-
-        if quest_id in self.quests \
-            and not (quest_id in self.active_quests \
-                        or quest_id in self.finished_quests):
-            self.active_quests.append(quest_id)
-            return True
-        return False
-
-    def finishQuest(self, quest_id):
-        """Move a quest to the finished quests log
-           @param quest_id: The id of the quest you want to move
-           @return: True on success
-           @return: False when it failes"""
-        if quest_id in self.active_quests:
-            self.finished_quests.append(quest_id)
-            self.active_quests.remove(quest_id)
-            return True
-        return False
-    
-    def restartQuest(self, quest_id):
-        """Restart a quest
-           @param quest_id: ID of the quest you want to restart
-           @return: True on success
-           @return: False when it failes"""
-        if quest_id in self.active_quests:
-            self.quests[quest_id].restartQuest()
-    
-    def failQuest(self, quest_id):
-        """Set a quest to failed
-           @param quest_id: ID of the quest you want to fail
-           @return: True on success
-           @return: False when it failes"""
-        if quest_id in self.active_quests:
-            self.failed_quests.append(quest_id)
-            self.active_quests.remove(quest_id)
-            return True
-        return False
-            
-    def hasQuest(self, quest_id):
-        """Check whether a quest is present in the quest_list.
-        It doesn't matter which state the quest is, or even if its
-        started.
-        @param quest_id: ID of the quest you want to check
-        @return: True on when the quest is in the quest log
-        @return: False when it's not in the quest log"""
-        return quest_id in self.quests
-
-    def hasActiveQuest(self, quest_id):
-        """Check whether a quest is in the quest log
-        @param quest_id: ID of the quest you want to check
-        @return: True on when the quest is in the quest log
-        @return: False when it's not in the quest log"""
-        return quest_id in self.active_quests
-
-    def hasFinishedQuest(self, quest_id):
-        """Check whether a quest is in the finished quests log
-        @param quest_id: ID of the quest you want to check
-        @return: True on when the quest is in the finished quests log
-        @return: False when it's not in the finished quests log"""
-        return quest_id in self.finished_quests
-    
-    def hasFailedQuest(self, quest_id):
-        """Check whether a quest is in the failed quests log
-        @param quest_id: ID of the quest you want to check
-        @return: True on when the quest is in the failed quests log
-        @return: False when it's not in the failed quests log"""
-        return quest_id in self.failed_quests
-    
-    def getStateForSaving(self):
-        """Prepares state for saving
-        @type state: dictionary
-        @param state: State of the object"""
-        ret_dict = {}
-        variables_dict = ret_dict["Variables"] = {}
-        for quest in self.quests.itervalues():
-            quest_dict = variables_dict[quest.quest_id] = {}
-            for variable, data in quest.quest_variables.iteritems():
-                quest_dict[variable] = data["value"]
-        ret_dict["ActiveQuests"] = self.active_quests
-        ret_dict["FinishedQuests"] = self.finished_quests
-        ret_dict["FailedQuests"] = self.failed_quests
-        return ret_dict
-
-    def restoreFromState(self, state):
-        """Restores the state"""
-        variables_dict = state["Variables"]
-        for quest_id, variables in variables_dict.iteritems():
-            for variable, value in variables.iteritems():
-                self.quests[quest_id].setValue(variable, value)
-        self.active_quests = state["ActiveQuests"]
-        self.finished_quests = state["FinishedQuests"]
-        self.failed_quests = state["FailedQuests"]
--- a/src/parpg/serializers.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +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 <http://www.gnu.org/licenses/>.
-"""
-Provides classes used to serialize and deserialize Python classes.
-"""
-
-from abc import ABCMeta, abstractmethod
-try:
-    from xml.etree import cElementTree as ElementTree
-except ImportError:
-    from xml.etree import ElementTree
-try:
-    from collections import OrderedDict
-except ImportError:
-    from .common.ordereddict import OrderedDict
-
-from .common.utils import dedent_chomp
-
-import logging
-
-logger = logging.getLogger('serializers')
-
-class Serializable(object):
-    def __init__(self, class_, init_args=None, attributes=None):
-        self.class_ = class_
-        if init_args is not None:
-            self.init_args = OrderedDict(init_args)
-        else:
-            self.init_args = OrderedDict()
-        if attributes is not None:
-            self.attributes = OrderedDict(attributes)
-        else:
-            self.attributes = OrderedDict()
-
-
-class SerializableRegistry(object):
-    """
-    Class holding the data used to serialize and deserialize a particular
-    Python object.
-    """
-    registered_classes = {}
-    
-    @classmethod
-    def registerClass(cls, name, class_, init_args=None, attributes=None):
-        serializable = Serializable(class_, init_args, attributes)
-        cls.registered_classes[name] = serializable
-
-
-class AbstractSerializer(object):
-    __metaclass__ = ABCMeta
-    
-    @abstractmethod
-    def serialize(self, object_, stream):
-        pass
-    
-    @abstractmethod
-    def deserialize(self, stream):
-        pass
-
-
-class XmlSerializer(AbstractSerializer):
-    def serialize(self, statistic, stream):
-        pass
-    
-    @classmethod
-    def deserialize(cls, stream):
-        element_tree = ElementTree.parse(stream)
-        root_element = element_tree.getroot()
-        object_ = cls.construct_object(root_element)
-        return object_
-    
-    @classmethod
-    def construct_object(cls, element):
-        element_name = element.tag
-        if element_name in SerializableRegistry.registered_classes.keys():
-            object_ = cls.construct_registered_class(element)
-        elif len(element) > 0:
-            # Element contains subelements, so we'll treat it as an
-            # OrderedDict.
-            if element_name == 'list':
-                object_ = cls.construct_list(element)
-            else:
-                object_ = cls.construct_ordered_dict(element)
-        else:
-            object_ = cls.construct_primitive(element)
-        return object_
-    
-    @classmethod
-    def construct_registered_class(cls, element):
-        element_name = element.tag
-        serializable = SerializableRegistry.registered_classes[element_name]
-        class_ = serializable.class_
-        init_args = OrderedDict()
-        for subelement in element:
-            arg = cls.construct_object(subelement)
-            subelement_name = subelement.tag
-            init_args[subelement_name] = arg
-        try:
-            object_ = class_(**init_args)
-        except (TypeError, ValueError) as exception:
-            logger.error(init_args)
-            error_message = \
-                'unable to deserialize tag {0}: {1}'.format(element_name,
-                                                            exception)
-            raise ValueError(error_message)
-        return object_
-    
-    @classmethod
-    def construct_ordered_dict(cls, element):
-        object_ = OrderedDict()
-        for subelement in element:
-            child = cls.construct_object(subelement)
-            name = subelement.tag
-            object_[name] = child
-        return object_
-    
-    @classmethod
-    def construct_list(cls, element):
-        object_ = []
-        for subelement in element:
-            child = cls.construct_object(subelement)
-            object_.append(child)
-        return object_
-    
-    @classmethod
-    def construct_primitive(cls, element):
-        text = element.text
-        # Interpret the element's text as unicode by default.
-        element_type = element.attrib.get('type', 'unicode')
-        if element_type == 'unicode':
-            formatted_text = dedent_chomp(text)
-            object_ = unicode(formatted_text)
-        elif element_type == 'str':
-            formatted_text = dedent_chomp(text)
-            object_ = str(formatted_text)
-        elif element_type == 'int':
-            object_ = int(text)
-        elif element_type == 'float':
-            object_ = float(text)
-        else:
-            error_message = '{0!r} is not a recognized primitive type'
-            error_message.format(element_type)
-            raise ValueError(error_message)
-        return object_
--- a/src/parpg/settings.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,491 +0,0 @@
-#!/usr/bin/env python2
-
-#  Copyright (C) 2011  Edwin Marshall <emarshall85@gmail.com>
-
-#   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/>.
-
-""" Provides a class used for reading and writing various configurable options
-    throughout the game
-
-    This class produces an INI formated settings file as opposed to an XML
-    formatted one. The reason that python's built-in ConfigurationParser isn't 
-    sufficient is because comments aren't preserved when writing a settings
-    file, the order in which the options are written isn't preserved, and the 
-    interface used with this class is arguably more convenient that
-    ConfigParser's.
-
-    Default Settings may be generated by envoking this module from the
-    command line:
-        python -m settings.py [system] [data_directory]
-
-    where [system] is one of local, windows, or linux (mac coming soon),
-    and data_directory is the base path for the data files to be loaded.
-
-    Both [system] and [data_directory] are option. If omitted, both
-    default to whichever what is reasonable based on the system settings.py
-    is run on
-"""
-
-import os
-import sys
-import platform
-
-#TODO: add logging to replace print statements
-class Section(object):
-    """ An object that represents a section in a settings file.
-
-        Options can be added to a section by simply assigning a value to an 
-        attribute:
-            section.foo = baz
-        would produce:
-            [section]
-            foo = baz
-        in the settings file. Options that do not exist on assignment
-        are created dynamcially.
-
-        Values are automatically converted to the appropriate python type. 
-        Options that begin and end with brackets([, ]) are converted to lists,
-        and options that are double-quoted (") are converted to strings. 
-        Section also recognizes booleans regardless of case, in addition to the
-        literals 'yes' and 'no' of any case. Except in the case of 
-        double-quoted strings, extra white-space is trimmed, so you need not 
-        worry. For example:
-            foo = bar
-        is equivalent to :
-            foo    =         baz
-    """
-    def __init__(self, name):
-        """ Initialize a new section.
-
-            @param name: name of the section. In the INI file, sections are surrounded
-                         by brackets ([name])
-            @type name: string
-        """
-        self.name = name
-
-    def __setattr__(self, option, value):
-        """ Assign a value to an option, converting types when appropriate.
-
-            @param option: name of the option to assign a value to.
-            @type option: string @param value: value to be assigned to the option.
-            @type value: int, float, string, boolean, or list
-        """
-        value = str(value)
-        if value.startswith('[') and value.endswith(']'):
-            value = [item.strip() for item in value[1:-1].split(',')]
-        elif value.lower() == 'true' or value.lower() == 'yes':
-            value = True
-        elif value.lower() == 'false' or value.lower() == 'no':
-            value = False
-        elif value.isdigit():
-            value = int(value)
-        else:
-            try:
-                value = float(value)
-            except ValueError:
-                # leave as string
-                pass
-
-        self.__dict__[option] = value
-
-    def __getattribute__(self, option):
-        """ Returns the option's value"""
-        # Remove leading and trailing quotes from strings that have them
-        return_value = object.__getattribute__(self, option)
-        try:
-            for key, value in return_value.iteritems():
-                if (hasattr(value, 'split') and 
-                    value.startswith("\"") and value.endswith("\"")):
-                    return_value[key] = value[1:-1]
-        except AttributeError:
-            pass
-
-        return return_value
-
-    @property
-    def options(self):
-        """ Returns a dictionary of existing options """
-        options = self.__dict__
-        # get rid of properties that aren't actually options
-        if options.has_key('name'):
-            options.pop('name')
-
-        return options
-
-class Settings(object):
-    """ An object that represents a settings file, its sectons,
-        and the options defined within those sections.
-    """
-    def __init__(self, settings_path='', system_path='', user_path='',
-                 filename='parpg.cfg'):
-        """ initializes a new settings object. If no paths are given, they are
-            guessed based on whatever platform the script was run on.
-
-            Examples:
-                paths = ['/etc/parpg', '/home/user_name/.config/parpg']
-                settings = Settings(*paths)
-                
-                paths = {'system': '/etc/parpg', 
-                         'user': '/home/user_name/.config/parpg'}
-                settings = Settings(**paths)
-
-                settings = Settings('.')
-
-                settigns = Settings()
-
-            @param system_path: Path to the system settings file.
-            @type system_path: string (must be a valid path)
-
-            @param user_path: Path to the user settings file. Options that
-                              are missing from this file are propogated 
-                              from the system settings file and saved on
-                              request
-            @type user_path: string (must be a valid path)
-            
-            @param suffix: Suffix of the settings file that will be generated.
-            @type suffix: string
-        """
-        self.filename = filename
-        self.settings_file = ''
-        
-        self.paths = {}
-        if not system_path and not user_path and not settings_path:
-            # use platform-specific values as paths
-            (self.paths['system'], self.paths['user'], 
-             self.paths['settings']) = self.platform_paths()
-        else:
-            # convert supplied paths to absolute paths
-            abs_paths = [os.path.expanduser(path)
-                         for path in [system_path, user_path, settings_path]]
-            (self.paths['system'], self.paths['user'],
-             self.paths['settings']) = abs_paths
-
-        self.read()
-
-
-    def __getattr__(self, name):
-        """ Returns a Section object to be used for assignment, creating one
-            if it doesn't exist.
-
-            @param name: name of section to be retrieved
-            @type name: string
-        """
-        if name in ['get', 'set']:
-            raise AttributeError("{0} is deprecated. Please consult Settings' "
-                                  "documentation for information on how to "
-                                  "create/modify sections and their respective "
-                                  "options".format(name))
-        else:
-            if not self.__dict__.has_key(name):
-                setattr(self, name, Section(name))
-
-        return getattr(self, name)
-
-    def platform_paths(self, system=None):
-        if system is None:
-            system = platform.system().lower()
-        
-        if system == 'linux':
-            return (os.path.join(os.sep, 'usr', 'share', 'parpg'),
-                    os.path.join(os.environ['XDG_CONFIG_HOME'], 'parpg'),
-                    os.path.join(os.sep, 'etc', 'parpg'))
-        elif system == 'windows':
-            return (os.path.join(os.environ['PROGRAMFILES'], 'PARPG'),
-                    os.path.join(os.environ['USERDATA'], 'PARPG'),
-                    os.path.join(os.environ['PROGRAMFILES'], 'PARPG'))
-        else:
-            # TODO: determine values for Mac
-            return None
-
-    def read(self, filenames=None):
-        """ Reads a settings file and populates the settings object 
-            with its sections and options. Calling this method without
-            any arguments simply re-reads the previously defined filename
-            and paths
-
-            @param filenames: name of files to be parsed. 
-            @type path: string or list
-        """
-        
-        if filenames is None:
-            filenames = [os.path.join(self.paths['settings'], self.filename),
-                         os.path.join(self.paths['user'], self.filename)]
-        elif hasattr(filenames, 'split'):
-            filenames = [filenames]
-
-        for filename in filenames:
-            section = None
-            if os.path.exists(filename):
-                try:
-                    self.settings_file = open(filename, 'r').readlines()
-                except IOError as (errno, strerror):
-                    if errno == 2:
-                        if os.path.basename(filename).startswith('system'):
-                            print ('{0} could not be found. Please supply a '
-                                   'different path or generate a system settings '
-                                   'file with:\n'
-                                   'python2 -m parpg.settings').format(filename)
-                            sys.exit(1)
-                    else:
-                        print 'Error No. {0}: {1} {2}'.format(errno, filename, strerror)
-                        sys.exit(1)
-
-                for line in self.settings_file:
-                    if line.startswith('#') or line.strip() == '':
-                        continue
-                    elif line.startswith('[') and line.endswith(']\n'):
-                        getattr(self, line[1:-2])
-                        section = line[1:-2]
-                    else:
-                        option, value = [item.strip() 
-                                         for item in line.split('=', 1)]
-                        setattr(getattr(self, section), option, value)
-
-    def write(self, filename=None):
-        """ Writes a settings file based on the settings object's 
-            sections and options
-
-            @param filename: Name of file to save to. By default, this is
-                             the user settings file.
-            @type path: string
-        """
-        if filename is None:
-            filename = os.path.join(self.paths['user'], 
-                                    'user{0}'.format(self.suffix))
-
-        for section in self.sections:
-
-            if '[{0}]\n'.format(section) not in self.settings_file:
-                self.settings_file.append('\n[{0}]\n'.format(section))
-                for option, value in getattr(self, section).options.iteritems():
-                    template = '{0} = {1}\n'.format(option, value)
-                    self.settings_file.append(template)
-            else:
-                start_of_section = (self.settings_file
-                                        .index('[{0}]\n'.format(section)) + 1)
-
-                for option, value in getattr(self, 
-                                             section).options.iteritems():
-                    if hasattr(value, 'sort'):
-                        value = '[{0}]'.format(', '.join(value))
-
-                    new_option = False
-                    template = '{0} = {1}\n'.format(option, value)
-                    for index, line in enumerate(self.settings_file[:]):
-                        if option in line:
-                            new_option = False
-                            if str(value) not in line:
-                                self.settings_file[index] = template
-
-                            break
-                        else:
-                            new_option = True
-                    if new_option:
-                        while self.settings_file[start_of_section].startswith('#'):
-                            start_of_section += 1
-
-                        self.settings_file.insert(start_of_section, template)
-
-        with open(filename, 'w') as out_stream:
-            for line in self.settings_file:
-                out_stream.write(line)
-
-    @property
-    def sections(self):
-        """ Returns a list of existing sections"""
-        sections = self.__dict__.keys()
-        sections.pop(sections.index('settings_file'))
-        sections.pop(sections.index('paths'))
-        sections.pop(sections.index('suffix'))
-        sections.pop(sections.index('filename'))
-        
-        return sections
-
-    @property
-    def system_path(self):
-        return self.paths['system']
-
-    @property
-    def user_path(self):
-        return self.paths['user']
-
-    @property
-    def settings_path(self):
-        return self.paths['settings']
-
-DEFAULT_SETTINGS = """\
-[fife]
-#------------------------------------------------------------------------------
-# Options marked with ? are untested/unknown
-
-# Game window's title (string) DO NOT EDIT!
-WindowTitle = PARPG Techdemo 2
-
-# Icon to use for the game window's border (filename) DO NOT EDIT!
-WindowIcon = window_icon.png
-
-# Video driver to use. (?)
-VideoDriver = ""
-
-# Backend to use for graphics (OpenGL|OpenGLe|SDL)
-RenderBackend = OpenGL 
-
-# Run the game in fullscreen mode or not. (True|False)
-FullScreen = False
-
-# Screen Resolution's width. Not used if FullScreen is set to False 
-# (800|1024|etc)
-ScreenWidth = 1024
-
-# Screen Resolution's height. Not used if FullScreen is set to False 
-# (600|768|etc)
-ScreenHeight = 768
-
-# Screen DPI? (?)
-BitsPerPixel = 0
-
-# ? (?)
-SDLRemoveFakeAlpha = 1
-
-# Use Framebuffer Objects (True|False)
-GLUseFramebuffer = True
-
-# Use NPOT textures (True|False)
-GLUseNPOT = True
-
-# The Sensitivity of the mouse. (-0.99 to 10.0)
-MouseSensitivity = 0.0
-
-# Sets whether the mouse should be accelerated. (True|False)
-MouseAcceleration = False
-
-# Subdirectory to load icons from (path)
-IconsPath = icons
-
-# ? ([R, G, B])
-ColorKey = [250, 0, 250]
-
-# ? (True|False)
-ColorKeyEnabled = False
-
-# Turn on sound effects and music (True|False)
-EnableSound = True
-
-# Initial volume of sound effects and music (0.0-100.0?)
-InitialVolume = 5.0
-
-# Characters to use to render fonts. DO NOT EDIT!
-FontGlyphs = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\""
-
-# Subdirectory to load fronts from (path)
-FontsPath = fonts
-
-# Font to load when game starts
-Font = oldtypewriter.ttf
-
-# Size of in-game fonts
-DefaultFontSize = 12
-
-# ? (?)
-LogModules = [controller]
-
-# ? (?)
-PychanDebug = False
-
-# use Psyco Acceperation (True|False)
-UsePsyco = False
-
-# ? (?)
-ProfilingOn = False
-
-# Lighting Model to use (0-2)
-Lighting = 0
-
-[parpg]
-#------------------------------------------------------------------------------
-
-# System subdirectory to load maps from (path)
-MapsPath = maps
-
-# YAML file that contains the available maps (filename)
-MapsFile = maps.yaml
-
-# Map to load when game starts (filename)
-Map = Mall
-
-# ? (filename)
-AllAgentsFile = all_agents.yaml
-
-# System subdirectory to load objects from (path)
-ObjectsPath = objects
-
-# YAML file that contains the database of availabel objects (filename)
-ObjectDatabaseFile = object_database.yaml
-
-# System subdirectory to load dialogues from (path)
-DialoguesPath = dialogue
-
-# System subdirectory to load quests from (path)
-QuestsPath = quests
-
-# User subdirectory to save screenshots to
-ScreenshotsPath = screenshots
-
-# User subdirectory to save games to
-SavesPath = saves
-
-# System subdirectory where gui files are loaded from (path)
-GuiPath = gui
-
-# System subdirectory where cursors are loaded from (path)
-CursorPath = cursors
-
-# File to use for default cursor (filename)
-CursorDefault = cursor_plain.png
-
-# File to use for up cursor (filename)
-CursorUp = cursor_up.png
-
-# File to use for right cursor (filename)
-CursorRight = cursor_right.png
-
-# File to use for down cursor (filename)
-CursorDown = cursor_down.png
-
-# File to use for left cursor (filename)
-CursorLeft = cursor_left.png
-
-# how many pixles to move the camera per time frame (digit)
-ScrollSpeed = 1.0
-
-# Player walk speed (digit)
-PCSpeed = 3\
-"""
-
-if __name__ == '__main__':
-    from optparse import OptionParser
-
-    usage = "usage: %prog [options] system[, system, ...]"
-    parser = OptionParser(usage=usage)
-
-    parser.add_option('-f', '--filename', default='system.cfg',
-                      help='Filename of output configuration file')
-
-    opts, args = parser.parse_args()
-    
-    with open(opts.filename, 'w') as f:
-        for line in DEFAULT_SETTINGS:
-            f.write(line)
--- a/src/parpg/sounds.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +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 <http://www.gnu.org/licenses/>.
-
-# sounds.py holds the object code to play sounds and sound effects
-from fife import fife
-
-class SoundEngine:
-    def __init__(self, fife_engine):
-        """Initialise the SoundEngine instance
-           @type fife_engine: fine.Engine
-           @param fife_engine: Instance of the Fife engine
-           @return: None"""
-        self.engine = fife_engine
-        self.sound_engine = self.engine.getSoundManager()
-        self.sound_engine.init()
-        # set up the sound
-        self.music = self.sound_engine.createEmitter()
-        self.music_on = False
-        self.music_init = False
-    
-    def playMusic(self, sfile=None):
-        """Play music, with the given file if passed
-           @type sfile: string
-           @param sfile: Filename to play
-           @return: None"""
-        if(sfile is not None):
-            # setup the new sound
-            sound = self.engine.getSoundClipManager().load(sfile)
-            self.music.setSoundClip(sound)
-            self.music.setLooping(True)
-            self.music_init = True
-        self.music.play()
-        self.music_on = True
-
-    def pauseMusic(self):
-        """Stops current playback
-           @return: None"""
-        if(self.music_init == True):
-            self.music.pause()
-            self.music_on = False
-
-    def toggleMusic(self):
-        """Toggle status of music, either on or off
-           @return: None"""
-        if((self.music_on == False)and(self.music_init == True)):
-            self.playMusic()
-        else:
-            self.pauseMusic()
-
-    def setVolume(self, volume):
-        """Set the volume of the music
-           @type volume: integer
-           @param volume: The volume wanted, 0 to 100
-           @return: None"""
-        self.sound_engine.setVolume(0.01 * volume)
-
--- a/src/parpg/systems/__init__.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from scriptingsystem import ScriptingSystem
\ No newline at end of file
--- a/src/parpg/systems/gamerulessystem.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from parpg.bGrease import System
-
-class GameRulesSystem(System):
-    """
-    System responsible for defining the game rules and mechanics by which
-    characters interact with the world.
-    """
-    
-    pass
--- a/src/parpg/systems/scriptingsystem.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from collections import deque
-from copy import deepcopy
-
-from parpg.bGrease import System
-
-class Script(object):
-    """Script object"""
-
-    def __init__(self, actions, system):
-        """Constructor"""
-        assert(isinstance(actions, deque))
-        self.actions = actions
-        assert(isinstance(system, ScriptingSystem))
-        self.system = system
-        self.reset()
-
-    def reset(self):
-        """Resets the state of the script"""
-        self.running_actions = deepcopy(self.actions)
-        self.running = False
-        self.finished = False
-        self.time = 0
-        self.wait = 0
-        self.cur_action = None
-    
-    def update(self, time):
-        """Advance the script"""
-        if not self.running:
-            return
-        if self.cur_action and not self.cur_action.executed:
-            return
-        self.time += time
-        if self.wait <= self.time:
-            self.time = 0		    
-            try:
-                action_data = self.running_actions.popleft()
-                action = self.system.actions[action_data[0]]
-                action_params = eval(action_data[1], 
-                                          self.system.funcs, 
-                                          self.system.vals
-                                          ) 
-                if not (isinstance(action_params, list) 
-                        or isinstance(action_params, tuple)):
-                    action_params = [action_params]
-                self.cur_action = action(self.system.world, *action_params)
-                self.wait = action_data[2]
-                if len(action_data) >= 4:
-                    vals = (
-                        eval(action_data[4], self.system.funcs, self.system.vals) 
-                        if len(action_data) > 4
-                        else ()
-                    )
-                    command = action_data[3]
-                    self.system.commands[command](
-                        *vals, 
-                        action=self.cur_action
-                    )
-                else:
-                    self.cur_action.execute()
-            except IndexError:
-                self.finished = True
-                self.running = False
-
-
-class ScriptingSystem(System):
-    """
-    System responsible for managing scripts attached to entities to define 
-    their behavior.
-    """
-
-    def __init__(self, commands, actions):
-        """Constructor"""
-        self.funcs = {}
-        self.vals = {}
-        self.commands = commands
-        self.actions = actions
-        self.game_state = None
-        self.reset()
-
-    def reset(self):
-        """Resets the script and condition collections"""
-        self.scripts = {}
-        self.conditions = []
-        
-    
-    def step(self, dt):
-        """Execute a time step for the system. Must be defined
-        by all system classes.
-
-        :param dt: Time since last step invocation
-        :type dt: float
-        """
-        self.vals.clear()        
-        self.vals.update(
-            self.game_state.getObjectDictOfMap(
-                self.game_state.current_map_name)
-        )
-        self.funcs.clear()
-        self.funcs.update(self.game_state.funcs)
-        for condition_data in self.conditions:
-            condition = condition_data[0]
-            script_name = condition_data[1]
-            if not self.scripts.has_key(script_name):
-                return
-            script = self.scripts[script_name]
-            if eval(condition, self.funcs, self.vals) and not script.running:
-                script.running = True
-        for script in self.scripts.itervalues():
-            assert(isinstance(script, Script))
-            if script.finished:
-                script.reset()
-            elif script.running:
-                script.update(dt)
-                
-    def setScript(self, name, actions):
-        """Sets a script.
-        @param name: The name of the script
-        @param actions: What the script does
-        @type actions: deque or iterable
-        """
-        if not(isinstance(actions, deque)):
-            actions = deque(actions)
-        self.scripts[name] = Script(actions, 
-                                    self
-                                    )
-        
-    def addCondition(self, condition, script_name):
-        """Adds a condition.
-        @param condition: Condition which will be evaluated
-        @param script_name: Name of the script that will be executed if the
-        condition evaluates to True.
-        """
-        self.conditions.append((condition, script_name))
-    
-    
-    def runScript(self, name):
-        """Runs a script with the given name
-        @param name: The name of the script"""
-        if self.scripts.has_key(name):
-            self.scripts[name].running = True
-        
-    
\ No newline at end of file
--- a/src/parpg/vfs.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +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 <http://www.gnu.org/licenses/>.
-
-# KLUDGE M. George Hansen 2011-06-04: Die, global variable, die!
-VFS = None
\ No newline at end of file
--- a/src/parpg/viewbase.py	Thu Jan 12 18:01:28 2012 +0100
+++ /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 <http://www.gnu.org/licenses/>.
-
-class ViewBase(object):
-    """Base class for views"""
-    def __init__(self, engine, model):
-        """Constructor for engine
-           @param engine: A fife.Engine instance
-           @type engine: fife.Engine
-           @param model: a script.GameModel instance
-           @type model: script.GameModel 
-           """
-        self.engine = engine
-        self.model = model
--- a/src/parpg/world.py	Thu Jan 12 18:01:28 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-from parpg.bGrease.world import *
-from parpg.bGrease.component import Component
-
-from parpg.mode import FifeMode
-from parpg import components
-from parpg.components.fifeagent import commands
-from parpg.systems import ScriptingSystem
-from parpg.entities.action import ACTIONS
-
-class World(FifeMode, BaseWorld):
-
-    def __init__(self):
-        FifeMode.__init__(self)
-        BaseWorld.__init__(self)
-        
-    def configure(self):
-        """Configure the game world's components, systems and renderers"""
-        for name, component in components.components.iteritems():
-            setattr(self.components, name, component)
-        self.systems.scripting = ScriptingSystem(commands, ACTIONS)
-    
-    def pump(self, dt):
-        for component in self.components:
-            if hasattr(component, "step"):
-                component.step(dt)
-        for system in self.systems:
-            if hasattr(system, "step"):
-                system.step(dt)
\ No newline at end of file