#include <iostream>
#include <vector>
#include <conio.h> // For _getch()
#include <algorithm> // For std::find_if
#include <cstdlib> // For system(), rand()
#include <ctime> // For time()
#include <cmath> // For abs()
#include <string>
// Struct for entities (player, enemies, bunkers)
struct Entity {
int x, y;
int health;
char symbol;
};
// Struct for pickups (like medkits)
struct Pickup {
int x, y;
char symbol;
int value; // e.g., health restore
};
// Struct for player weapons
struct Weapon {
std::string name;
int range; // effective shooting range
int ammo; // current ammo in clip
int clipSize; // max ammo in a clip
};
// Global score variable
int score = 0;
// --------------------
// Battle Encounter System (Turn-Based)
// --------------------
void displayHealthBar(const std::string &name, int health, int maxHealth) {
int barWidth = 20;
int pos = (health * barWidth) / maxHealth;
std::cout << name << " Health: [";
for (int i = 0; i < barWidth; i++) {
if (i < pos)
std::cout << "#";
else
std::cout << "-";
}
std::cout << "] " << health << "/" << maxHealth << std::endl;
}
bool battleEncounter(const std::string &battleName, int &playerHealth, int maxPlayerHealth, int enemyHealth) {
std::cout << "\n=== Battle: " << battleName << " ===\n";
while (playerHealth > 0 && enemyHealth > 0) {
displayHealthBar("Player", playerHealth, maxPlayerHealth);
std::cout << "Enemy Health: " << enemyHealth << std::endl;
std::cout << "Press 's' to shoot: ";
char action = _getch();
if (action == 's' || action == 'S') {
int damage = 10 + rand() % 11; // Damage: 10-20
std::cout << "\nYou shoot the enemy and deal " << damage << " damage!\n";
enemyHealth -= damage;
if (enemyHealth <= 0) {
std::cout << "Enemy defeated!\n";
break;
}
} else {
std::cout << "\nInvalid input, you lose your chance to shoot!\n";
}
int enemyDamage = 10 + rand() % 6; // Damage: 10-15
std::cout << "Enemy shoots back and deals " << enemyDamage << " damage!\n";
playerHealth -= enemyDamage;
if (playerHealth <= 0) {
std::cout << "You have been defeated in battle: " << battleName << "\n";
return false;
}
}
return true;
}
bool battleBunker(Entity &bunker, int &playerHealth) {
int bunkerMaxHealth = bunker.health;
std::cout << "\nInitiating Bunker Assault at (" << bunker.x << "," << bunker.y << "). Bunker Health: " << bunker.health << "\n";
while (bunker.health > 0 && playerHealth > 0) {
displayHealthBar("Player", playerHealth, 100);
displayHealthBar("Bunker", bunker.health, bunkerMaxHealth);
std::cout << "Press 's' to shoot the bunker: ";
char action = _getch();
if (action == 's' || action == 'S') {
int damage = 10 + rand() % 11; // Damage: 10-20
std::cout << "\nYou hit the bunker for " << damage << " damage!\n";
bunker.health -= damage;
if (bunker.health <= 0) {
std::cout << "Bunker destroyed and captured!\n";
return true;
}
} else {
std::cout << "\nInvalid input, you missed your chance!\n";
}
int turretDamage = 5 + rand() % 6; // Damage: 5-10
std::cout << "Bunker turret fires and deals " << turretDamage << " damage to you!\n";
playerHealth -= turretDamage;
if (playerHealth <= 0) {
std::cout << "You have been killed by the bunker defenses!\n";
return false;
}
}
return true;
}
// --------------------
// Map and Campaign Gameplay
// --------------------
void render(const std::vector<std::vector<char>>& baseMap,
const Entity& player,
const std::vector<Entity>& enemies,
const std::vector<Pickup>& pickups,
const std::vector<Entity>& bunkers,
const Weapon& weapon) {
system("cls");
std::vector<std::vector<char>> displayMap = baseMap;
for (const auto &pick : pickups) {
displayMap[pick.y][pick.x] = pick.symbol;
}
for (const auto &bunker : bunkers) {
displayMap[bunker.y][bunker.x] = bunker.symbol;
}
for (const auto &enemy : enemies) {
displayMap[enemy.y][enemy.x] = enemy.symbol;
}
displayMap[player.y][player.x] = player.symbol;
for (const auto &row : displayMap) {
for (char c : row)
std::cout << c << ' ';
std::cout << std::endl;
}
std::cout << "Player Health: " << player.health;
if (player.health < 30)
std::cout << " [WARNING: LOW HEALTH]";
std::cout << "\nScore: " << score;
std::cout << "\nWeapon: " << weapon.name << " | Ammo: " << weapon.ammo << "/" << weapon.clipSize << std::endl;
std::cout << "\nControls:" << std::endl;
std::cout << " Movement: w/a/s/d and diagonals (q, e, z, c)" << std::endl;
std::cout << " Shooting: i/j/k/l for up/left/down/right" << std::endl;
std::cout << " Grenade: g Reload: r" << std::endl;
}
void addObstacles(std::vector<std::vector<char>>& baseMap, int count) {
int height = baseMap.size();
int width = baseMap[0].size();
int placed = 0;
while (placed < count) {
int x = rand() % width;
int y = rand() % height;
if (baseMap[y][x] == '.') {
baseMap[y][x] = '#';
placed++;
}
}
}
void playCampaign(int campaign) {
const int MAP_WIDTH = 10;
const int MAP_HEIGHT = 10;
std::vector<std::vector<char>> baseMap(MAP_HEIGHT, std::vector<char>(MAP_WIDTH, '.'));
addObstacles(baseMap, 10);
Entity player = {5, 9, 100, 'P'};
std::vector<Entity> enemies;
std::vector<Pickup> pickups;
Weapon weapon = {"Rifle", 6, 6, 6}; // Range, ammo, clip size.
std::vector<Entity> bunkers;
if (campaign == 1) {
std::cout << "Mission Briefing: D-Day - Your objective is to capture enemy bunkers along the coast.\n";
bunkers.push_back({3, 0, 50, 'B'});
bunkers.push_back({7, 0, 50, 'B'});
baseMap[0][3] = 'B';
baseMap[0][7] = 'B';
enemies = {
{3, 3, 50, 'E'},
{7, 3, 50, 'E'},
{5, 5, 50, 'E'}
};
pickups.push_back({2, 6, 'M', 20});
} else if (campaign == 2) {
std::cout << "Mission Briefing: Aden Offensive - Hold off enemy forces at all costs!\n";
enemies = {
{2, 2, 50, 'E'},
{4, 3, 50, 'E'},
{6, 2, 50, 'E'},
{3, 4, 50, 'E'},
{7, 4, 50, 'E'}
};
pickups.push_back({1, 8, 'M', 20});
} else {
std::cout << "Mission Briefing: Berlin Attack - Capture the flag deep in enemy territory!\n";
baseMap[0][5] = 'F';
enemies = {
{4, 2, 50, 'E'},
{6, 2, 50, 'E'},
{5, 4, 50, 'E'},
{3, 3, 50, 'E'}
};
pickups.push_back({8, 7, 'M', 20});
}
while (true) {
render(baseMap, player, enemies, pickups, bunkers, weapon);
char input = _getch();
int dx = 0, dy = 0;
bool isMove = false, isShoot = false, isGrenade = false, isReload = false;
if (input == 'w') { dy = -1; isMove = true; }
else if (input == 's') { dy = 1; isMove = true; }
else if (input == 'a') { dx = -1; isMove = true; }
else if (input == 'd') { dx = 1; isMove = true; }
else if (input == 'q') { dx = -1; dy = -1; isMove = true; }
else if (input == 'e') { dx = 1; dy = -1; isMove = true; }
else if (input == 'z') { dx = -1; dy = 1; isMove = true; }
else if (input == 'c') { dx = 1; dy = 1; isMove = true; }
else if (input == 'i') { dy = -1; isShoot = true; }
else if (input == 'k') { dy = 1; isShoot = true; }
else if (input == 'j') { dx = -1; isShoot = true; }
else if (input == 'l') { dx = 1; isShoot = true; }
else if (input == 'g') { isGrenade = true; }
else if (input == 'r') { isReload = true; }
// Process movement.
if (isMove) {
int newX = player.x + dx;
int newY = player.y + dy;
if (newX >= 0 && newX < MAP_WIDTH && newY >= 0 && newY < MAP_HEIGHT &&
(baseMap[newY][newX] == '.' || baseMap[newY][newX] == 'B' || baseMap[newY][newX] == 'F')) {
player.x = newX;
player.y = newY;
if (campaign == 1 && baseMap[newY][newX] == 'B') {
auto it = std::find_if(bunkers.begin(), bunkers.end(), [newX, newY](const Entity &b) {
return b.x == newX && b.y == newY;
});
if (it != bunkers.end()) {
bool survived = battleBunker(*it, player.health);
if (survived) {
score += 100;
baseMap[newY][newX] = '.';
bunkers.erase(it);
} else {
render(baseMap, player, enemies, pickups, bunkers, weapon);
std::cout << "Game Over! You were killed by bunker defenses.\n";
return;
}
}
}
if (campaign == 3 && baseMap[newY][newX] == 'F') {
baseMap[newY][newX] = '.';
score += 100;
std::cout << "Flag captured! (+100 points)\n";
}
}
for (auto it = pickups.begin(); it != pickups.end(); ) {
if (it->x == player.x && it->y == player.y) {
player.health += it->value;
if (player.health > 100) player.health = 100;
std::cout << "Picked up a medkit! Health restored by " << it->value << ".\n";
score += 50;
it = pickups.erase(it);
} else {
++it;
}
}
}
// Process shooting.
else if (isShoot) {
if (weapon.ammo <= 0) {
std::cout << "Out of ammo! Reload (press 'r')!\n";
} else {
weapon.ammo--;
std::cout << "BANG!\n";
// Start bullet trace one cell away from the player.
int shotX = player.x + dx;
int shotY = player.y + dy;
for (int r = 0; r < weapon.range; r++) {
if (shotX < 0 || shotX >= MAP_WIDTH || shotY < 0 || shotY >= MAP_HEIGHT)
break;
if (baseMap[shotY][shotX] == '#')
break;
// Check for an enemy at this cell.
auto it = std::find_if(enemies.begin(), enemies.end(), [shotX, shotY](const Entity &e) {
return e.x == shotX && e.y == shotY;
});
if (it != enemies.end()) {
int damage = 10 + rand() % 60; // Damage: 10-20
it->health -= damage;
std::cout << "Hit enemy at (" << shotX << "," << shotY << ") for " << damage << " damage.\n";
if (it->health <= 0) {
enemies.erase(it);
score += 100;
std::cout << "Enemy eliminated! (+100 points)\n";
}
break; // Stop bullet once an enemy is hit.
}
shotX += dx;
shotY += dy;
}
}
}
// Process grenade attack.
else if (isGrenade) {
std::cout << "BOOM! Grenade exploded.\n";
std::cout << "Enter grenade direction (i/j/k/l): ";
char gDir = _getch();
int centerX = player.x, centerY = player.y;
if (gDir == 'i') { centerY = player.y - 1; }
else if (gDir == 'k') { centerY = player.y + 1; }
else if (gDir == 'j') { centerX = player.x - 1; }
else if (gDir == 'l') { centerX = player.x + 1; }
for (auto it = enemies.begin(); it != enemies.end(); ) {
if (abs(it->x - centerX) <= 1 && abs(it->y - centerY) <= 1) {
it->health -= 20;
std::cout << "Grenade hit enemy at (" << it->x << "," << it->y << ") for 20 damage.\n";
if (it->health <= 0) {
it = enemies.erase(it);
score += 100;
std::cout << "Enemy eliminated by grenade! (+100 points)\n";
continue;
}
}
++it;
}
}
// Process reload.
else if (isReload) {
weapon.ammo = weapon.clipSize;
std::cout << "Reloading...\n";
}
// Enemy actions.
for (auto &enemy : enemies) {
// If enemy is aligned with player, attempt shooting.
if (enemy.x == player.x || enemy.y == player.y) {
int shotDx = (enemy.x == player.x) ? 0 : (enemy.x < player.x ? 1 : -1);
int shotDy = (enemy.y == player.y) ? 0 : (enemy.y < player.y ? 1 : -1);
int shotX = enemy.x + shotDx;
int shotY = enemy.y + shotDy;
while (shotX >= 0 && shotX < MAP_WIDTH && shotY >= 0 && shotY < MAP_HEIGHT) {
if (baseMap[shotY][shotX] == '#') break;
if (shotX == player.x && shotY == player.y) {
int dmg = 10 + rand() % 6; // Damage: 10-15.
player.health -= dmg;
std::cout << "An enemy shot you for " << dmg << " damage!\n";
break;
}
shotX += shotDx;
shotY += shotDy;
}
}
// Otherwise, move enemy toward player if the destination is empty.
else {
int moveDx = (enemy.x < player.x) ? 1 : (enemy.x > player.x ? -1 : 0);
int moveDy = (enemy.y < player.y) ? 1 : (enemy.y > player.y ? -1 : 0);
int newX = enemy.x + moveDx;
int newY = enemy.y + moveDy;
if (newX >= 0 && newX < MAP_WIDTH && newY >= 0 && newY < MAP_HEIGHT &&
baseMap[newY][newX] == '.') {
enemy.x = newX;
enemy.y = newY;
}
}
}
if (player.health <= 0) {
render(baseMap, player, enemies, pickups, bunkers, weapon);
std::cout << "Game Over! You died during the mission.\n";
return;
}
if (campaign == 1 && bunkers.empty()) {
render(baseMap, player, enemies, pickups, bunkers, weapon);
std::cout << "\nAll bunkers captured. Initiating final battle...\n";
bool result = battleEncounter("Bunker Final Assault", player.health, 100, 80);
if (result)
std::cout << "Victory! Mission accomplished.\n";
else
std::cout << "Defeat! Mission failed in final battle.\n";
return;
}
else if (campaign == 2 && enemies.empty()) {
render(baseMap, player, enemies, pickups, bunkers, weapon);
std::cout << "\nAll enemies eliminated. Initiating final battle...\n";
bool result = battleEncounter("Final Defense", player.health, 100, 90);
if (result)
std::cout << "Victory! Mission accomplished.\n";
else
std::cout << "Defeat! Mission failed in final battle.\n";
return;
}
else if (campaign == 3 && baseMap[0][5] != 'F') {
render(baseMap, player, enemies, pickups, bunkers, weapon);
std::cout << "\nFlag captured. Initiating final battle...\n";
bool result = battleEncounter("Flag Defense", player.health, 100, 80);
if (result)
std::cout << "Victory! Mission accomplished.\n";
else
std::cout << "Defeat! Mission failed in final battle.\n";
return;
}
}
}
int main() {
srand(static_cast<unsigned int>(time(0)));
std::cout << "Battleground 1 - Enhanced Edition\n";
std::cout << "Controls:\n";
std::cout << " Movement: w/a/s/d and diagonals (q, e, z, c)\n";
std::cout << " Shooting: i/j/k/l for up/left/down/right\n";
std::cout << " Grenade: g\n";
std::cout << " Reload: r\n";
std::cout << "\nSelect Campaign:\n1. D-Day\n2. Aden Offensive\n3. Berlin Attack\nEnter choice (1-3): ";
int choice;
std::cin >> choice;
if (choice >= 1 && choice <= 3) {
playCampaign(choice);
} else {
std::cout << "Invalid choice." << std::endl;
}
std::cout << "\nPress any key to exit.";
_getch();
return 0;
}