**This is an old revision of the document!**

# Super Smash Brothers

## Background

• In Smash Bros, players “smash” each other until one player sustains enough damage that they get knocked out (KO).
• The exact limit is random, but usually somewhere between 100% and 200%.

## Problem

We’re going to create a simplified 2-player Super Smash (SS) game in which ** Users gets to input their names ** Each player is given a random damage limit between 100 and 200 ** Players take turns smashing each other until one player exceeds their damage limit ** On a turn, a player can choose ** a risky smash (10-40 damage) or ** a sure smash (25-30 damage) ** First player’s hits are discounted 5 to make it fair

## Solution

### Source.cpp

#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include "SSPlayer.h"

using namespace std;

// Constants used for printing random smash sounds
const vector<string> SOUNDS = {"AIEEE", "ZLONK","PLOP","GLIPP","SOCK","ZLORP", "ZOK", "POWEE","SPLATT","SLOSH","KAYO", "BANG", "BAM"};
const int MAX_EXCLAMATION_POINT = 5;
const int MIN_EXCLAMATION_POINT = 1;

// First player gets a 5 point discount since (s)he goes first
const int FIRST_PLAYER_DISCOUNT = 5;

// Static functions (implemented previously)
string prompt_for_name_for_player(int player_num);
string get_random_smash_sound();
void print_smash_sounds();

int main()
{
// SET UP PLAYERS
srand(time(0));

string player_1_name = prompt_for_name_for_player(1);
string player_2_name = prompt_for_name_for_player(2);

// Create SSPlayer objects from names
SSPlayer * player1 = new SSPlayer(player_1_name, FIRST_PLAYER_DISCOUNT);
SSPlayer * player2 = new SSPlayer(player_2_name, 0);

// Use pointers to keep track of who's attacking and defending
SSPlayer * current_attacker_ptr = player1;
SSPlayer * current_defender_ptr = player2;

// EXECUTE MATCH
// As long as the current attacker wasn't wiped out from the last smash...
while (current_attacker_ptr->get_damage() <= current_attacker_ptr->get_damage_limit())
{
// State whose turn it is and prompt the player if they want a risky or a sure smash
cout << current_attacker_ptr->get_name() << ", it's your turn to SMASH!" << endl;
cout << "(R)isky or (S)ure smash? ";
string input;
getline(cin, input); // don't need to sync 'cause haven't used cin >> before

// Calculate the hit damage
double hit_damage;
if (input == "R")
{
hit_damage = current_attacker_ptr->make_risky_smash();
}
else
{
hit_damage = current_attacker_ptr->make_sure_smash();
}

// Apply damage to the defender
current_defender_ptr->suffer_hit(hit_damage);

// print smash sounds...
print_smash_sounds();

// Say who hit who and for how much
cout << current_attacker_ptr->get_name() << " SMASHED "
<< current_defender_ptr->get_name() << " for a loss of " << hit_damage << endl;

// Report the current damage counts for each player
cout << player1->get_name() << " (" << player1->get_damage() << ") - "
<< player2->get_name() << " (" << player2->get_damage() << ")" << endl;

// switch roles
SSPlayer * temp = current_attacker_ptr;
current_attacker_ptr = current_defender_ptr;
current_defender_ptr = temp;

system("pause");
}

// print more smash sound for good measure
print_smash_sounds();

cout << "MATCH OVER!" << endl;

// print out the full player summaries (which shows the damage limits), winner first
cout << current_defender_ptr->to_string() << endl << endl
<< current_attacker_ptr->to_string() << endl;

// print out a congratulations for the winner
cout << "CONGRATS, " << current_defender_ptr->get_name() << endl;

system("pause");
return 0;
}

/*
*/
string prompt_for_name_for_player(int player_num)
{
cout << "Player " << player_num << " name: ";
string player_name;
getline(cin, player_name);

return player_name;
}

/*
Print a line of three smash sounds to the console flanked with two lines of asterices
*/
void print_smash_sounds()
{
cout << endl
<< "****************************" << endl
<< get_random_smash_sound() << get_random_smash_sound() << get_random_smash_sound() << endl
<< "*****************************" << endl
<< endl;
}

/*
Generate a random smash sound with a random number of exclamation points
@return smash the generated smash sound
*/
string get_random_smash_sound()
{
string sound;

int rand_num = rand() % SOUNDS.size();
sound = SOUNDS[rand_num];

rand_num = rand() % (MAX_EXCLAMATION_POINT - MIN_EXCLAMATION_POINT) + MIN_EXCLAMATION_POINT;
for (int i = 0; i < rand_num; i++)
{
sound += "!";
}

return sound;
}

