Public Group

Combat recursion member function...function HELP

This topic is 4105 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

K, so I have a menu system up that: - directs the user to a function that allows them to create their character, then returns to the main menu. - directs the user to a function that allows them to generate some enemies, then returns to the main menu. - directs the user to a function that allows them to fight the enemies they just generated, one-on-one I have the first two functions up and working, but I don't know what to do for the fight function. I have an idea that I want to implement, here it is: When 2 Characters battle, the player against an enemy, I want some function, either a member function in class Character or a function in my main source, to take a look at the stats of each of the Characters, and then use those stats to determine who strikes first, then have each of the Characters strike 1 time at the other, reducing each of the Characters health by some amount. Then, if both Characters are still alive, I want to call the function again, so they each strike each other 1 more time, reduce the health, and continue this loop until one of the Characters' health <= 0. I was thinking of adding a member function to class Character that would take a parameter of type Character, so calling this function from the player Character would look like: player.versus( enemy1 ). Then this would calculate or do something and return the winner, perhaps. But then I don't know if I should return a pointer to the Character or return the Character itself or what, and then what to do with the information that is returned. I'm lost. How do I do this? Here is my code:
// This is the header file for the Classes
#include <string>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <ctime>
using namespace std;

const string basenames[10] = { "Troll", "Ogre", "Ooze", "Gargoyle", "Dragon", "Orc", "Elemental", "Blood-Elf", "Goblin", "Gremlin" };

void createCharacter();
void generateEnemies();
void fight();

class Character
{
private:
string name;
int health;
int power;
int defense;

public:
Character();
Character( string chname, int hp, int ap, int def );
void setName( string chname );
void setHealth( int hp );
void setPower( int ap );
void setDefense( int def );
string getName();
int getHealth() const;
int getPower() const;
int getDefense() const;
//Character* versus( Character thisCharacter );

};

Character::Character() : name( basenames[ rand() % 10 ] ), health( rand() % 11 + 10 ), power( rand() % 11 + 10 ), defense( rand() % 11 + 10 )
{}

Character::Character( string chname, int hp, int ap, int def ) : health( hp ), power( ap ), defense( def )
{}

void Character::setName( string chname )
{
name = chname;
}

void Character::setHealth( int hp )
{
health = hp;
}

void Character::setPower( int ap )
{
power = ap;
}

void Character::setDefense( int def )
{
defense = def;
}

string Character::getName()
{
return ( name );
}

int Character::getHealth() const
{
return ( health );
}

int Character::getPower() const
{
return ( power );
}

int Character::getDefense() const
{
return ( defense );
}

/*
Character* Character::versus( Character thisCharacter )
{
if( this -> getHealth() > thisCharacter.getHealth() )
return this;
else if( this -> getHealth() < thisCharacter.getHealth() )
return thisCharacter;
else
return this;
}
*/
class ChDatabase
{
private:
vector<Character> database;

public:
ChDatabase();
void eraseFirstCharacter();
void displayAllCharacters();

};

ChDatabase::ChDatabase()
{}

{
database.push_back( thisCharacter );
}

void ChDatabase::eraseFirstCharacter()
{
database.erase( database.begin() );
}

void ChDatabase::displayAllCharacters()
{
if( database.empty() )
cout << "Database empty." << endl;
else
{
for( vector<Character>::iterator iter = database.begin(); iter != database.end(); ++iter )
{
cout << "   Name: " << iter -> getName() << endl;
cout << " Health: " << iter -> getHealth() << endl;
cout << " Attack: " << iter -> getPower() << endl;
cout << "Defense: " << iter -> getDefense() << endl << endl;
}
}

}


#include "classheader.h"

ChDatabase enemyDataBase;
ChDatabase playerDataBase;

bool exitmainloop = false;
bool playercreated = false;
bool enemiescreated = false;

