view inventory.py @ 1:4912a6f97c52

Various improvements to the build process including support for self-contained builds. * Note that despite all of these changes PARPG still does not run because asset paths are not standardized, * Modified the SCons script so that by default running `scons` with no arguments creates a self-contained "build" under a build subdirectory to make in-source testing easier. To install PARPG, use `scons install` instead. * Got rid of the binary launcher and replaced it with a shell script for unix and a batch script for Windows (batch script is untested). The binary turned out to be too much trouble to maintain. * Modified the parpg.settings module and parpg.main entry script so that PARPG searches through several default search paths for configuration file(s). PARPG thus no longer crashes if it can't find a configuration file in any particular search path, but will crash it if can't find any configuration files. * Paths supplied to parpg.main are now appended as search paths for the configuration file(s). * Changed the default configuration file name to "parpg.cfg" to simplify searches. * Created the site_scons directory tree where SCons extensions and tools should be placed. * Created a new SCons builder, CopyRecurse, which can copy only certain files and folders from a directory tree using filters (files and folders that start with a leading dot "." e.g. ".svn" are ignored by default). * Added the CPython SCons tool (stands for Compile-Python - I didn't name it!), which provides the InstallPython builder for pre-compiling python sources before they are installed. However, it is currently broken and only installs the python sources.
author M. George Hansen <technopolitica@gmail.com>
date Tue, 31 May 2011 02:46:20 -0700
parents 7a89ea5404b1
children c76f03c290f6
line wrap: on
line source

# 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.objects.base import Container
from parpg.objects.composed import SingleItemContainer as Slot

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