9 replies [Last post]
Posts: 100

I decided to start over with the basics and have been playing with this: http://www.penguinprogrammer.co.uk/rpg-tutorial/introduction/

It's a strictly text-based RPG engine in C++ with a tutorial explaining it all. I'm using Linux Mint and Code::Blocks. It uses Jsonbox for the game description files. The only change I've made is that I'm calling 'armor' as 'clothing' and 'weapon' as 'tool', and filled out more json information.

I downloaded the source from that site, and after finally interpreting how to get it all together and set up the compiler to use the version of C++ for the syntax the thing was written in, I finally got it to compile. (One other note: I opted to include the json source with the engine code instead of installing as a library)

When I run/debug it, it throws a segmentation fault. As far as I can figure, I have a bad pointer somewhere.

More specifically, looking through the debugger, it appears the pointer issue is somewhere in:

a) Two lines in Value.cpp (in Jsonbox, which I'm assuming are correct as this is a utility not modified or generated by the code in question)

b) Two lines in 'Inventory.cpp'

c) Two lines in Area.cpp

d) one line Entity_Manager.cpp

e) one line in Main.cpp

I'm not sure at all, but I'm wondering if this line in Inventory.cpp is the culprit?

std::list<std::pair<Item*, int>> items;

It was the single line the compiler had the most trouble with, and while it compiled, it still complains that 'items' does not have a type, or bad syntax. The only way I could get this line to compile (the whole thing at that) was to use the "use c++0x language standard" option.

(partial code for Inventory.cpp)

class Item;
class Tool;
class Clothing;
 
class Inventory
{
	private:
 
	// We use a similar method here to in EntityManager where we store
	// a list of base pointers. We use a list and not a vector as inventories
	// are highly mutable. This way they can also be efficiently sorted.
	// The first element of the pair stores a pointer to the item in
	// the EntityManager, and the second element stores the quantity of the item
 
	std::list<std::pair<Item*, int>> items;
 
	// Given the Json value v which contains a list of items, tools, or clothing of type T
	// load the Ts into the storage list (either items, tools, or clothing)
	template <typename T>
	void load(JsonBox::Value& v, EntityManager* mgr);
 
	// Return a JSON representation of all the items of the type T
	template <typename T>
	JsonBox::Array jsonArray();

Am I barking up the wrong tree? Any help appriciated. I'm using this to both learn more about c++ and class structure/syntax (which is cryptic for me coming from C), and to learn more how a game engine is laid out in simple form, as Netgore was far too big a pond for me to get lost in, especially with no .net experience.

Posts: 123

Can you post your entire output when your trying to compile?

from what I can see the only reason you could possibly be getting an error is if your not including the list or pair libraries on that line. since int is a native type, and you defined a temporary class for item above, your shouldnt need to include its header file... also if it was an incomplete type it shouldnt compile, however I am curious as to how your making and adding the items to that list.

also it will be easier to get ahold of me on skype which is iixshinxii

Posts: 100

I will see if I can get skype set up, haven't used it yet. Thanks for your reply, sparked some ideas to check, but Im still no farther along.

The program compiles. When it is run, it pops a 'SIGSEGV' segmentation fault, a memory allocation error (or so I am lead to believe. I looked it up and the most common cause that makes sense is a pointer error, but that is an assumption)

I 'rebuilt' it and here is the build log:

||=== Build: Debug in ptq03 (compiler: GNU GCC Compiler) ===|
/home/troll6/Desktop/ptq03/src/dialogue.hpp||In member function ‘int Dialogue::activate()’:|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|32|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|42|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp||In member function ‘int Dialogue::activate()’:|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|32|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|42|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp||In member function ‘int Dialogue::activate()’:|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|32|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|42|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp||In member function ‘int Dialogue::activate()’:|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|32|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|42|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp||In member function ‘int Dialogue::activate()’:|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|32|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|42|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/main.cpp||In function ‘int main()’:|
/home/troll6/Desktop/ptq03/src/main.cpp|73|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/main.cpp|77|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/main.cpp|123|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/main.cpp|127|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp||In member function ‘int Dialogue::activate()’:|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|32|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
/home/troll6/Desktop/ptq03/src/dialogue.hpp|42|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
||=== Build finished: 0 error(s), 16 warning(s) (0 minute(s), 43 second(s)) ===|

When I run a debug execute, here's the stack:

#0 0x41f8ac JsonBox::Value::tryGetString(this=0x0, defaultValue=...) (/home/troll6/Desktop/ptq03/src/JsonBox/Value.cpp:475)
#1 0x41f899 JsonBox::Value::getString(this=0x0) (/home/troll6/Desktop/ptq03/src/JsonBox/Value.cpp:471)
#2 0x419452 Inventory::load(this=0x7fffffffe200, v=..., mgr=0x63fa80 ) (/home/troll6/Desktop/ptq03/src/inventory.cpp:18)
#3 0x41874c Inventory::Inventory(this=0x7fffffffe200, v=..., mgr=0x63fa80 ) (/home/troll6/Desktop/ptq03/src/inventory.cpp:170)
#4 0x404446 Area::load(this=0x6a05f0, v=..., mgr=0x63fa80 ) (/home/troll6/Desktop/ptq03/src/area.cpp:42)
#5 0x4041df Area::Area(this=0x6a05f0, id=..., v=..., mgr=0x63fa80 ) (/home/troll6/Desktop/ptq03/src/area.cpp:26)
#6 0x416754 EntityManager::loadJson(this=0x63fa80 , filename=...) (/home/troll6/Desktop/ptq03/src/entity_manager.cpp:22)
#7 0x425b0f main() (/home/troll6/Desktop/ptq03/src/main.cpp:43)

As far as I can figure, here's my interpretation of this...

main.cpp line 43:

