Hello

I'm making a dungeons and dragons and i need something to contain all inventoryitems like pieces of equipment, potions,...
How can I put them all in one array or vector?

Thanks,

Jasper

Recommended Answers

All 19 Replies

Would it not work if you just had 2 separate vectors? One of type Potion and another of type Equipment?

vector<Potion> p;
vector<Equipment> e;

Would it not work if you just had 2 separate vectors? One of type Potion and another of type Equipment?

vector<Potion> p;
vector<Equipment> e;

I've also thought of that but than I would have to keep different vector of the same size for every type of item. And how would I know if the inventory is full. I think it's to memory consuming, there must be a better solution.
But thanks, if I don't come up with anything, I'll do it like this.

Jasper

Member Avatar for Mouche

Perhaps you could have a bag class. In this bag class, you could have vectors of all the types of items the bag could hold (which looks like two or three in your case?). Then you could write methods to add to the bag and overload them -- for example, you'd have add() for a potion input, an equipment input, a weapon input, and so on. In order to get the size of the bag, you could just add up the sizes of the vectors in the bag.

Just an idea... it seems helpful if your game is going to get rather large. If it's going to be simple, just having separate vectors for your items may suffice.

To know whether the inventory is full or not, you'd need to check the sum of the sizes of the vectors against a certain max inventory number. With the bag class idea, you could return an error code such as -1 if the bag is full and then deal with it how you want.

Why do you need to have the same size for each vector and why do you think using two vectors is memory consuming?

Just did some researching, I was wrong. Sounds good. Thanks!
I'm still learning C++ and before I used Scheme (lisp derrivate) and there vectors are fixed size and the size has to be known upon creation. Resizing would mean a data-copy which is pretty expensive.
I'll give it a shot right now and see what it will be.

Member Avatar for Mouche

Ah okay. Resizing via data-copy is much less efficient than using a variable-size structure. In C++, arrays are fixed-size, and vectors and lists are variable-size array-type structures.

An idea would be to create a 'holder' class called 'Inventory' which would tie in the classes Potion and Equipment then have a vector of type 'Inventory' so for example, something like...

class Inventory
{
public:
Inventory(Potion thePotion, Equipment theEquipment) // inline ctor
{
      p = thePotion;
      e = theEquipment;
}

// functional prototypes / get/setter functions etc 
protected:
Potion p;
Equipment e;
};

vector<Inventory> vI;

I think this could be an option/something to think about.

Member Avatar for Mouche

It'd be possible to make that work, pac-man, but why would you want a list of items that hold a potion, an equipment or both? If you put a potion and equipment in the same item, the vector size would not give you the Inventory size. If you only use one item per Inventory item, you'd need a flag designating which item it is.

It'd be possible to make that work, pac-man, but why would you want a list of items that hold a potion, an equipment or both? If you put a potion and equipment in the same item, the vector size would not give you the Inventory size. If you only use one item per Inventory item, you'd need a flag designating which item it is.

hi there, I just thought of the idea in response to the OP's "How can I put them all in one array or vector?"

On that point you've made I guess you could actually have the Inventory class holding a vector<Potion> and vector<Equipment> instead of a single Potion and Equipment object.

Member Avatar for Mouche

Then you would only need one inventory object, not a vector of inventory objects and that's exactly what I was proposing before. Then if you write methods for the class, you only have to interact with it using your written methods and don't have to deal with the vectors directly.

Why not just have all items inherit from an 'Item' base class and make a vector of Items? I.E., a helmet is a piece of armor, which is a piece of equipment, which is an item. A healing potion is a potion, which is an item. A +3 vorpal short sword is a sword, which is a weapon, which is equipment, which is an item.

commented: That a step in the right direction +11

Then you would only need one inventory object, not a vector of inventory objects and that's exactly what I was proposing before. Then if you write methods for the class, you only have to interact with it using your written methods and don't have to deal with the vectors directly.

Makes sense.

I need a little help, I've made a class Item which contains things like the name, type, price and weight.
I've made equipment and potion subclasses of item. These add a few extra values like damage for a weapon and the effect of the potion.
But how can I access the type of the item. The variable is private but I've made an accessor. When I try to define a function with the same name for the piece of equipment it says

Equipment.cpp:13: error: passing ‘const CEquipment’ as ‘this’ argument of ‘int CEquipment::GetWeight()’ discards qualifiers

This is some of my code:

class CEquipment : public CItem{
public:
	CEquipment(const char t='N', std::string n = "NULL", int b = 0, const dicethrow & d = dicethrow(0,1), int p = 0, int w = 0)
	:item_(new CItem(t,n,p,w)),bonus_(b),dammage_(d){};
	CEquipment(const std::string &s):bonus_(0),dammage_(dicethrow(0,1)){load(s);};
	