int main()
{
system("CLS");

srand(time(NULL));

do
{
int choice;

system("CLS");
cout << "\tCreate-a-Character!\n\n";
cout << "What would you like to do?\n";
cout << "1 - Create your Character!\n"
<< "2 - Generate some enemies!\n"
<< "3 - FIGHT!\n"
<< "4 - Exit\n"
<< "Selection: ";
cin >> choice;

switch( choice )
{
case 1:
char YorN;
if( playercreated )
{
cout << "\n\tYou already have a character.  Continuing will delete your character.\n"
<< "\tAre you sure you want to continue? ";
cin >> YorN;
if( tolower( YorN ) == 'y' )
{
playerDataBase.eraseFirstCharacter();
createCharacter();
}
else
continue;
}
else
createCharacter();
break;
case 2:
if( !playercreated )
{
cout << "\n\tYou must create your character first!\n";
cin.get();
cin.get();
continue;
}
generateEnemies();
break;
case 3:
if( playercreated && enemiescreated )
fight();
else
{
cout << "\n\tYou need to create your character or generate your enemies!\n";
cin.get();
cin.get();
continue;
}
break;
case 4:
exitmainloop = true;
break;
default:
cout << "Invalid choice.";
break;
}
}while( !exitmainloop );

return 0;
}

void createCharacter()
{

string chname;
char keep;

Character* pplayer;

do
{

pplayer = new Character;

system("CLS");

cout << "\tWelcome to Character Creation!" << endl;
cout << "Here are your stats: " << endl;
cout << " Health: " << pplayer -> getHealth() << endl;
cout << " Attack: " << pplayer -> getPower() << endl;
cout << "Defense: " << pplayer -> getDefense() << endl << endl;
cout << "Would you like to keep these (y/n)? ";
cin >> keep;

if( tolower( keep ) == 'n'  )
{
delete pplayer;
}
}
while( tolower( keep ) == 'n' );

cout << "\nCharacter name: ";
cin >> chname;
pplayer -> setName( chname );

delete pplayer;

system("CLS");

cout << "\tCongratulations! Here is your character: " << endl << endl;
playerDataBase.displayAllCharacters();

playercreated = true;

system("PAUSE");

main();
}

void generateEnemies()
{
system("CLS");

int num;

cout << "\tWelcome to the Enemy Generator!\n\n";
cout << "How many enemies would you like to generate? ";
cin >> num;
cout << endl;

for( int i = 0; i < num; ++i )
{
}

enemyDataBase.displayAllCharacters();

enemiescreated = true;

system("PAUSE");
main();
}

void fight()
{
cout << "Prepare to fight!";
system("PAUSE");
}



Share on other sites
Why do this recursively? Why not just a while loop:

while (player.health > 0 && enemy.health > 0){    //do combat...}

Or:

while (player.InCombat()){    player.GetAction();    ResolveCombat();}

Or something along those lines? Recursion seems a bit unnecessary for something like this...

Share on other sites
Quote:
 Original post by Driv3MeFarWhy do this recursively? Why not just a while loop:while (player.health > 0 && enemy.health > 0){ //do combat...}Or:while (player.InCombat()){ player.GetAction(); ResolveCombat();}Or something along those lines? Recursion seems a bit unnecessary for something like this...

Ha becuase I don't know how to write an algorithm for "// do combat," and this idea popped into my head and I thought it would be interesting to see it done this way.

Share on other sites
Ha alright well I guess any ideas on how to simulate combat would be appreciated. I mean gimme the basics, assume nothing. I have no clue how to do any sort of combat other than making a single comparison between two values and declaring a winner! Hah that doesn't quite work

Share on other sites
Combat is, at the core, just comparisons between numbers [lol]. Since you're characters don't have a "speed" attribute, you could just always make the player go first, or just generate a random number (just a 0 or 1 would suffice) and make the player or enemy go first depending on that.

From there, just compare the player's power to the enemy's defense, and apply damage based on that. I'll leave exactly how to determine how much damage up to you, but you could just do a subtraction and count that as the damage done, or add some randomness to it. Rinse and repeat as needed.

Share on other sites
Quote:
 Original post by Driv3MeFarCombat is, at the core, just comparisons between numbers [lol]. Since you're characters don't have a "speed" attribute, you could just always make the player go first, or just generate a random number (just a 0 or 1 would suffice) and make the player or enemy go first depending on that.From there, just compare the player's power to the enemy's defense, and apply damage based on that. I'll leave exactly how to determine how much damage up to you, but you could just do a subtraction and count that as the damage done, or add some randomness to it. Rinse and repeat as needed.

So should I make a function in my source code or a member function of class Character that would run through these comparisons and declare a winner? Also, I' m having trouble understand how to call a function have the function return an object of class Character ( I think I understand "return this;" ), but I don't understand what I can then do with an object that's been returned from a function.
Just to make sure, could somebody gimme a quick and simple example of using the this pointer. Thanks!

Share on other sites
Lets say you have something like this:

const Character *Character::GetCharacter()
{
return this;
}

int main()
{
Character *character = new Character();
const Character* pointer = character->GetCharacter();

pointer->whatever...
}

Basically, if you have a member function return it's this pointer, you can use that pointer to access any const member function of that instance of that object. The this pointer is just like any other const pointer to an object, the only difference is that every instance of a class has one automatically, and it points to itself.

As for how to structure where combat gets done, that's up to you. I would probably make an "attack" member function in the Character class, or something like that.

Share on other sites
Ok so I tried my hand at a combat function for Character. Here it is:

Character* Character::versus( Character thisCharacter ){	bool InCombat = true;	while( InCombat )	{		if( this->getHealth() > 0 && thisCharacter.getHealth() > 0 )		{			int sp = rand() % 10 + thisCharacter.getSpeed();			int sp2 = rand() % 10 + this->getSpeed();			if( sp2 >= sp )			{				int hp = thisCharacter.getHealth();				int hp2 = this->getHealth();				hp -= ( (this->getPower()) - (thisCharacter.getDefense()) ); 				thisCharacter.setHealth( hp );				if( thisCharacter.getHealth() > 0 )				{					hp2 -= ( (thisCharacter.getPower()) - (this->getDefense()) );					this->setHealth( hp2 );				}				else					InCombat = false;					return this;				continue;			}			else			{				int hp = thisCharacter.getHealth();				int hp2 = this->getHealth();				hp2 -= ( (thisCharacter.getPower()) - (this->getDefense()) );				this->setHealth( hp2 );				if( this->getHealth() > 0 )				{					hp -= ( (this->getPower()) - (thisCharacter.getDefense()) ); 					thisCharacter.setHealth( hp );				}				else					InCombat = false;					return *thisCharacter;				continue;			}		}	}}

This doesn't compile

And here's where I call it:
cout << *( playerDataBase[0].versus( enemyDataBase[0] ) ).getName();

And this doesn't compile either.

Here are my errors, but I don't know how to fix any of this...
Compiling...main.cppc:\documents and settings\nate\my documents\visual studio 2005\projects\aggregate\aggregate\classheader.h(146) : error C2100: illegal indirectionc:\documents and settings\nate\my documents\visual studio 2005\projects\aggregate\aggregate\classheader.h(146) : error C2440: 'return' : cannot convert from 'Character' to 'Character *'        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called.\main.cpp(14) : warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data.\main.cpp(160) : error C2676: binary '[' : 'ChDatabase' does not define this operator or a conversion to a type acceptable to the predefined operator.\main.cpp(160) : error C2228: left of '.versus' must have class/struct/union.\main.cpp(160) : error C2676: binary '[' : 'ChDatabase' does not define this operator or a conversion to a type acceptable to the predefined operator.\main.cpp(160) : error C2228: left of '.getName' must have class/struct/union

Share on other sites
Combat is where you have to start using your imagination.
A text console game is not going to have combat based on quick mouse input and stuff like that, the way Quake does. What you need is a game world where the player can explore and find items/weapons/armor etc.

Things that could make a winner/looser in a text console combat:

Someone said weapon speed earlier. I'm not going to suggest that becouse it doesn't go well with the event driven RPG I'm working on.

1. Weapon damage. If you have a game world where the player can move around and explore different locations and find items/weapons, the damage of the currently equipped weapon will make a difference in combat. The more you explore, the better weapons you will have.

2. Armor. You already have this attribute. The better armor the player has equipped, the less damage he will take from a enemy hit.

3. Health potions. Spending a "turn" on drinking a health potion (If you have any left) should be worth it during a fight. The enemies in the game should also have this possibility. Other things; invisibility potions, weapon oil.

4. Escape. In a RPG like the one I'm working on there should be possible to escape from a fight. Enemies could have this ability as well.

5. Critical hits. This adds some good/bad luck to the fight, and some randomness. Other things; a chance to dodge, evade and parry. Based on skill.

6. Combinations. Items that can be used on your equipment to improve it. If your game has some kind of timer, you can have this effect fade away over time. Like a sword getting dull over time. Or you could pay a weapon smith to sharpen your sword just before you go into the dragons lair...

The list could go on and on.
What you need to make all this happen is a game with some kind of time or event driver. IMO that is what you are looking at right now.
The reason I am making all this fuzz is that I wrote a simple event driven game world some time ago that I thought I would show you.
#include <string>#include <map>#include <iostream>using namespace std; struct Location{	map<string, Location*> exits;		string description;};int main(){	string userCommand;		map<string, Location*> world;		// create locations			world["start"] = new Location;	world["start"]->description = "Start location...\nExits: town";		world["farm"] = new Location;	world["farm"]->description = "Farm...\nExits: town";		world["town"] = new Location;	world["town"]->description = "Town...\nExits: farm";		// setup links between locations	world["start"]->exits["town"] = world["town"];	world["farm"]->exits["town"] = world["town"];	world["town"]->exits["farm"] = world["farm"];	// setup current location	Location* location = world["start"];		while(1)	{						cout << location->description << endl;		getline(cin, userCommand);		if(userCommand == "exit")			break;				map<string, Location*>::iterator lookup = location->exits.find(userCommand);				if(lookup != location->exits.end())			location = lookup->second;		else			cout << "Invalid exit." << endl;	}	// release memory		for(map<string, Location*>::iterator doe = world.begin(); doe != world.end(); ++doe)		delete doe->second;				return 0;}

This little RPG wannabe (I have a version with more flesh on it if your iterrested) has a game loop generating events based on user input, and a game world for the player to explore.

[Edited by - pulpfist on May 22, 2007 9:38:58 AM]

Share on other sites
Quote:
 Original post by pulpfistCombat is where you have to start using your imagination.A text console game is not going to have combat based on quick mouse input and stuff like that, the way Quake does. What you need is a game world where the player can explore and find items/weapons/armor etc.Things that could make a winner/looser in a text console combat:Someone said weapon speed earlier. I'm not going to suggest that becouse it doesn't go well with the event driven RPG I'm working on.1. Weapon damage. If you have a game world where the player can move around and explore different locations and find items/weapons, the damage of the currently equipped weapon will make a difference in combat. The more you explore, the better weapons you will have.2. Armor. You already have this attribute. The better armor the player has equipped, the less damage he will take from a enemy hit.3. Health potions. Spending a "turn" on drinking a health potion (If you have any left) should be worth it during a fight. The enemies in the game should also have this possibility. Other things; invisibility potions, weapon oil.4. Escape. In a RPG like the one I'm working on there should be possible to escape from a fight. Enemies could have this ability as well.5. Critical hits. This adds some good/bad luck to the fight, and some randomness. Other things; a chance to dodge, evade and parry. Based on skill.6. Combinations. Items that can be used on your equipment to improve it. If your game has some kind of timer, you can have this effect fade away over time. Like a sword getting dull over time. Or you could pay a weapon smith to sharpen your sword just before you go into the dragons lair...The list could go on and on.What you need to make all this happen is a game with some kind of time or event driver. IMO that is what you are looking at right now.The reason I am making all this fuzz is that I wrote a simple event driven game world some time ago that I thought I would show you.*** Source Snippet Removed ***This little RPG wannabe (I have a version with more flesh on it if your iterrested) has a game loop generating events based on user input, and a game world for the player to explore.

Ha that's cool, now I need to use that to design the ability to "move around." But, I'm having trouble figuring out how to do combat still.
I know my method of combat so far isn't the best way to do it at all, but before proposing something new, could somebody correct my design to get it to work. Then once it works and I see that there are many other and better ways to do the same thing, we can discuss those =) Thanks!

1. 1
2. 2
3. 3
4. 4
frob
15
5. 5

• 16
• 12
• 20
• 12
• 17
• Forum Statistics

• Total Topics
632155
• Total Posts
3004485

×

Important Information

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!