	entityManager.loadJson<Area>("areas.json");

loading areas

entity_manager.cpp line 22:

template <class T>
void EntityManager::loadJson(std::string filename)
{
	JsonBox::Value v;
	v.loadFromFile(filename);
 
	JsonBox::Object o = v.getObject();
	for(auto entity : o)
	{
		std::string key = entity.first;
		this->data[key] = dynamic_cast<Entity*>(new T(key, entity.second, this));  // line 22

loading a string from json file

area.cpp line 26:
Area::Area(std::string id, JsonBox::Value& v, EntityManager* mgr) : Entity(id)
{
this->load(v, mgr); // line 26
}
loading values from json file

area.cpp line 42

void Area::load(JsonBox::Value& v, EntityManager* mgr)
{
	JsonBox::Object o = v.getObject();
 
	// Build the dialogue
	// This is an optional parameter because it will not be saved
	// when the area is modified
	if(o.find("dialogue") != o.end())
		this->dialogue = Dialogue(o["dialogue"]);
 
	// Build the inventory
		// this might be where we make the random generation of items?
		// Rather, generate based on probability. It might also be handled in the inventory.*pp file(s)
	this->items = Inventory(o["inventory"], mgr); // line 42

getting values from 'inventory'

inventory.cpp line 170

Inventory::Inventory(JsonBox::Value& v, EntityManager* mgr)
{
	JsonBox::Object o = v.getObject();
	load<Item>(o["items"], mgr); // line 170

getting 'items'

inventory.cpp line 18

template <typename T>
void Inventory::load(JsonBox::Value& v, EntityManager* mgr)
{
	for(auto item : v.getArray())
	{
		std::string itemId = item.getArray()[0].getString();  // line 18

getting string from file (but I don't see how it does this)

value.cpp line 471

	const std::string &Value::getString() const {
		return tryGetString(EMPTY_STRING);  // line 471
	}

getting string

value.cpp line 475

const std::string &Value::tryGetString(const std::string &defaultValue) const {
		return (type == STRING) ? (*data.stringValue) : (defaultValue);  // line 475
	}

trying to get the string... fails here

as to the json entries it *should* be looking at...

start area in Areas.json:

	"area_cage_01_start": {
		"dialogue": {
			"description": "You are in your cage in the Testing-Place.",
			"choices": []
		},
		"doors": ["door_cage_01_biolab_cage"],
		"inventory": {
			"items": [
				["item_gold_lump", 5]
			],
			"tools": [],
			"clothing": [
				["clothing_silk_shirt", 1]
			]
		},
		"creatures": []
	},

here's the only item in that area in 'Items.json':

	"item_gold_lump": {
		"name": "Golden Lump",
		"description": "A small lump of shiny yellow metal"
	},

All other sections that read json files work good, 'areas' is the last section to load when starting the game. The other sections use the same json/value.cpp, and I quadruple checked the original example game against mine to make sure the spacing and syntax was identical. The uneducated feeling I get is that I have something going on in one of the two json files that's out of the bounds for the thing to work (like using periods instead of newline or something... is there a string code for a "."?) or something else that is seemingly unrelated I'm missing.

BTW, I don't have any file hosting options at the moment to put the code up at this time.

Posts: 123

From what it looks like is you have a this with a memory address 0x0 which is null...

When I get home from work I'll download their source and see if I ca reproduce what your getting by doing what you said you did.

Posts: 123

Alright after a second look through your post it appears that you are using an unsafe method, inventory.cpp line 18, you are getting an array and getting the first index and then calling getstring on it depending of the implementation of getarray, it could be returning an address of a nullptr... if the definition is like:

Note: this is pseudo code...

Template <typename t>
T& getarray (){
return *ptrArray;
}

if in this instance ptrArray is pointing at null(since maybe the items didn't load correctly.) You would instantly be calling a function on a null item and that can cause the segmentation fault you are receiving.

Posts: 123

Nvm I realised the answer to this question - editted

Posts: 100

I compiled the example game from the site, and it seems to work fine. I'm going back through my json files to check and make sure I didn't do something wrong there (for the upteenth time), then compare my items.cpp with the example. I'm still at a loss for what I've messed up. The learning lesson is getting foggy.

Anyone ever worked with Json files? It would be nice if there was a easier way to do data entry on them for less chance of syntax error.

update:

If a string is parsed that is to be displayed on a screen, and it is longer than what can be displayed, but does not have any "\n", could this cause this issue? I read up on json formats and added a format viewer, and the only thing I can see different between my Items.json and the one that came with the demo is that I have item descriptions longer than one line of screen text without any 'newline' commands (was going to wait on formatting until after I saw what it looked like in play).

Posts: 123

If you hit enter in that file to go to the next line then yes that is possibly the error however if you did not and it just word wrapped then it is not likely, when reading in a file you so not out \n in the file as when it reads it in it will read it as \n and not as the escape character sequence to verify that I would need to see how they are parsing the json file.

Every time you hit enter depending on The text editr in the binary of the file it adds the binary value of either \r\n or \n most linux text editor's will only insert a \n. That is not something you will need to write in the text file itself.

Easy test, retype your description without hitting enter and see what happens

Posts: 123

Also in regard to your question what string would be to large to display to the screen? I use things like printf ("location: %f, %f, %f\t elevation offset was: %f\t new location is: %f, %f, %f", pos.x, pos.y, pos.z, elevationOffset, newpos.x, newpos.y, newpos.z); all the time, the only way I could see there being an issue with a strong length is if you are using their method to display a strong and they implemented a hard limit it or a hard limit on the description length. I've seen four print out enormously long strings.

Posts: 123

I'll be on That Skype I listed earlier tomorrow after 4 pm est.