	const char GetType(){return item_.GetType();};
	std::string GetName(){return item_->GetName();};
	int GetBonus(){return bonus_;};
	dicethrow & GetDammage(){return dammage_;};
	int GetPrice(){return item_->GetPrice();};
	int GetWeight(){return item_->GetWeight();};

	friend std::ostream& operator << (std::ostream &, const CEquipment &);
	friend std::istream& operator >> (std::istream &, CEquipment &);

private:
	CItem* item_;
	int bonus_;
	dicethrow dammage_;

	void load(const std::string&);
};
class CItem{
public:
	CItem(const char t='N', std::string n = "NULL", int p = 0, int w = 0):type_(t),name_(n),price_(p),weight_(w){};
	
 	const char GetType(){return type_;};
	std::string GetName(){return name_;};
	int GetPrice(){return price_;};
 	int GetWeight(){return weight_;};

private:
 	char type_;
	std::string name_;
	int price_;
	int weight_;
};

What do I do wrong?
I've tried to make the function virtual.

Thanks,

Jasper

Try changing the private keyword to protected..

Variables declared protected mean that only derived classes of the base class can access them.

Oh and also, the virtual keyword will be required if you want to override the base class' function with the derived class' implementation.

Try changing the private keyword to protected..

Variables declared protected mean that only derived classes of the base class can access them.

Oh and also, the virtual keyword will be required if you want to override the base class' function with the derived class' implementation.

OK, now it compiles but the data is incorrect.
I load the weapons and stuff from a .txt file. It worked fine but I can't seem to be able to change the values from the item. Before it worked perfect.
I can only change the value of a variable in item by using a setter. Can I do it directly like

int p = 5;
price_ = 5;

This code is in a function in equipment for example and price_ is in item.

Try

className->variable = x;

Okay, everything works with the inheritance.
Now I want to create an array of type item so that all the derived classes can fit into it but I always lose the extra data that is specific to that derived class like how much damage a weapon does.
I think I've got to use pointers to the thing I want to add but can't seem to get it working.

class CItemContainer{
	
public:
	CItemContainer(int c):capacity(c){};
	int GetWeight();
	int GetSize();
	bool Full();
	const CItem operator[](const char idx) const;
	CItem operator[](const char idx);
	void Insert(CItem* val){items_.push_back(val);};
	void Remove(); // remove last
	void Remove(const int idx); //remove at idx

	vector<CItem*> items_; // should be private
	private:
	int capacity;
	
};

int
main(){
	CItemContainer a(5);
	
	CPotion* p = new CPotion(); // create new potion with default values
	a.Insert(p); // add potion to the back of the vector
	CPotion p2 = *(a.items_[0]); // error: conversion from ‘CItem’ to non-scalar type ‘CPotion’ requested
	
}

The items_ vector should be private but for now its public to be able to access the data without an accessor.

I'd suggest taking a look at references as opposed to pointers. I personally have found that more people are able to better understand them as opposed to pointers.

CPotion p2 = *(a.items_[0]); // error: conversion from ‘CItem’ to non-scalar type ‘CPotion’ requested

Don't forget you have to cast your item back to a potion. There are better ways to do this than the way I'm going to show you, as I'm still stuck being a hybrid C/C++ programmer.

C:

// if you want a pointer to the object
CPotion *p2 = (CPotion *)a.items[0];

// if you want the actual object 
CPotion p2 = (CPotion)*a.items[0];

C++:

CPotion *p2 = dynamic_cast<CPotion *>(a.items[0]);

I think that's how the C++ version works. I've never actually used it. I'm beginning to think my school didn't have it quite figured out when they taught us C++.

CPotion p2 = *(a.items_[0]); // error: conversion from ‘CItem’ to non-scalar type ‘CPotion’ requested

Don't forget you have to cast your item back to a potion. There are better ways to do this than the way I'm going to show you, as I'm still stuck being a hybrid C/C++ programmer.

C:

// if you want a pointer to the object
CPotion *p2 = (CPotion *)a.items[0];

// if you want the actual object 
CPotion p2 = (CPotion)*a.items[0];

C++:

CPotion *p2 = dynamic_cast<CPotion *>(a.items[0]);

I think that's how the C++ version works. I've never actually used it. I'm beginning to think my school didn't have it quite figured out when they taught us C++.

I just asked some guy who knows everything about c++ and he said just the same. This is how I (he actually) got it to work:

CItem* a[5];
	CPotion p2;
	CEquipment p;
	a[0] = &p;
	a[1] = &p2;
	CEquipment * p3 = (CEquipment *)a[0]; 
	CPotion * p4 = (CPotion *)a[1];

So its the C-way but C++ can run C code so its fine for me.
He also said something about static_cast. But I like it this way (I saw some of his code once and he did it the C-way)

Thanks!

Jasper

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.