#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(), sin(), cos(), M_PI
#include <string>
// --------------------
// Data Structures (Common)
// --------------------
struct Entity {
int x, y;
int health;
char symbol;
};
struct Pickup {
int x, y;
char symbol;
int value; // e.g., health restore
};
struct Weapon {
std::string name;
int range; // effective shooting range (grid cells)
int ammo; // current ammo in clip
int clipSize; // max ammo in a clip
};
int score = 0;
// --------------------
// Battle Encounter System (for Campaigns 1-3)
// --------------------
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++) {
std::cout << (i < pos ? "#" : "-");
}
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') {
// Rifle now does 10-60 damage.
int damage = 10 + rand() % 51;
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; // 10-15 damage
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() % 51; // Rifle damage now 10-60
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; // 5-10 damage
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-Based Gameplay (Campaigns 1-4)
// --------------------
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 &p : pickups)
displayMap[p.y][p.x] = p.symbol;
for (const auto &b : bunkers)
displayMap[b.y][b.x] = b.symbol;
for (const auto &e : enemies)
displayMap[e.y][e.x] = e.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:\n Movement: w/a/s/d and diagonals (q, e, z, c)\n Shooting: i/j/k/l for up/left/down/right\n Grenade: g Reload: r" << std::endl;
}
void addObstacles(std::vector<std::vector<char>> &baseMap, int count) {
int height = baseMap.size(), width = baseMap[0].size();
int placed = 0;
while (placed < count) {
int x = rand() % width, y = rand() % height;
if (baseMap[y][x] == '.') {
baseMap[y][x] = '#';
placed++;
}
}
}
void playCampaign(int campaign) {
const int MAP_WIDTH = 10, 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;
// Rifle now uses a damage formula of 10-60 (implemented in shooting code below)
Weapon weapon = {"Rifle", 6, 6, 6};
std::vector<Entity> bunkers;
if (campaign == 1) {
std::cout << "Mission Briefing: D-Day - 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!\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 if (campaign == 3) {
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});
}
else if (campaign == 4) {
// German D-Day: Machine Gun Defense.
std::cout << "German D-Day Mission: Defend the trench using your machine gun with two NPC teammates.\n";
player.health = 100;
std::vector<Entity> teammates = { {4,9,80,'T'}, {6,9,80,'T'} };
int totalWaves = 10;
for (int wave = 1; wave <= totalWaves; wave++) {
std::cout << "\n--- Wave " << wave << " ---\n";
std::vector<Entity> waveEnemies = {
{rand() % MAP_WIDTH, 0, 40, 'A'},
{rand() % MAP_WIDTH, 0, 40, 'A'},
{rand() % MAP_WIDTH, 0, 40, 'A'}
};
while (!waveEnemies.empty()) {
system("cls");
std::cout << "German D-Day - Wave " << wave << " / " << totalWaves << "\n";
displayHealthBar("Player", player.health, 100);
for (size_t i = 0; i < teammates.size(); i++)
std::cout << "Teammate " << i+1 << " Health: " << teammates[i].health << "\n";
std::cout << "Remaining attackers: " << waveEnemies.size() << "\n";
std::cout << "Press 's' to fire machine gun (direction: i/j/k/l): ";
char action = _getch();
int mdx = 0, mdy = 0;
if (action=='i') { mdy = -1; }
else if (action=='k') { mdy = 1; }
else if (action=='j') { mdx = -1; }
else if (action=='l') { mdx = 1; }
else { std::cout << "\nInvalid input, turn skipped.\n"; }
int shotX = player.x + mdx, shotY = player.y + mdy;
bool hit = false;
// Machine gun now does 25-50 damage.
for (int r = 0; r < 6 && !hit; r++) {
if (shotX < 0 || shotX >= MAP_WIDTH || shotY < 0 || shotY >= MAP_HEIGHT)
break;
auto it = std::find_if(waveEnemies.begin(), waveEnemies.end(), [shotX, shotY](const Entity &e){
return e.x == shotX && e.y == shotY;
});
if (it != waveEnemies.end()) {
int damage = 25 + rand() % 26; // Damage: 25-50
it->health -= damage;
std::cout << "\nYou machine gun an attacker at (" << shotX << "," << shotY << ") for " << damage << " damage.\n";
if (it->health <= 0) {
waveEnemies.erase(it);
score += 100;
std::cout << "Attacker eliminated! (+100 points)\n";
}
hit = true;
break;
}
shotX += mdx; shotY += mdy;
}
// Teammates fire automatically.
for (auto &tm : teammates) {
if (!waveEnemies.empty()) {
int targetIndex = rand() % waveEnemies.size();
int damage = 25 + rand() % 26; // same machine gun damage.
waveEnemies[targetIndex].health -= damage;
std::cout << "Teammate fires and deals " << damage << " damage.\n";
if (waveEnemies[targetIndex].health <= 0) {
waveEnemies.erase(waveEnemies.begin() + targetIndex);
score += 100;
std::cout << "Attacker eliminated by teammate! (+100 points)\n";
}
}
}
// Enemies shoot back.
for (auto &ae : waveEnemies) {
int dmg = 10 + rand() % 6; // 10-15 damage
if (!teammates.empty() && (rand() % 2 == 0)) {
int tIndex = rand() % teammates.size();
teammates[tIndex].health -= dmg;
std::cout << "An attacker shoots teammate " << tIndex+1 << " for " << dmg << " damage.\n";
if (teammates[tIndex].health <= 0) {
std::cout << "Teammate " << tIndex+1 << " is down!\n";
teammates.erase(teammates.begin() + tIndex);
}
} else {
player.health -= dmg;
std::cout << "An attacker shoots you for " << dmg << " damage.\n";
}
}
std::cout << "\nPress any key for next turn in this wave...";
_getch();
if (player.health <= 0) break;
}
if (player.health <= 0) break;
std::cout << "\nWave " << wave << " cleared! Press any key to continue to the next wave...";
_getch();
}
if (player.health > 0)
std::cout << "\nAll waves repelled! German D-Day mission accomplished.\n";
else
std::cout << "\nYou have been overwhelmed in the trenches. Mission failed.\n";
return;
}
// For campaigns 1-3, regular map-based gameplay loop.
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; }
if (isMove) {
int newX = player.x + dx, 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! 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 medkit (" << it->value << ")\n"; score += 50; it = pickups.erase(it); }
else ++it;
}
}
else if (isShoot) {
if (weapon.ammo <= 0) { std::cout << "Out of ammo! Reload (press 'r')!\n"; }
else {
weapon.ammo--;
std::cout << "BANG!\n";
int shotX = player.x + dx, 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;
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() % 51; // Rifle damage 10-60
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;
}
shotX += dx; shotY += dy;
}
}
}
else if (isGrenade) {
std::cout << "BOOM! Grenade exploded.\nEnter 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;
}
}
else if (isReload) { weapon.ammo = weapon.clipSize; std::cout << "Reloading...\n"; }
for (auto &enemy : enemies) {
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, 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;
player.health -= dmg;
std::cout << "Enemy shot you for " << dmg << " damage!\n";
break;
}
shotX += shotDx; shotY += shotDy;
}
}
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, 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);
std::cout << (result ? "Victory! Mission accomplished.\n" : "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);
std::cout << (result ? "Victory! Mission accomplished.\n" : "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);
std::cout << (result ? "Victory! Mission accomplished.\n" : "Defeat! Mission failed in final battle.\n");
return;
}
}
}
// --------------------
// Campaign 5: German Aden Offensive (Panther Assault)
// --------------------
struct Tank {
float x, y;
float angle; // in degrees, 0 = right.
float speed;
int health;
};
float degToRad(float deg) {
return deg * M_PI / 180.0f;
}
float angleDiff(float a, float b) {
float diff = fabs(a - b);
return diff > 180 ? 360 - diff : diff;
}
void playCampaign5() {
const int MAP_WIDTH = 20, MAP_HEIGHT = 10;
// Player's Panther tank:
Tank playerTank = { MAP_WIDTH/2.0f, MAP_HEIGHT - 2.0f, 90.0f, 0.0f, 150 };
// Weapons:
int cannonAmmo = 4; // Main cannon ammo.
int machineGunAmmo = 20; // Machine gun ammo.
// Crew members (symbol 'C'):
int crewHealth1 = 100, crewHealth2 = 100;
int totalWaves = 8;
for (int wave = 1; wave <= totalWaves; wave++) {
std::cout << "\n--- Wave " << wave << " ---\n";
std::vector<Entity> enemies;
int numInfantry = 3 + rand() % 3; // 3-5 infantry (symbol 'I').
int numEnemyTanks = 1 + rand() % 2; // 1-2 enemy tanks (symbol 'T').
for (int i = 0; i < numInfantry; i++) {
enemies.push_back({ rand() % MAP_WIDTH, 0, 40, 'I' });
}
for (int i = 0; i < numEnemyTanks; i++) {
enemies.push_back({ rand() % MAP_WIDTH, 0, 80, 'T' });
}
// Wave simulation loop.
while (!enemies.empty()) {
system("cls");
std::cout << "German Aden Offensive (Panther Assault) - Wave " << wave << " / " << totalWaves << "\n";
std::cout << "Tank Health: " << playerTank.health << "\n";
std::cout << "Crew: Crew1(" << crewHealth1 << ") Crew2(" << crewHealth2 << ")\n";
std::cout << "Cannon Ammo: " << cannonAmmo << " Machine Gun Ammo: " << machineGunAmmo << "\n";
std::cout << "Enemies remaining: " << enemies.size() << "\n";
std::cout << "Controls: w (accelerate), s (brake), a/d (turn), [space] main cannon, m machine gun, r reload\n";
std::cout << "Enter command: ";
char cmd = _getch();
// Driving controls:
if (cmd == 'w') {
playerTank.speed += 0.5f;
if (playerTank.speed > 3.0f) playerTank.speed = 3.0f;
} else if (cmd == 's') {
playerTank.speed -= 0.5f;
if (playerTank.speed < 0) playerTank.speed = 0;
} else if (cmd == 'a') {
playerTank.angle += 10.0f;
if (playerTank.angle >= 360.0f) playerTank.angle -= 360.0f;
} else if (cmd == 'd') {
playerTank.angle -= 10.0f;
if (playerTank.angle < 0) playerTank.angle += 360.0f;
}
// Weapons:
else if (cmd == ' ') {
if (cannonAmmo <= 0) {
std::cout << "\nOut of cannon ammo! Press r to reload.\n";
} else {
cannonAmmo--;
std::cout << "\nFiring main cannon!\n";
float rad = degToRad(playerTank.angle);
int shotRange = 8;
int hitIndex = -1;
int bx = (int)round(playerTank.x), by = (int)round(playerTank.y);
for (int r = 0; r < shotRange; r++) {
bx += (int)round(cos(rad));
by -= (int)round(sin(rad));
for (size_t i = 0; i < enemies.size(); i++) {
if (enemies[i].x == bx && enemies[i].y == by) {
hitIndex = i;
break;
}
}
if (hitIndex != -1) break;
}
if (hitIndex != -1) {
int baseDamage = 200; // Main cannon base damage.
// Calculate angle from tank to enemy.
float dx = enemies[hitIndex].x - playerTank.x;
float dy = playerTank.y - enemies[hitIndex].y;
float targetAngle = atan2(dy, dx) * 180.0f / M_PI;
if (targetAngle < 0) targetAngle += 360;
float diff = angleDiff(playerTank.angle, targetAngle);
float multiplier = (diff < 45 ? 0.5f : (diff > 135 ? 1.5f : 1.0f));
int damage = (int)(baseDamage * multiplier);
enemies[hitIndex].health -= damage;
std::cout << "Main cannon hit enemy at (" << enemies[hitIndex].x << "," << enemies[hitIndex].y << ") for " << damage << " damage.\n";
if (enemies[hitIndex].health <= 0) {
std::cout << "Enemy destroyed!\n";
enemies.erase(enemies.begin() + hitIndex);
score += 150;
}
} else {
std::cout << "Main cannon missed.\n";
}
}
}
else if (cmd == 'm') {
if (machineGunAmmo <= 0) {
std::cout << "\nOut of machine gun ammo! Press r to reload.\n";
} else {
machineGunAmmo--;
std::cout << "\nFiring machine gun!\n";
float rad = degToRad(playerTank.angle);
int shotRange = 6;
int hitIndex = -1;
int bx = (int)round(playerTank.x), by = (int)round(playerTank.y);
for (int r = 0; r < shotRange; r++) {
bx += (int)round(cos(rad));
by -= (int)round(sin(rad));
for (size_t i = 0; i < enemies.size(); i++) {
if (enemies[i].x == bx && enemies[i].y == by) { hitIndex = i; break; }
}
if (hitIndex != -1) break;
}
if (hitIndex != -1) {
int damage = 30 + rand() % 11; // 30-40 damage.
enemies[hitIndex].health -= damage;
std::cout << "Machine gun hit enemy at (" << enemies[hitIndex].x << "," << enemies[hitIndex].y << ") for " << damage << " damage.\n";
if (enemies[hitIndex].health <= 0) { enemies.erase(enemies.begin() + hitIndex); score += 100; std::cout << "Enemy destroyed!\n"; }
} else {
std::cout << "Machine gun missed.\n";
}
}
}
else if (cmd == 'r') {
cannonAmmo = 4;
machineGunAmmo = 20;
std::cout << "\nReloading all weapons...\n";
}
// Update tank position using simple physics.
float rad = degToRad(playerTank.angle);
playerTank.x += playerTank.speed * cos(rad);
playerTank.y -= playerTank.speed * sin(rad);
if (playerTank.x < 0) playerTank.x = 0;
if (playerTank.x >= MAP_WIDTH) playerTank.x = MAP_WIDTH - 1;
if (playerTank.y < 0) playerTank.y = 0;
if (playerTank.y >= MAP_HEIGHT) playerTank.y = MAP_HEIGHT - 1;
// Enemy actions: move enemies one cell toward the tank.
for (auto &enemy : enemies) {
if (enemy.x < (int)round(playerTank.x)) enemy.x++;
else if (enemy.x > (int)round(playerTank.x)) enemy.x--;
if (enemy.y < (int)round(playerTank.y)) enemy.y++;
else if (enemy.y > (int)round(playerTank.y)) enemy.y--;
// Enemy fires with 30% chance if in range.
if (rand() % 100 < 30) {
int baseDmg = 15 + rand() % 6; // 15-20 damage.
float dx = enemy.x - playerTank.x;
float dy = playerTank.y - enemy.y;
float enemyAngle = atan2(dy, dx) * 180.0f / M_PI;
if (enemyAngle < 0) enemyAngle += 360;
float diff = angleDiff(playerTank.angle, enemyAngle);
float multiplier = (diff < 45 ? 0.5f : (diff > 135 ? 1.5f : 1.0f));
int dmg = (int)(baseDmg * multiplier);
playerTank.health -= dmg;
std::cout << "An enemy fires at your tank for " << dmg << " damage.\n";
}
}
std::cout << "\nPress any key for next turn in this wave...";
_getch();
if (playerTank.health <= 0) break;
}
if (playerTank.health <= 0) break;
std::cout << "\nWave cleared! Press any key for next wave...";
_getch();
}
if (playerTank.health > 0)
std::cout << "\nAll enemy defenses destroyed! German Aden Offensive mission accomplished.\n";
else
std::cout << "\nYour Panther tank and crew were destroyed. Mission failed.\n";
}
// --------------------
// Main
// --------------------
int main() {
srand(static_cast<unsigned int>(time(0)));
std::cout << "Battleground 1 - Enhanced Edition\n";
std::cout << "Controls (Campaigns 1-4):\n Movement: w/a/s/d and diagonals (q, e, z, c)\n Shooting: i/j/k/l for up/left/down/right\n Grenade: g Reload: r\n";
std::cout << "\nSelect Campaign:\n1. D-Day\n2. Aden Offensive\n3. Berlin Attack\n4. German D-Day (Machine Gun Defense)\n5. German Aden Offensive (Panther Assault - Drive the Tank)\nEnter choice (1-5): ";
int choice;
std::cin >> choice;
if (choice >= 1 && choice <= 5) {
if (choice == 5) {
playCampaign5();
} else {
playCampaign(choice);
}
} else {
std::cout << "Invalid choice." << std::endl;
}
std::cout << "\nPress any key to exit.";
_getch();
return 0;
}