### SSPlayer.h

#include <string>

using namespace std;

#ifndef _SSPLAYER_H
#define _SSPLAYER_H

class SSPlayer
{
public:
//CONSTRUCTOR

/*
Create a new player with a random damage limit between 100 and 200
*/
SSPlayer(string _name, double hit_discount);

//MEMBER FUNCTIONS

/*
@return name of this player
*/
string get_name() const;

/*
@return the current damage to *this* player
*/
double get_damage() const;

/*
@return the damage limit at which this player dies
*/
double get_damage_limit() const;

/*
This function calculates a hit damage in a larger range
@return a random value in a larger range
*/
double make_risky_smash();

/*
This function calculates a hit damage in a small range
@return a random value in a smaller range
*/
double make_sure_smash();

/*
@param damage points that should be added to player's current damage
*/
void suffer_hit(double hit_damage);

/*
@return string representation that includes the player's name, damage, damage limit
*/
string to_string() const;

private:
/*
This function is used for make_sure_smash and make_risky_smash so as to not repeat code
but is not accessible outside of the class
*/
double make_smash(double lower_range, double upper_range);

// DATA MEMBERS

string name;
double hit_discount;

double damage;
double damage_limit;
double max_match_hit;
double min_match_hit;

int total_hits; // used to calculate average hit damage
double total_hit_damage; // used to calculate average hit damage

// static means that not every object of the class will keep its own copy of the variable
// const means that the value can't change
// these are initialized in .cpp file
static const double MAX_PLAYER_DAMAGE;
static const double MIN_PLAYER_DAMAGE;

static const double MAX_SURE_HIT_DAMAGE;
static const double MIN_SURE_HIT_DAMAGE;
static const double MAX_RISKY_HIT_DAMAGE;
static const double MIN_RISKY_HIT_DAMAGE;
};

#endif

### SSPlayer.cpp

#include <iomanip>
#include <sstream>
#include "SSPlayer.h"

const double SSPlayer::MAX_PLAYER_DAMAGE = 200;

const double SSPlayer::MIN_PLAYER_DAMAGE = 100;

const double SSPlayer::MAX_SURE_HIT_DAMAGE = 30;

const double SSPlayer::MIN_SURE_HIT_DAMAGE = 25;

const double SSPlayer::MAX_RISKY_HIT_DAMAGE = 40;

const double SSPlayer::MIN_RISKY_HIT_DAMAGE = 10;

SSPlayer::SSPlayer(string _name, double _hit_discount)
{
name = _name;
hit_discount = _hit_discount;

damage = 0;
// randomly set the damage limit when player is created
damage_limit = (rand() * 1.0 / RAND_MAX) * (MAX_PLAYER_DAMAGE - MIN_PLAYER_DAMAGE) + MIN_PLAYER_DAMAGE;
max_match_hit = -1.0;
min_match_hit = 100000;

total_hits = 0;
total_hit_damage = 0.0;
}

string SSPlayer::get_name() const
{
return name;
}

double SSPlayer::get_damage() const
{
return damage;
}

double SSPlayer::get_damage_limit() const
{
return damage_limit;
}

double SSPlayer::make_risky_smash()
{
// use private member function to avoid code duplication
return make_smash(MAX_RISKY_HIT_DAMAGE, MIN_RISKY_HIT_DAMAGE);
}

double SSPlayer::make_sure_smash()
{
// use private member function to avoid code duplication
return make_smash(MAX_SURE_HIT_DAMAGE, MIN_SURE_HIT_DAMAGE);
}

void SSPlayer::suffer_hit(double hit_damage)
{
damage += hit_damage;
}

string SSPlayer::to_string() const
{
ostringstream strm;

strm << fixed << setprecision(2);

strm << name << endl
<< "Damage: " << damage << "/" << damage_limit << endl
<< "Avg hit: " << (total_hit_damage/total_hits) << endl
<< "Max hit: " << max_match_hit << endl
<< "Min hit: " << min_match_hit << endl;

return strm.str();
}

double SSPlayer::make_smash(double lower_limit, double upper_limit)
{
double smash_damage = (rand() * 1.0 / RAND_MAX) * (upper_limit - lower_limit) + lower_limit - hit_discount;

// is this smash the max so far? the min? update accordingly
if (smash_damage > max_match_hit)
{
max_match_hit = smash_damage;
}
if (smash_damage < min_match_hit)
{
min_match_hit = smash_damage;
}

// update tallies to calculate average hit damage at the end
total_hits++;
total_hit_damage += smash_damage;

return smash_damage;
}