Adam Schmidt
Adam Schmidt

Reputation: 103

C++ Why is my loop breaking?

I'm following a tutorial for making a MUD (text-based RPG), and I am having issues with my main function. If you'll look at the code, you'll see that when the player moves it will check for a random encounter, and if monster != 0, it will go into the combat loop. When I execute this in the command prompt, it will allow me to attack the monster, but it never makes it to the monster->attack(mainPlayer) function. It just goes back to the screen that states whether I want to move, rest, view stats, or quit. Any help with this would be greatly appreciated!

#include "stdafx.h"
#include "Map.h"
#include "Player.h"
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;

int main()
{
    srand( time(0) );
    Map gameMap;
    Player mainPlayer;

    mainPlayer.createClass();

    // Begin adventure
    bool done = false;
    while( !done )
    {
        // Each loop cycle we output the player position and
        // a selection menu.

        gameMap.printPlayerPos();

        int selection = 1;
        cout << "1) Move 2) Rest 3) View Stats 4) Quit: ";
        cin >> selection;

        Monster* monster = 0;
        switch( selection )
        {
        case 1:
            // Move the player
            gameMap.movePlayer();

            // Check for a random encounter.  This function
            // returns a null pointer if no monsters are
            // encountered.
            monster = gameMap.checkRandomEncounter();

            // 'monster' not null, run combat simulation.
            if( monster != 0)
            {
                // Loop until 'break' statement.
                while( true )
                {
                    // Display hitpoints
                    mainPlayer.displayHitPoints();
                    monster->displayHitPoints();
                    cout << endl;

                    // Player's turn to attack first.
                    bool runAway = mainPlayer.attack(*monster);

                    if( runAway )
                    {
                        break;
                    }

                    if( monster->isDead() )
                    {
                        mainPlayer.victory(monster->getXPReward());
                        mainPlayer.levelUp();
                        break;
                    }

                    monster->attack(mainPlayer);

                    if( mainPlayer.isDead() )
                    {
                        mainPlayer.gameover();
                        done = true;
                        break;
                    }
                }

                // The pointer to a monster returned from
                // checkRandomEncounter was allocated with
                // 'new', so we must delete it to avoid
                // memeory leaks.
                delete monster;
                monster = 0;
            }

            break;
        case 2:
            mainPlayer.rest();
            break;
        case 3:
            mainPlayer.viewStats();
            break;
        case 4:
            done = true;
            break;
        } // End switch statement
    } // End While statement
} // End main function

Here is the Player::attack function:

bool Player::attack(Monster& monster)
{
    int selection = 1;
    std::cout << "1) Attack 2) Run: ";
    std::cin >> selection;
    std::cout << std::endl;

    switch( selection )
    {
    case 1:
        std::cout << "You attack the " << monster.getName()
                  << " with a " << mWeapon.mName << std::endl;

        if( Random(0, 20) < mAccuracy )
        {
            int damage = Random(mWeapon.mDamageRange);

            int totalDamage = damage - monster.getArmor();

            if( totalDamage <= 0)
            {
                std::cout << "Your attack failed to penetrate the " 
                          << monster.getName() << "'s armor." << std::endl;
            }
            else
            {
                std::cout << "You attack for " << totalDamage
                          << " damage!" << std::endl;

                // Subtract from monster's hitpoints.
                monster.takeDamage(totalDamage);
            }
        }
        else
        {
            std::cout << "You miss!" << std::endl;
        }
        std::cout << std::endl;
        break;

    case 2:
        // 25% chance of being able to run.
        int roll = Random(1, 4);

        if( roll == 1 )
        {
            std::cout << "You run away!" << std::endl;
            return true; //<-- Return out of the function.
        }
        else
        {
            std::cout << "You could not escape!" << std::endl;
            break;
        }
    }
}

And here is the Monster::attack function:

void Monster::attack(Player& player)
{

    cout << "A " <<mName << " attacks you "
         << "with a " << mWeapon.mName << std::endl;

    if( Random(0,20) < mAccuracy )
    {
        int damage = Random(mWeapon.mDamageRange);

        int totalDamage = damage - player.getArmor();

        if( totalDamage <= 0 )
        {
            cout << "The " << mName << "'s attack failed to "
                 << "penetrate your armor." << endl;
        }

        else
        {
            cout << "You are hit for " << totalDamage
                 << " damage!" << endl;

            player.takeDamage(totalDamage);
        }
    }
    else
    {
        cout << "The " << mName << " missed!" << endl;
    }
    cout << endl;
}

Upvotes: 0

Views: 292

Answers (2)

SirGuy
SirGuy

Reputation: 10760

Your Player::attack doesn't return in all cases (specifically when it needs to return false). When the calling function tries to access the return value of Player::Attack it will get junk and so you enter the if(ranAway) block and break out of your while loop

Upvotes: 1

Daniel Frey
Daniel Frey

Reputation: 56863

Your Player::attack() method has only one return-statement: return true;. You forgot to add the final line return false; to your method.

This could have easily been prevented if you enable warnings (and pay attention to them!)

Upvotes: 3

Related Questions