changeset 148:2241722311bf

Moved the action module into the entities package. Removed the objects package.
author KarstenBock@gmx.net
date Sun, 09 Oct 2011 21:02:48 +0200
parents bb29d81d7ce6
children 86656563555e
files entities/action.py gamescenecontroller.py gui/containergui_base.py gui/hud.py gui/inventorygui.py inventory.py objects/__init__.py objects/action.py
diffstat 8 files changed, 603 insertions(+), 620 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/entities/action.py	Sun Oct 09 21:02:48 2011 +0200
@@ -0,0 +1,598 @@
+#   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
+    
+    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
+                
+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
+        npc_coordinates = self.npc.fifeagent.behaviour.getLocation().\
+                        getLayerCoordinates()
+        pc_coordinates = player_char.behaviour.agent.\
+                            getLocation().getLayerCoordinates()
+        
+        distance_squared = (npc_coordinates.x - pc_coordinates.x) *\
+                           (npc_coordinates.x - pc_coordinates.x) +\
+                           (npc_coordinates.y - pc_coordinates.y) *\
+                           (npc_coordinates.y - pc_coordinates.y)
+        
+        # If we are too far away, we approach the NPC again
+        if distance_squared > 2:
+            player_char.behaviour.approach(
+                [npc_coordinates.x, npc_coordinates.y],
+                        TalkAction(self.controller, 
+                                   self.npc, 
+                                   self.commands
+                                   )
+            )        
+        else:
+            player_char.behaviour.agent.act(
+                '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 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()
+
+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,
+           }
--- a/gamescenecontroller.py	Sun Oct 09 20:54:03 2011 +0200
+++ b/gamescenecontroller.py	Sun Oct 09 21:02:48 2011 +0200
@@ -28,7 +28,7 @@
 from controllerbase import ControllerBase
 from parpg.gui.hud import Hud
 from parpg.gui import drag_drop_data as data_drag
-from objects.action import (ChangeMapAction, ExamineAction, TalkAction,
+from entities.action import (ChangeMapAction, ExamineAction, TalkAction,
                             OpenAction, CloseAction, UnlockAction, LockAction, 
                             PickUpAction, DropItemAction, 
                             ExamineContentsAction,
--- a/gui/containergui_base.py	Sun Oct 09 20:54:03 2011 +0200
+++ b/gui/containergui_base.py	Sun Oct 09 21:02:48 2011 +0200
@@ -18,7 +18,7 @@
 
 from parpg import vfs
 from parpg.gui import drag_drop_data as data_drag
-from parpg.objects.action import ACTIONS
+from parpg.entities.action import ACTIONS
 from parpg.entities import General
 
 class ContainerGUIBase(object):
@@ -142,7 +142,7 @@
     def executeMenuItem(self, action):
         """Executes the items action
         @param action: The action to run
-        @type action: Class derived from parpg.objects.action.Action
+        @type action: Class derived from parpg.entities.action.Action
         """
         action.execute()
     
--- a/gui/hud.py	Sun Oct 09 20:54:03 2011 +0200
+++ b/gui/hud.py	Sun Oct 09 21:02:48 2011 +0200
@@ -28,7 +28,7 @@
 from parpg.gui import drag_drop_data as data_drag
 from parpg.gui.inventorygui import CharacterGUI
 from actionsbox import ActionsBox
-from parpg.objects.action import DropItemAction
+from parpg.entities.action import DropItemAction
 from parpg.components import container
 
 logger = logging.getLogger('hud')
--- a/gui/inventorygui.py	Sun Oct 09 20:54:03 2011 +0200
+++ b/gui/inventorygui.py	Sun Oct 09 21:02:48 2011 +0200
@@ -21,7 +21,7 @@
 
 from parpg.gui import drag_drop_data as data_drag
 from parpg.gui.containergui_base import ContainerGUIBase
-from parpg.objects.action import ACTIONS
+from parpg.entities.action import ACTIONS
 from parpg.components import equip, equipable, container
 from parpg.entities import General
 
--- a/inventory.py	Sun Oct 09 20:54:03 2011 +0200
+++ b/inventory.py	Sun Oct 09 21:02:48 2011 +0200
@@ -13,9 +13,6 @@
 # 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.objects.base import Container
-#from parpg.objects.composed import SingleItemContainer as Slot
-
 import copy
 
 # TODO: many missing function definitions in this code
--- a/objects/__init__.py	Sun Oct 09 20:54:03 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +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/>.
--- a/objects/action.py	Sun Oct 09 20:54:03 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,598 +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
-    
-    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
-                
-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
-        npc_coordinates = self.npc.fifeagent.behaviour.getLocation().\
-                        getLayerCoordinates()
-        pc_coordinates = player_char.behaviour.agent.\
-                            getLocation().getLayerCoordinates()
-        
-        distance_squared = (npc_coordinates.x - pc_coordinates.x) *\
-                           (npc_coordinates.x - pc_coordinates.x) +\
-                           (npc_coordinates.y - pc_coordinates.y) *\
-                           (npc_coordinates.y - pc_coordinates.y)
-        
-        # If we are too far away, we approach the NPC again
-        if distance_squared > 2:
-            player_char.behaviour.approach(
-                [npc_coordinates.x, npc_coordinates.y],
-                        TalkAction(self.controller, 
-                                   self.npc, 
-                                   self.commands
-                                   )
-            )        
-        else:
-            player_char.behaviour.agent.act(
-                '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 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()
-
-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,
-           }