Interacting with elements in a given room in a text based RPG

So I'm writing a text based RPG using OOP in C++ for a University project. I've designed a class for dealing with the user being in a generic room and taking the relevant input to say, talk to a specific NPC contained in that room. The get_menu_info() function outputs a string of choices, numbered 0 to leave the area, and all other numerical choices in this case would be to talk to NPCs, which are contained in the class for the specific area. I am testing these features with a derived area class, a village in this case.

The village function available_interactions_for_area takes 3 arguments, an integer, an area (base class of village) and a character(base class of player).

In the code below, it is the available_interactions_for_area function that is skipped over, restarting the do - while loop without interacting with anything in the room.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//file = inputoutput.cpp
int inputoutputhandler::interact_with_area(player& p) {
	
	const area a = p.get_current_area();
	cout << a.get_description() <<"\n"<<endl;

	bool still_in_area(true);
	do {
		cout << a.get_menu_info() << endl;

		bool check = false;
		int answer;
		int b = a.get_number_of_room_options();
		while (!check)
		{
			check = true;

			cin >> answer;

			if (cin.fail()||answer>b)
			{
				cin.clear();
				cin.ignore();
				cout << "Please enter one of the given options" << endl;
				check = false;
			}

		}
		
			if (answer == 0) { still_in_area = false; }
			else {
				
				//this function doesn't work, and is skipped over
				a.available_interactions_for_area(answer, a, p); 
			}

		
	} while (still_in_area);

	return 0;
}


I'm not sure if it's needed, but I will post the function skipped in question also below, just know the talk_to function is an overloaded function from the charcter class and has had no issues in simpler tests. I have outputted a string at the top of the function which does not output when I run the program suggesting to me the function doesn't even initiate.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void village::available_interactions_for_area(int i, const area &a, character &p)const {
	//checking this function starts

	cout << "checking user is inside available interaction function"<<endl;
	switch (i) {
	case 1:	
		p.talk_to(p, a.getNPC(0));
		break;
	case 2:
		cout << "another npc would go here but keeping things simple for testing" << endl;

		break;
	default:
		p.talk_to(p, a.getNPC(i-1));

	}
};



Any suggestions would be greatly appreciated, cheers.
Last edited on
[edited]
Last edited on
I think I see the problem. In line 4, you declare a const area object and assign it to (what I assume is) a villager object. When doing this in an inheritance heirarchy, you encounter slicing. In order to fix this, you have to make "a" a reference:

 
const area& a = p.get_current_area();


When available_interactions_for_area is called on an area REFERENCE, then the run-time type is considered and the proper village::available_interactions_for_area is called via its vtable entry. However, if it is just a base class object area, then "area" knows nothing about its derived types and all information about the village class is lost, therefore it calls area::available_interactions_for_area.

By the way, unless area has some specific functionality, you should probably make it a purely abstract base class.
Last edited on
It will output test text inside the else{} brackets already, have already tried a test output there, it's the actual function that's being skipped hence why the check output is inside, was wondering why it's being skipped and it's not even processing the initial line of test text inside the aformentioned function.
Please read the second comment I posted above
I have a feeling it's something to do with the arguments of the function or the initialisation of answer maybe, because this test version of the same function relying on the same framework with no external functions called also doesn't output the message it should

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void village::available_interactions_for_area(int i, const area &a, character &p)const {
	//checking this function starts

	cout << "checking user is inside available interaction function"<<endl;
	switch (i) {
	case 1:	
		cout << "Talk to first npc" << endl;
		//p.talk_to(p, a.getNPC(0));
		break;
	case 2:
		cout << "another npc would go here but keeping things simple for testing" << endl;

		break;
	default:
		//p.talk_to(p, a.getNPC(i-1));
		break;

	}
};
Please read the second comment I posted above. I gave you the solution.
Well-spotted, toasty.
Ah sorry toaster hadn't refreshed the page before replying to the first answer. I'll try that now.
No problem. Let me know if you have any further questions.
Okay so you are correct it was calling the parent function as i put a test output in the area cpp file to check, but making the adjustment you suggested didn't resolve the issue. The problem with making it an abstract base class is I keep getting the error message that I cannot instantiate the abstract class 'area' so made it non virtual as a quick fix as I am quite new to programming
Oh no wait, I just made the member functions take & of say, area in the header files and it worked!! Thanks so much mate
The reason you are getting that error is because you tried to make an object of an abstract base class. Now that you have made the area object a reference, you won't get that error anymore.

It's actually worse to make it a non abstract base class because then you run into confusing cases like this where the base class method is being called even though you expect the derived class method to be called, and worse, you implemented the base class version with an empty function {}, so you logically think that the compiler skipped over your function call when in reality it is actually calling the empty base class version.

Just make sure you don't make any area objects (only references and pointers) and you won't receive any errors with an abstract base class. And make sure to mark this question as "Solved" if you don't have any other questions.
Last edited on
Topic archived. No new replies allowed.