The ‘skeleton’ of the game works, making it playable, so I’m mainly just looking for renditions and feedback on both the code, and the actual game.
Here’s the things I’m already working to fix/add:
- Add color to text
- Add startup menu
- Find a way to put names in commander fights OR alternatively have player name their cmdr
- Balance the stats like a lot oh my god
- Make integer inputs non-integer capable
- Loop the current player's turn until they input an appropriate number
- Equipment for commander
- List current price for each technology
Currently, the game’s files have a combined 562 lines, so to make it a little easy on you, here are the links to the project on the compiler I use, and the Github repository:
Compiler – https://replit.com/@Selisine/CBPR?v=1
Github – https://github.com/aidenpike/CBPR
Here is the actual code: main.cpp
#include <iostream>
#include "Country.h"
using namespace std;
int main(){
Player *currentPlayer;
getNames(&p1);
getNames(&p2);
while (true) {
//Player One Turn
playerTurn(&p1);
//Player Two Turn
playerTurn(&p2);
}
}
Country.h
#include <iostream>
#include <algorithm>
#include <string>
#include "Commander.h"
using std::cout;
using std::string;
using std::cin;
using std::endl;
struct Player {
string name = " ";
int territories = 2;
int armies = 10;
int armySkill = 0;
int armyEndurance = 0;
int weaponComplexity = 0;
int passiveIncome = 0;
int money = 49900;
bool weaponFailure = false;
int player = 0;
} p1, p2;
Player *currentPlayer;
//Rolls, chances, and lists
//Dice Roll
int battleRoll(int dice){
srand(int(time(0)));
return rand()%dice + 1;
}
void getNames(Player *currentPlayer){
cout << "Player, enter your name: ";
getline(cin, currentPlayer->name);
if (currentPlayer->name == "Oasis"){
cout << "Welcome back, old friend.\n";
currentPlayer->armySkill += 100;
currentPlayer->weaponComplexity += 10;
currentPlayer->passiveIncome += 1000;
currentPlayer->armies += 100;
}
}
//Comma Seperation Math (100% not stolen)
string commaSeperate(int num){
auto src = std::to_string(num);
auto dest = std::string();
auto count = 3;
for(auto i = src.crbegin() ; i != src.crend() ; ++i) {
if (count == 0)
{
dest.push_back(',');
count = 3;
}
if (count--) {
dest.push_back(*i);
}
}
reverse(dest.begin(), dest.end());
return dest;
}
//Tech List
void techList(){
cout << "[A] Army Skill\n";
cout << "[B] Army Endurance\n";
cout << "[C] Weapon Upgrade\n";
cout << "[D] Level Up Commander\n";
cout << "[H] Passive Income\n";
}
//Stat List
void listStats(Player *currentPlayer){
string passiveIncome = commaSeperate(currentPlayer->passiveIncome * 50 + 100);
string money = commaSeperate(currentPlayer->money);
cout << "It is currently " << currentPlayer->name << "'s turn. Here are their stats:\n";
cout << "\t \x1B[33m" << currentPlayer->territories << "\033[0m Territories\n"; //Yellow
cout << "\t \x1B[30m" << currentPlayer->armies << "\033[0m Armies\n"; //Light gray maybe
cout << "\t\x1B[34mLevel " << currentPlayer->armySkill << "\033[0m Army Skill\n"; //Blue
cout << "\t\x1B[31mLevel " << currentPlayer->armyEndurance << "\033[0m Army Endurance\n"; //Red
cout << "\t\x1B[35mLevel " << currentPlayer->weaponComplexity << "\033[0m Weapon Complexity\n"; //Purple
cout << "\t \x1B[32m$" << passiveIncome << "\033[0m Dollars in passive income\n"; //Green
cout << "\t \x1B[32m$" << money << "\033[0m Dollars\n\n\n"; //Green
}
//Weapon Failure
void weaponFailure(Player *currentPlayer){
int weaponFail = battleRoll(20) + 1 * currentPlayer->weaponComplexity;
if ((weaponFail - currentPlayer->armySkill) <= 5){
cout << "\x1B[31m" << currentPlayer->name << ", your weapons failed during battle!\033[0m\n";
switch (rand()%3 + 1){
case 1:
cout << "\x1B[33m" << currentPlayer->name << " loses this battle, and flees!\033[0m\n";
(battleRoll(10) + currentPlayer->armyEndurance <= 5) ? currentPlayer->armies-- : currentPlayer->armies = currentPlayer->armies;
currentPlayer->money -= rand()%1000 + 500;
currentPlayer->weaponFailure = true;
break;
case 2:
cout << "\x1B[32m" << currentPlayer->name << ", you escape by a thread!\033[0m\n";
currentPlayer->money -= rand()%1000 + 500;
currentPlayer->weaponFailure = true;
break;
case 3:
cout << "\x1B[31m" << currentPlayer->name << ", the battle was immensely devastating.\033[0m\n";
currentPlayer->money -= rand()%2000 + 1300;
(battleRoll(10) + currentPlayer->armyEndurance <= 10) ? currentPlayer->armies -= 2 : currentPlayer->armies = currentPlayer->armies;
currentPlayer->weaponComplexity--;
currentPlayer->weaponFailure = true;
}
}
}
//Expand territory
void expandTerritory(Player *currentPlayer){
int territoryPrice = 10000;
if (currentPlayer->money >= territoryPrice){
cout << currentPlayer->name << " expanded their territory!\n";
currentPlayer->money -= territoryPrice;
currentPlayer->territories++;
}
else {
cout << "You don't have enough money!\n\n";
}
}
//Actual function for tech choices
void upgradeTechnology(Player *currentPlayer){
p1.player = 1;
p2.player = 2;
int techPrice = 8000;
char techBranch = ' ';
cout << "Which technology would you like to upgrade?\n";
techList();
cin >> techBranch;
techBranch = toupper(techBranch);
switch (techBranch){
//Army Skill
case 'A':
if (techPrice + (800 * currentPlayer->armySkill) > currentPlayer->money){
cout << "You don't have enough money!\n\n";
}
else {
cout << "After a long day, your armies' training is done. It pays off an they gain one skill level!\n\n";
currentPlayer->armySkill++;
currentPlayer->money -= techPrice + (800 * currentPlayer->armySkill);
}
break;
case 'B':
if (techPrice + (1000 * currentPlayer->armyEndurance > currentPlayer->money)){
cout << "Not enough money!\n\n";
}
else {
cout << "Your armies train hard, focusing more towards their endurance. Their endurance gains on level!\n\n";
currentPlayer->armyEndurance++;
currentPlayer->money -= techPrice + (1000 * currentPlayer->armyEndurance);
}
break;
case 'C':
if (2000 + techPrice + (1000 * currentPlayer->weaponComplexity > currentPlayer->money)){
cout << "Not enough money!\n\n";
}
else {
cout << "Using your ingenious military scientists, you manage to develop a newer, more complex weapon. Your weapon complexity level increases!\n\n";
currentPlayer->weaponComplexity++;
currentPlayer->money -= 2000 + techPrice + (1000 * currentPlayer->weaponComplexity);
}
break;
case 'D':
if (techPrice + (500 * returnLevel(currentPlayer->player)) > currentPlayer->money){
cout << "Not enough money!\n\n";
}
else {
cmdrLVLRedirect(currentPlayer->player);
currentPlayer->money -= techPrice + (500 * returnLevel(currentPlayer->player));
}
break;
case 'H':
if (techPrice + (800 * currentPlayer->passiveIncome) > currentPlayer->money){
cout << "Not enough money!\n\n";
}
else if (currentPlayer->passiveIncome <= currentPlayer->territories){
cout << "You add more mines to your territories.\n\n";
currentPlayer->passiveIncome++;
currentPlayer->money -= techPrice + (800 * currentPlayer->passiveIncome);
}
else {
cout << "Not enough territories to add mines to!\n\n";
currentPlayer->passiveIncome = currentPlayer->territories;
}
}
}
//Recruit an army
void recruitArmy(Player *currentPlayer){
int armyPrice = 8000;
if (currentPlayer->money >= armyPrice){
cout << "A new army is hired.\n\n";
currentPlayer->armies++;
currentPlayer->money -= armyPrice;
}
else {
cout << "Not enough money to recruit another army!\n\n";
}
}
void battleInitiation(){
int outcomeChoice = 0;
int pOneATKRoll = battleRoll(8) + battleRoll(8) + p1.armySkill * 2 + p1.weaponComplexity * 3 + p1.armies + cmdr1.cmdrMOR;
int pTwoATKRoll = battleRoll(8) + battleRoll(8) + p2.armySkill * 2 + p2.weaponComplexity * 3 + p2.armies + cmdr2.cmdrMOR;
bool cmdrFight = false;
cout << "What is your goal for battle?\n";
cout << "1. Devastate\n";
cout << "2. Conquer\n";
cin >> outcomeChoice;
(rand()%2 + 1 == 2) ? cmdrFight = true : cmdrFight = false;
p1.weaponFailure = false;
p2.weaponFailure = false;
weaponFailure(&p1);
weaponFailure(&p2);
switch (outcomeChoice){
case 1:
if (p1.weaponFailure && p2.weaponFailure){
cout << "It's a tie!\n\n";
p1.money -= 5;
p2.money -= 5;
p1.weaponFailure = false;
p2.weaponFailure = false;
cmdrFight = false;
}
else if (cmdrFight){
if (cmdrBattle() == "p1win"){
cout << p1.name << " has devastated this territory.\n\n";
p2.territories--;
p2.money -= rand()%750 + 500;
}
else {
cout << p2.name << " has devastated this territory.\n\n";
p1.territories--;
p1.money -= rand()%750 + 500;
}
}
else if (pOneATKRoll > pTwoATKRoll || p2.weaponFailure){
cout << p1.name << " has devastated this territory.\n\n";
p2.territories--;
p2.money -= rand()%750 + 500;
}
else if (pOneATKRoll == pTwoATKRoll){
cout << "Both players' weapons fail, it's a tie!\n\n";
p1.money -= 5;
p2.money -= 5;
}
else if (pOneATKRoll < pTwoATKRoll || p1.weaponFailure){
cout << p2.name << " has devastated this territory.\n\n";
p1.territories--;
p1.money -= rand()%750 + 500;
}
break;
case 2:
if (p1.weaponFailure && p2.weaponFailure){
cout << "It's a tie!\n\n";
p1.money -= 5;
p2.money -= 5;
}
else if (cmdrFight){
if (cmdrBattle() == "p1win"){
cout << p1.name << " has conquered this territory.\n\n";
p1.territories++;
p2.territories--;
p1.money += rand()%500 + 250;
p2.money -= rand()%500 + 250;
}
else {
cout << p2.name << " has conquered this territory.\n\n";
p2.territories++;
p1.territories--;
p2.money += rand()%500 + 250;
p1.money -= rand()%500 + 250;
}
}
else if (pOneATKRoll > pTwoATKRoll || p2.weaponFailure){
cout << p1.name << " has conquered this territory.\n\n";
p1.territories++;
p2.territories--;
p1.money += rand()%500 + 250;
p2.money -= rand()%500 + 250;
}
else if (pOneATKRoll == pTwoATKRoll || (p1.weaponFailure && p2.weaponFailure)){
cout << "It's a tie!\n\n";
p1.money -= 5;
p2.money -= 5;
}
else if (pOneATKRoll < pTwoATKRoll || p1.weaponFailure){
cout << p2.name << " has conquered this territory.\n\n";
p2.territories++;
p1.territories--;
p2.money += rand()%500 + 250;
p1.money -= rand()%500 + 250;
}
}
p1.weaponFailure = false;
p2.weaponFailure = false;
}
//Lose Check
void hasLost(){
if (p1.territories <= 0 && p2.territories <= 0){
cout << "Both empires go down in flames. The war is a tie.\n\n";
exit(0);
}
if (p1.money <= 0 && p2.money <= 0){
cout << "Both empires go down in flames. The war is a tie.\n\n";
exit(0);
}
if (p1.money <= 0){
cout << p1.name << " has been devastated by " << p2.name << "!\n\n";
exit(0);
}
else if (p1.territories <= 0){
cout << p1.name << " has been conquered by " << p2.name << "!\n\n";
exit(0);
}
if (p2.money <= 0){
cout << p2.name << " has been devastated by " << p1.name << "!\n\n";
exit(0);
}
else if (p2.territories <= 0){
cout << p2.name << " has been conquered by " << p1.name << "!\n\n";
exit(0);
}
}
void playerTurn(Player *currentPlayer){
hasLost();
//Passive Income
currentPlayer->money += 100 + (50 * currentPlayer->passiveIncome);
//List stats for current player
listStats(currentPlayer);
int choice = 0;
cout << "What do you wish to do?" << endl;
cout << "\t1. Grow Territory ($10,000)\n";
cout << "\t2. Upgrade Technology\n";
cout << "\t3. Recruit Army ($8,000)\n";
cout << "\t4. Attack\n";
cout << "\t5. Pass\n\n";
cin >> choice;
switch (choice){
case 1:
expandTerritory(currentPlayer);
break;
case 2:
upgradeTechnology(currentPlayer);
break;
case 3:
recruitArmy(currentPlayer);
break;
case 4:
battleInitiation();
break;
}
}
Commander.h
#include <iostream>
using std::cout;
using std::endl;
using std::string;
struct Commander {
int cmdrLVL = 1;
int cmdrATK = 2;
int cmdrDEF = 5;
int cmdrMDEF = 5;
int cmdrHP = 10;
int cmdrMHP = 10;
int cmdrMOR = 3;
} cmdr1, cmdr2;
Commander *currentCmdr;
void cmdrLevelUp(Commander *currentCmdr, int player){
cout << "Player " << player << ", you leveled up your commander!\n";
currentCmdr->cmdrLVL++;
currentCmdr->cmdrHP *= 1.2 * currentCmdr->cmdrLVL + 1;
currentCmdr->cmdrMHP *= 1.2 * currentCmdr->cmdrLVL + 1;
currentCmdr->cmdrDEF *= 1.2 * currentCmdr->cmdrLVL + 1;
currentCmdr->cmdrMDEF *= 1.2 * currentCmdr->cmdrLVL + 1;
currentCmdr->cmdrATK *= 1.1 * currentCmdr->cmdrLVL + 1;
currentCmdr->cmdrMOR *= 1.05 * currentCmdr->cmdrLVL + 1;
}
void cmdrLVLRedirect(int player){
(player == 1) ? cmdrLevelUp(&cmdr1, player) : cmdrLevelUp(&cmdr2, player);
}
void cmdrChoiceList(){
cout << "1. Attack\n";
cout << "2. Repair Armor\n";
cout << "3. Forfeit\n";
}
int returnLevel(int player){
return (player == 1) ? cmdr1.cmdrLVL : cmdr2.cmdrLVL;
}
void cmdrStats(Commander *currentCmdr){
cout << "[Current Commander Stats]\n";
cout << "\tHP: " << currentCmdr->cmdrHP << "/" << currentCmdr->cmdrMHP << endl;
cout << "\tDEF: " << currentCmdr->cmdrDEF << "/" << currentCmdr->cmdrMDEF << endl;
cout << "\tATK: " << currentCmdr->cmdrATK << endl;
cout << "\tMorale: " << currentCmdr->cmdrMOR << endl;
}
void cmdrResetStats(Commander *currentCmdr){
currentCmdr->cmdrHP = currentCmdr->cmdrMHP;
currentCmdr->cmdrDEF = currentCmdr->cmdrMDEF;
}
//One Fight Cycle
void cmdrFight(Commander *currentCmdr, Commander *opposingCmdr){
int choice = 0;
if (currentCmdr->cmdrDEF < 0){
currentCmdr->cmdrDEF = 0;
}
cmdrStats(currentCmdr);
cmdrChoiceList();
std::cin >> choice;
switch (choice){
case 1:
cout << "This commander takes a swift strike at his opponent!\n";
if (rand()%20 + 1 < 10){
cout << "He hits!\n";
if (currentCmdr->cmdrDEF > 0){
currentCmdr->cmdrDEF -= opposingCmdr->cmdrATK;
}
else if (currentCmdr->cmdrDEF <= 0){
currentCmdr->cmdrHP -= opposingCmdr->cmdrATK;
}
}
else {
cout << "He misses!\n";
}
break;
case 2:
if (cmdr1.cmdrDEF < cmdr1.cmdrMDEF){
cout << "This commander repairs his armor!\n'";
currentCmdr->cmdrDEF += (rand()%3 + 1) * currentCmdr->cmdrLVL;
}
else if (cmdr1.cmdrDEF >= cmdr1.cmdrMDEF){
cout << "Armor already at max!\n";
currentCmdr->cmdrDEF = currentCmdr->cmdrMDEF;
}
break;
case 3:
cout << "This commander forfeits this skirmish!\n";
currentCmdr->cmdrHP = 0;
break;
}
}
//Entire Fight Loop
string cmdrBattle(){
cout << "A fight between both commanders ensues!\n\n";
cmdrResetStats(&cmdr1);
cmdrResetStats(&cmdr2);
while (cmdr1.cmdrHP > 0 || cmdr2.cmdrHP > 0){
cout << "Player 1, it's your move. What do you wish to do?\n";
cmdrFight(&cmdr1, &cmdr2);
if (cmdr1.cmdrHP <= 0){
cout << "Player 1's commander has fallen!\n\n";
return "p2win";
break;
}
cout << "Player 2, it's your move. What do you wish to do?\n";
cmdrFight(&cmdr2, &cmdr1);
if (cmdr2.cmdrHP <= 0){
cout << "Player 2's commander has fallen!\n\n";
return "p1win";
break;
}
}
}