Advertisement

Creating a simple inventory management system...

Started by December 04, 2017 02:19 AM
1 comment, last by Shaarigan 7 years, 2 months ago

https://gist.github.com/anonymous/cbff9fc74258450eb27d50db6aa8ce03

I'm trying to write code to manage an inventory in a simple way. 

This is the first code I've written to do this.

I'm having a bit of trouble understanding certain things. For context, this is intended to be a text adventure.

I have an Item class, and Weapons + First Aid subclasses. If I want to instantiate a weapon, I'll call Item sword = new Weapon("Sword") -- the Item class, as you'll see in my code, requires a name when it is instantiated.

If I want to find that Item in a room I'll pass "Sword" through to DeleteItemFromRoom(string item) and check the item string (containing "Sword") against the "name" property of the Item class to see if it exists.

I don't know if I'm doing it right, or if I should create a global manager, or if instead of creating new items for each room I had a table of pre-defined items and identified them by unique keys... I don't know how to do that though. So I was hoping for some advice or a nudge in the right direction. I want my code to be clean but I still want efficiency

When you play a board game like "munchkin" for example, you will have a pile of item cards in stock, in each players hand and maybe in a room. Those item cards are physically unique and drawn from the pile, added to a players inventory and finally discarded to a pile.

Big RPGs do "in a very very simplified way" the same, A designer places an item in the game, it gets certain unique ID that in the past sometimes caused trouble to identify those items and make lookups (has a palyer taken the item then remove it from the initial level state to get the level back to its 'saved' state, place it in the world at certain location if a player dropped it, place it in inventory of NPC xy if he sold/gave it to that NPC ...) so what I would do for your simple case is to generate an item ID for each item in each 'room' or level starting by some bytes to identify the place the item cames from, the item itself and maybe some other information.

An ID could then look like this


UInt64 CreateId(UInt16 location, UInt16 itemClass, UInt32 flags)
{
     return ((location << 62) | (itemClass << 60) | flags);
}

I've used the location as the left most 2 bytes followed by 2 bytes for an item class that may be your sword, bow, dagger, whatever as pattern and added additional 4 bytes as state bits. Those state bits may be used in your pattern for example


...
class Sword : Item
{
    //inherited from parent class
    public UInt64 Id
    { 
       get;
       private set;
    }

    public bool IsLongSword
    {
        get { return (Id & 0x1);}
    }
    public bool IsShortSword
    {
        get { return (Id & 0x2);}
    }

    public bool IsRusty
    {
        get { return (Id & 0x4);}
    }

    public bool IsEnchanted
    {
        get { return (Id & 0x8);}
    }
}

...
Item[] item = Room.GetItems(ItemClasses.Sword);
...
  
class Room
{
   //item id <> count in the room
   Dictionary<UInt64, UInt32> items = new Dictionary<UInt64, UInt32>();
   
   GetItems(ItemClass targetItemClass)
   {
      List<Item> result = new List<Item>();
      foreach(UInt64 id in items)
      {
         // Bitmask to select the parts of the id, Room Id 2 Byte, Item Class 2 Byte, Flags 4 Byte
         //                        |RID| IC|Flags   |
         UInt16 itemClass = (id & 0x0000FFFF00000000);
         if((ItemClass)itemClass == targetItemClass)
            result.Add(new Item(id));
      }
      return result.ToArray();
   }
}

So you could always identify your items by its id, its class and parent room also, usefull when dropping an item and for stacking (you need to increase count by id, should not be too difficult in your kind of game).

To identify your items by certain name is risky because you could misspell the name for failure and will never get the right item so you need to debug the code, also strings are wasting memory and using a 2 byte enum is much more memory friendly here. Big games do this too by hashing certain string-names to a 4 byte integer value for example. Integers are also more hash-collection friendly (as they are just integers you will not waste time for a hashing function to covnert them).

Using hash-containers like Dictionary or HashTable you will safe a lot of lookup time for targeting single Ids (while seeking for all items of certain type is still an O(n) operation)

This topic is closed to new replies.

Advertisement