This article was originally written for Darren Hebden's RLNews
An Inventory tracks Items in Storage. Items are anything you deem
trackable: gloves, clubs, food, coins, flowers. Storage is anything
defined as able to hold items: chests, sacks, hands, buildings.
A basic Inventory does not care about extraneous fluff, such as
container limitations. Keeping inventory implementation basic enables
code reuse as discussed later.
Throughout this paper, psuedo code is used to model examples. The
examples use the following sample item definition:
define Item:
variable Name
Tracking items
There are two basic ways to track items. First is with a simple list,
rather like writing a list of groceries. Lists usually are FIFO (First
in First out) or LIFO (Last in First out). Other ways may exist. Indeed
in some languages, there are very exotic forms of lists. A trouble with
lists is the retrieval of information from the middle of the list. The
list is examined from either end until the information is located.
Our example simple list:
list define Inventory
Second is through a more complex scheme wherein more than the item is
tracked. Also tracked is information about the item. This is so items
may be grouped. Grouping has its pro's and con's like anything else.
Use of grouping, for example, allows easier display of items (in my own
opinion of course). In a way, grouping is a more esoteric list form,
using such things as dictionaries, maps and other terms.
In this example, the items are tracked by their name. Example:
list define Inventory:
list define itemNames
keyedList define qtys
Add items
What use is an Inventory if you are not able to add items to it? Thus,
the first function we define is the add() function.
In basic form, add() only wants to place the passed item to the list:
List define Inventory:
define add(item):
insert item
With the complex form, add() is more detailed. Questions are raised:
is the item already in inventory - this might affect or tracking
feature-? Did I/you make an adjustment to the tracking feature if
necessary? Note how this is done in the example:
list define Inventory:
list define itemNames
keyedList define qtys
define add(item):
if item is in me.itemNames #do I exist?
then me.qtys.key(item.name) = +1
if item is not in me.itemNames #I don't exist
then me.qtys.key.add(item.name)
me.itemNames.add(item.name)
me.qtys.key(item.name) = +1
Remove items
The remove() function is really the opposite of add(). Find the item
passed and remove it from the list. Let's examin it with our two
pseudo codes.
Of course, this example doesn't take into consideration language
dependent behavior (C - did you fix your pointers?). Thus the
abstraction is the same for add():
List define Inventory:
define remove(item):
delete item
Here, as in the complex add() function, more work needs accomplished.
We not only find the item, but we make certain our tracking feature
is adjusted accordingly.
list define Inventory:
list define itemNames
keyedList define qtys
define remove(item):
if item is in me.itemNames
then me.qtys.key(item.name) = -1
if me.qtys.key(item.name) == 0
then me.qtys.delete(item.name)
if item is not in me.itemNames
then error
At the completion, our example would show the proper quantity for the
item. Plus, if we have no more item in inventory, no quantity or
listing will exist.
Display items (opt.)
This is listed as optional, because you may not code Inventory display
as part of your Inventory. It may be in your UI code. However, during
testing, having a simple Inventory Display feature is very useful.
Like always, the simplest way is the list method. Merely iterate the
list, printing each item:
List define Inventory:
define display():
For each item in Inventory:
print item.name
Because of our tracking feature, we need print item and qty. Otherwise
uncertainty will exist. The only added feature of the complex over
simple is the header printed "Item Qty".
List define Inventory:
define display():
print "Item Qty"
for each item in me.itemNames:
print item, me.qtys.key(item.name)
Possible benefits
For developers using OO style languages (C++, SmallTalk, Java, etc),
having a simple Inventory Object lets you easily include it in other
areas of the game. Containers (combinations of Items and Inventory),
Buildings (Structure and Inventory), and more can be made. Of course
non-OO languages(C, Pascal, Basic) can use Inventory as functions in
other parts of the game. The point is: once you define what a basic
inventory will be in your game, find how to use it in more areas.
An Example
Here is an example inventory, using the Python language. I find Python
to be a grat language for prototyping. It is easy to spot errors, fix
them, etc. Then you may easily recode in any other language.
The Item Object -
class Item:
def __init__(self, name): #object constructor
self.name = name
The Inventory Object -
class Inventory:
def __init__(self):
self. NameList = [] #a list of item names
self.qtys = {} #a dictionary of item quantities
self.contents = [] #a list of actual items
def add(self, itemList = []):
for item in itemList:
#Check item is self
if item is self:
print 'Cannot store', item,' in itself!'
if item in self.contents:
print 'You already have this item!'
else:
#Check if item is in nameList
if item.name in self.NameList:
#merely insert
self.qtys[item.name] = self.qtys[item.name] + 1
#otherwise add to nameList
else:
self.qtys[item.name] = 1
self.nameList.append(item.name)
self.contents.append(item)
def remove(self, item):
#does item exist?
If item not in self.contents:
print item.name, 'is not in your inventory'
else:
self.qtys[item.name] = self.qtys[item.name] - 1
if self.qtys[item.name] == 0:
del self.qtys[item.name]
self.NameList.remove(item.name)
self.contents.remove(item)
def display(self):
#let's show everything!
Print "Item\tQty"
for item in self.NameList:
print item,"\t", self.qtys[item]
More Info
For information about Python, visit: http://www.python.org
Please send all comments, queries, and error notifications to the author.
Written by: Ken Power email: uncle_wiggly@bigfoot.com
Version: 1.0 Date: Oct. 25, 1999
|