//Awesome_RTS //Copyright Tord Hjalt 2021- #include // for sleep etc. #include //för cin, cout #include //för getch #include //för string #include //för vector #include //for random shuffle vectors #include //för filer #include //för finjustering av cout layout: setw(n) #include //for threads #include using namespace std; #define SCREEN_WIDTH 70 // width of window #define SCREEN_HEIGHT 25 // height of window void DrawWorld(CHAR_INFO screenBuffer[], int a); void DrawWon(string Str, int X, int Y, WORD color); bool CheckInput(); //checks user input void HandleGameInput(CHAR_INFO screenBuffer[]); //on user key press void Eraser(CHAR_INFO screenBuffer[]); //clear screen bool Fight(int Armor); string sNamn; //för spelarens namn, till highscorelistan int Points = 0; //Declare function for highscore list: void fHighscores(void); void Intro() { PlaySound("mixkit-heavy-rain-and-thunder-ambience-1259.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void MenuSound() { PlaySound("mixkit-opening-software-interface-2578.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void NukeBlast() { //PlaySound("mixkit-epic-impact-afar-explosion-2782.wav", NULL, SND_FILENAME|SND_LOOP|SND_ASYNC); PlaySound("mixkit-epic-impact-afar-explosion-2782.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void E_bombs() { PlaySound("mixkit-bomb-distant-explotion-2772.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void Hit_Base() { PlaySound("mixkit-shatter-shot-explosion-1693.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void Hit_Tank() { PlaySound("mixkit-blast-hit-with-echo-2186.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void Artillery() { //PlaySound("mixkit-fast-game-explosion-1688.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); //wierd sound, change it PlaySound("mixkit-short-explosion-1694.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void Plant_Build() { PlaySound("mixkit-falling-hit-on-gravel-756.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void Hit_E() { PlaySound("mixkit-distant-war-explosions-1696.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void Nuke_Ready() { PlaySound("mixkit-synth-mechanical-notification-or-alert-650.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void Spying() { PlaySound("mixkit-alert-bells-echo-765.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void Won() { PlaySound("mixkit-trumpet-fanfare-2293.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } void Lost() { PlaySound("mixkit-cinematic-orchestra-horror-chaos-640.wav", NULL, SND_FILENAME|NULL|SND_ASYNC); } int DaKeyCode = 0; //holds user key id int bKeyDown = 0; // key downpresskey COORD *pUrban = 0; //global coord pointer bool Menumode = false; bool Ray = false; bool Nuke = false; bool Target = false; bool Nuked = false; bool Fact = false; bool NukeAuthorized = false; bool Tsend = false; bool North = false; bool South = false; bool East = false; bool West = false; int Tselect = 0; int Artselect = 1; bool Area1 = true; bool Area2 = false; bool Area3 = false; bool Area4 = false; bool Area5 = false; bool Art = false; int BMax = 0; int Walls = 0; //class definition: class Commander { private: // Private attributes //building integrity int Integrity_1 = 10; int Integrity_2 = 10; int Integrity_3 = 10; int Integrity_4 = 10; int Integrity_5 = 10; int Integrity_6 = 10; int Integrity_7 = 10; int Integrity_8 = 10; int Integrity_9 = 10; int Integrity_10 = 10; COORD Build_1 = {0,0}; //if 0,0 -> no house there COORD Build_2 = {0,0}; COORD Build_3 = {0,0}; COORD Build_4 = {0,0}; COORD Build_5 = {0,0}; COORD Build_6 = {0,0}; COORD Build_7 = {0,0}; COORD Build_8 = {0,0}; COORD Build_9 = {0,0}; COORD Build_10 = {0,0}; COORD DesignatedTarget = {1,24}; int Type_1 = 1; int Type_2 = 1; int Type_3 = 1; int Type_4 = 1; int Type_5 = 1; int Type_6 = 1; int Type_7 = 1; int Type_8 = 1; int Type_9 = 1; int Type_10 = 1; COORD Tank1 = {0,16}; COORD Tank2 = {0,16}; COORD Tank3 = {0,16}; COORD Tank4 = {0,16}; COORD Tank5 = {0,16}; COORD Tank6 = {0,16}; COORD Tank7 = {0,16}; COORD Tank8 = {0,16}; COORD Tank9 = {0,16}; COORD Tank10 = {0,16}; bool Tank1Lives = true; bool Tank2Lives = true; bool Tank3Lives = true; bool Tank4Lives = true; bool Tank5Lives = true; bool Tank6Lives = true; bool Tank7Lives = true; bool Tank8Lives = true; bool Tank9Lives = true; bool Tank10Lives = true; public: // Setters void HitMe(int h) { //dead if e.g. Integrity 1-10 < 0 switch(h) //use on Es also instead of vector { case 1: Integrity_1 = 0;break; case 2: Integrity_2 = 0;;break; case 3: Integrity_3 = 0;;break; case 4: Integrity_4 = 0;;break; case 5: Integrity_5 = 0;;break; case 6: Integrity_6 = 0;;break; case 7: Integrity_7 = 0;;break; case 8: Integrity_8 = 0;;break; case 9: Integrity_9 = 0;;break; case 10: Integrity_10 = 0;;break; default: cout << "default hitme" << endl; } } void Plant(int r, COORD Set, int Btype) //use on Es also, { switch(r) { case 1: {Build_1 = Set; Type_1 = Btype; }break; case 2: {Build_2 = Set; Type_2 = Btype; }break; case 3: {Build_3 = Set; Type_3 = Btype; }break; case 4: {Build_4 = Set; Type_4 = Btype; }break; case 5: {Build_5 = Set; Type_5 = Btype; }break; case 6: {Build_6 = Set; Type_6 = Btype; }break; case 7: {Build_7 = Set; Type_7 = Btype; }break; case 8: {Build_8 = Set; Type_8 = Btype; }break; case 9: {Build_9 = Set; Type_9 = Btype; }break; case 10: {Build_10 = Set; Type_10 = Btype; }break; } } void SetTarget(COORD Here) { DesignatedTarget = Here; } void TankMoves(int t, COORD SetT) { switch(t) { case 1: { Tank1 = SetT; }break; case 2: { Tank2 = SetT; }break; case 3: { Tank3 = SetT; }break; case 4: { Tank4 = SetT; }break; case 5: { Tank5 = SetT; }break; case 6: { Tank6 = SetT; }break; case 7: { Tank7 = SetT; }break; case 8: { Tank8 = SetT; }break; case 9: { Tank9 = SetT; }break; case 10: { Tank10 = SetT; }break; } } void setTankKill(int k) { switch(k) { case 1: { Tank1Lives = false; }break; //Tank 1 is killed case 2: { Tank2Lives = false; }break; case 3: { Tank3Lives = false; }break; case 4: { Tank4Lives = false; }break; case 5: { Tank5Lives = false; }break; case 6: { Tank6Lives = false; }break; case 7: { Tank7Lives = false; }break; case 8: { Tank8Lives = false; }break; case 9: { Tank9Lives = false; }break; case 10: { Tank10Lives = false; }break; } } // Getters int getIntegrity(int x) { switch(x) { case 1: return Integrity_1;break; case 2: return Integrity_2;break; case 3: return Integrity_3;break; case 4: return Integrity_4;break; case 5: return Integrity_5;break; case 6: return Integrity_6;break; case 7: return Integrity_7;break; case 8: return Integrity_8;break; case 9: return Integrity_9;break; case 10: return Integrity_10;break; default: {cout << "default getArmor" << " x: " << x << endl; } break; } } COORD GetCoord(int r) { switch(r) { case 1: return Build_1;break; case 2: return Build_2;break; case 3: return Build_3;break; case 4: return Build_4;break; case 5: return Build_5;break; case 6: return Build_6;break; case 7: return Build_7;break; case 8: return Build_8;break; case 9: return Build_9;break; case 10: return Build_10;break; default: cout << "default getCoord" << endl;break; } } int GetType(int t) { switch(t) { case 1: return Type_1;break; case 2: return Type_2;break; case 3: return Type_3;break; case 4: return Type_4;break; case 5: return Type_5;break; case 6: return Type_6;break; case 7: return Type_7;break; case 8: return Type_8;break; case 9: return Type_9;break; case 10: return Type_10;break; default: cout << "default getType" << endl;break; } } COORD GetTarget(void) { return DesignatedTarget; } COORD GetT_Coord(int tc) { switch(tc) { case 1: return Tank1;break; case 2: return Tank2;break; case 3: return Tank3;break; case 4: return Tank4;break; case 5: return Tank5;break; case 6: return Tank6;break; case 7: return Tank7;break; case 8: return Tank8;break; case 9: return Tank9;break; case 10: return Tank10;break; default: cout << "default getT_Coord" << endl;break; } } bool IsTankAlive(int q) { switch(q) { case 1: return Tank1Lives;break; case 2: return Tank2Lives;break; case 3: return Tank3Lives;break; case 4: return Tank4Lives;break; case 5: return Tank5Lives;break; case 6: return Tank6Lives;break; case 7: return Tank7Lives;break; case 8: return Tank8Lives;break; case 9: return Tank9Lives;break; case 10: return Tank10Lives;break; default: cout << "default istankalive" << endl;break; } } }; //declare two objects of the class: Commander Friend; Commander Enemy; int iChose = 6; // ? symbol for start screen int Gold = 400; bool Spy = false; ///////////////////////////////////////////////////////////////////////////////////////// /////////////// M A I N //////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// int main() { CHAR_INFO screenBuffer[SCREEN_WIDTH * SCREEN_HEIGHT] = {0}; COORD bufferSize = {SCREEN_WIDTH , SCREEN_HEIGHT}; COORD cReset = {1,24}; pUrban = &cReset; int NukeTime1 = 0; int NukeTime2 = 0; int NukeElapsed = 0; int Nuked1 = 0; //Nuke afterfader int Nuked2 = 0; int BeenNukedElapsed = 0; int FT_Time1 = 0; //Friendly Tank spawns int FT_Time2 = 0; int FT_Elapsed = 0; int FT_Time1b = 0; //Friendly Tank moves int FT_Time2b = 0; int FT_Elapsedb = 0; int GoldTime1 = 0; //Harvesting Gold timer int GoldTime2 = 0; int GoldElapsed = 0; int BombTime1 = 0; //E bombs home base int BombTime2 = 0; int BombElapsed = 0; int ArtTime1 = 0; //Artillery shots at enemy int ArtTime2 = 0; int ArtElapsed = 0; int TotalTime1 = 0; //time played, for points int TotalTime2 = 0; int TotalElapsed = 0; bool NCharge = false; int Power = 0; //bool Fact = false; COORD TLaunch = {8,14};//or crashes when have bugs? bool TLaunchOnce = true; int AllTanks = 0; COORD daE; int Strength = 0; string sWhat; int Bling = 0; int ArtXa = 0; int ArtYa = 0; vectorvXbomb; vectorvYbomb; vectorvXArt1; vectorvYArt1; vectorvXArt2; vectorvYArt2; vectorvXArt3; vectorvYArt3; vectorvXArt4; vectorvYArt4; vectorvXArt5; vectorvYArt5; vXbomb.push_back(14); vXbomb.push_back(11); vXbomb.push_back(8); vXbomb.push_back(5); vXbomb.push_back(2); vXbomb.push_back(15); vXbomb.push_back(10); vXbomb.push_back(7); vXbomb.push_back(4); vXbomb.push_back(1); vXbomb.push_back(13); vXbomb.push_back(9); vXbomb.push_back(6); vXbomb.push_back(3); vXbomb.push_back(0); vXbomb.push_back(12); vYbomb.push_back(15); vYbomb.push_back(16); vYbomb.push_back(18); vYbomb.push_back(20); vYbomb.push_back(22); vYbomb.push_back(24); vYbomb.push_back(17); vYbomb.push_back(19); vYbomb.push_back(21); vYbomb.push_back(23); for(int ax = 16; ax < 41; ax++) { vXArt1.push_back(ax); } for(int ay = 1; ay < 15; ay++) { vYArt1.push_back(ay); } for(int ax2 = 42; ax2 < 68; ax2++) { vXArt2.push_back(ax2); } for(int ay2 = 1; ay2 < 15; ay2++) { vYArt2.push_back(ay2); } for(int ax3 = 16; ax3 < 41; ax3++) { vXArt3.push_back(ax3); } for(int ay3 = 15; ay3 < 24; ay3++) { vYArt3.push_back(ay3); } for(int ax4 = 41; ax4 < 68; ax4++) { vXArt4.push_back(ax4); } for(int ay4 = 15; ay4 < 24; ay4++) { vYArt4.push_back(ay4); } for(int ax5 = 1; ax5 < 16; ax5++) { vXArt5.push_back(ax5); } for(int ay5 = 1; ay5 < 15; ay5++) { vYArt5.push_back(ay5); } bool Spied = false; //system("color E2");//ljusgul //system("color 8");//mörkgrå //system("color A2");//grön //svart 'fog of war': for (int p = 0; p < bufferSize.X; p++) { for (int q = 0; q < bufferSize.Y; q++) { screenBuffer[p + q * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[p + q * SCREEN_WIDTH].Attributes = 0; } } //but home base area is 'visible': for (int p2 = 0; p2 < 15; p2++) { for (int q2 = 15; q2 < SCREEN_HEIGHT; q2++) { screenBuffer[p2 + q2 * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[p2 + q2 * SCREEN_WIDTH].Attributes = BACKGROUND_GREEN; } } //coordinates: char charco; for (int c = 1; c < SCREEN_WIDTH; c++) { switch(c) { case 1: { charco = '1'; screenBuffer[c + 0 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[c + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: case 62: case 63: case 64: case 65: case 66: case 67: case 68: case 69: { screenBuffer[c + 0 * SCREEN_WIDTH].Char.AsciiChar = '.'; screenBuffer[c + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 10: { charco = '1'; screenBuffer[c + 0 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[c + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Char.AsciiChar = '0'; screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 20: { charco = '2'; screenBuffer[c + 0 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[c + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Char.AsciiChar = '0'; screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 30: { charco = '3'; screenBuffer[c + 0 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[c + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Char.AsciiChar = '0'; screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 40: { charco = '4'; screenBuffer[c + 0 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[c + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Char.AsciiChar = '0'; screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 50: { charco = '5'; screenBuffer[c + 0 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[c + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Char.AsciiChar = '0'; screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 60: { charco = '6'; screenBuffer[c + 0 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[c + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Char.AsciiChar = '0'; screenBuffer[(c+1) + 0 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; //default: charco = '.'; break; } }//end for c for (int c2 = 1; c2 < SCREEN_HEIGHT; c2++) { switch(c2) { case 1: { charco = '1'; screenBuffer[68 + c2 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[68 + c2 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 10: { charco = '1'; screenBuffer[68 + c2 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[68 + c2 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[69 + c2 * SCREEN_WIDTH].Char.AsciiChar = '0'; screenBuffer[69 + c2 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 20: { charco = '2'; screenBuffer[68 + c2 * SCREEN_WIDTH].Char.AsciiChar = charco; screenBuffer[68 + c2 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[69 + c2 * SCREEN_WIDTH].Char.AsciiChar = '0'; screenBuffer[69 + c2 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 21: case 22: case 23: case 24: { screenBuffer[69 + c2 * SCREEN_WIDTH].Char.AsciiChar = '.'; screenBuffer[69 + c2 * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } break; } } //put enemy base at random position out of 6: srand(GetTickCount()); //'seeding' the rand function with tick count int X = ((rand() % 6) + 1); //(1-6) COORD Ebase1, Ebase2, Ebase3, Ebase4, Ebase5, Ebase6, Ebase7, Ebase8; //1-60, 1-15, 16-60, 16-23: switch(X) { case 1: { Ebase1.X = 55; Ebase1.Y = 21; Ebase2.X = 5; Ebase2.Y = 13; Ebase3.X = 7; Ebase3.Y = 11; Ebase4.X = 9; Ebase4.Y = 3; Ebase5.X = 3; Ebase5.Y = 5; Ebase6.X = 30; Ebase6.Y = 18; Ebase7.X = 7; Ebase7.Y = 5; Ebase8.X = 19; Ebase8.Y = 15; } break; case 2: { Ebase1.X = 10; Ebase1.Y = 2; Ebase2.X = 12; Ebase2.Y = 9; Ebase3.X = 12; Ebase3.Y = 3; Ebase4.X = 16; Ebase4.Y = 3; Ebase5.X = 18; Ebase5.Y = 5; Ebase6.X = 19; Ebase6.Y = 5; Ebase7.X = 21; Ebase7.Y = 15; Ebase8.X = 23; Ebase8.Y = 5; } break; case 3: { Ebase1.X = 25; Ebase1.Y = 3; Ebase2.X = 27; Ebase2.Y = 20; Ebase3.X = 49; Ebase3.Y = 16; Ebase4.X = 31; Ebase4.Y = 3; Ebase5.X = 33; Ebase5.Y = 7; Ebase6.X = 37; Ebase6.Y = 8; Ebase7.X = 39; Ebase7.Y = 5; Ebase8.X = 45; Ebase8.Y = 7; } break; case 4: { Ebase1.X = 53; Ebase1.Y = 3; Ebase2.X = 55; Ebase2.Y = 22; Ebase3.X = 5; Ebase3.Y = 3; Ebase4.X = 59; Ebase4.Y = 9; Ebase5.X = 33; Ebase5.Y = 15; Ebase6.X = 25; Ebase6.Y = 9; Ebase7.X = 67; Ebase7.Y = 8; Ebase8.X = 49; Ebase8.Y = 12; } break; case 5: { Ebase1.X = 4; Ebase1.Y = 4; Ebase2.X = 56; Ebase2.Y = 23; Ebase3.X = 18; Ebase3.Y = 2; Ebase4.X = 59; Ebase4.Y = 21; Ebase5.X = 53; Ebase5.Y = 17; Ebase6.X = 60; Ebase6.Y = 19; Ebase7.X = 47; Ebase7.Y = 18; Ebase8.X = 39; Ebase8.Y = 18; } break; case 6: { Ebase1.X = 53; Ebase1.Y = 3; Ebase2.X = 5; Ebase2.Y = 13; Ebase3.X = 57; Ebase3.Y = 23; Ebase4.X = 59; Ebase4.Y = 13; Ebase5.X = 3; Ebase5.Y = 9; Ebase6.X = 47; Ebase6.Y = 19; Ebase7.X = 7; Ebase7.Y = 3; Ebase8.X = 9; Ebase8.Y = 12; } break; default: cout << "default sw x???" << endl; break; } Enemy.Plant(1,Ebase1,1); Enemy.Plant(2,Ebase2,1); Enemy.Plant(3,Ebase3,1); Enemy.Plant(4,Ebase4,1); Enemy.Plant(5,Ebase5,1); Enemy.Plant(6,Ebase6,1); Enemy.Plant(7,Ebase7,1); Enemy.Plant(8,Ebase8,1); //not using Buildings 9 and 10, so 'kill' them: Enemy.HitMe(9); Enemy.HitMe(10); DrawWorld(screenBuffer, iChose); DrawWon("Gold ",70,18, FOREGROUND_RED | FOREGROUND_INTENSITY); cout << Gold; DrawWon("E bases:",70,8, FOREGROUND_RED | FOREGROUND_INTENSITY); NukeTime1 = GetTickCount(); FT_Time1 = GetTickCount(); FT_Time1b = GetTickCount(); GoldTime1 = GetTickCount(); BombTime1 = GetTickCount(); ArtTime1 = GetTickCount(); TotalTime1 = GetTickCount(); int HX = 0; int HY = 0; int HX2 = 0; int HY2 = 0; int Nux1 = 0; int Nux2 = 0; int Nuy1 = 0; int Nuy2 = 0; bool WillFade = false; //intro: std::thread tIn(Intro); tIn.join(); //string sStart; system("color 8");//mörkgrå DrawWon("Welcome, Commander. ",2,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("The situation is urgent. The Aliens have established",2,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("several bases nearby. We also fear they will begin",2,7, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("satellite bombing of our staging area soon.",2,8, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("You must establish a base, and destroy all enemy bases.",2,9, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",2,10, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Your base will produce everything you need,",2,11, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("including nuclear bombs, tanks, artillery.",2,12, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Beware of the edges of this territory, scouts have",2,13, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("mysteriously vanished there. ",2,14, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",2,15, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Good luck! The world is counting on you now... ",2,16, FOREGROUND_GREEN| FOREGROUND_INTENSITY); DrawWon(" ",2,17, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ***help screen: tab key*** ",2,18, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ***Copyright Tord Hjalt 2021-*** ",2,19, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ***Sound effects by mixkit*** ",2,20, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",2,20, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Enter your secret code name to continue.",2,21, FOREGROUND_GREEN | FOREGROUND_INTENSITY); cin >> sNamn; //game loop: //////////////////// G A M E L O O P ////////////////////////////// //////////////////// G A M E L O O P ////////////////////////////// //////////////////// G A M E L O O P ////////////////////////////// //////////////////// G A M E L O O P ////////////////////////////// while(1) { if(CheckInput()) //if user pressed a key: HandleGameInput(screenBuffer); //nuke recharge sign: if((Power > 5)&&(Fact)) { NukeTime2 = GetTickCount(); NukeElapsed = NukeTime2 - NukeTime1; if(NukeElapsed > 60000)//5 sek during dev, for real: 4 min? 8 min? { //NukeTime1 = GetTickCount();//reset //NukeElapsed = 0;//reset NCharge = true; DrawWon(" ",70,1, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Nuke",70,0, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("ready.",70,1, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",0,0, FOREGROUND_GREEN | FOREGROUND_INTENSITY); //move cursor } else { DrawWon("Nuke",70,0, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("charging.",70,1, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon(" ",0,0, FOREGROUND_GREEN | FOREGROUND_INTENSITY); //move cursor } } DrawWorld(screenBuffer, iChose); if(Menumode) { system("color 8");//mörkgrå Target = false; //resets targetting with arrows cReset = {1,24}; //reset arrows std::thread tMenu(MenuSound); tMenu.join(); DrawWon("BUILD MENU ",8,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("****************************",8,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Power plant (P) 5 gold ",8,7, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Harvester (H) 20 gold ",8,8, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Wall (W) 300 gold ",8,9, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Artillery (A) 500 gold ",8,10, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Factory (F) 150 gold ",8,11, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Spy (S) (no gold/all tanks dead) ",8,12, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Nuke (N) (Factory and > 5 power) ",8,13, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Back to game (B) ",8,14, FOREGROUND_GREEN| FOREGROUND_INTENSITY); cin >> sWhat; if(((sWhat == "P") || (sWhat == "p")) && (BMax < 10) && (Gold > 4)) { screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Char.AsciiChar = 'P'; screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white iChose = 1; Power = Power + 5; Gold = Gold - 5; } else if(((sWhat == "H") || (sWhat == "h")) && (BMax < 10) &&(Gold > 19)) { screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Char.AsciiChar = 'H'; screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY; Bling++; iChose = 2; Power--; Gold = Gold - 20; } else if(((sWhat == "W") || (sWhat == "w")) && (BMax < 10) &&(Gold > 299)) { screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Char.AsciiChar = 'W'; screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Attributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; iChose = 3; Gold = Gold - 300; } else if(((sWhat == "A") || (sWhat == "a")) && (BMax < 10) && (Gold > 499) && (Art == false)) //can only have one at a time { screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Char.AsciiChar = 'A'; screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; iChose = 4; Power--; Gold = Gold - 500; Art = true; } else if(((sWhat == "F") || (sWhat == "f")) && (BMax < 10) &&(Gold > 149)) { screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Char.AsciiChar = 'F'; screenBuffer[cReset.X + cReset.Y * SCREEN_WIDTH].Attributes = FOREGROUND_BLUE | FOREGROUND_INTENSITY; iChose = 5; Fact = true; Power--; Gold = Gold - 150; } else if((sWhat == "S") || (sWhat == "s")) { iChose = 6; int tA = 0; for(int t = 1; t < 11; t++) { if(Friend.IsTankAlive(t)) tA++; } if((tA < 1) || (Gold < 1)) //all tanks are dead or have no gold { Spy = true; DrawWon("Spying..",70,23, FOREGROUND_GREEN | FOREGROUND_INTENSITY); std::thread tSpy(Spying); tSpy.join(); Gold = 200; Power = 7; Bling = 1; for(int se = 1; se < 9; se++) { int Etest = Enemy.getIntegrity(se); if(Etest > 0) { COORD SEb = Enemy.GetCoord(se); screenBuffer[SEb.X + SEb.Y * SCREEN_WIDTH].Char.AsciiChar = 'E'; screenBuffer[SEb.X + SEb.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; } } DrawWorld(screenBuffer, 6); Sleep(4000); }//end if tanks dead or no gold } else if((sWhat == "N") || (sWhat == "n")) { if((Power > 5)&&(Fact)&&(NCharge)) { //ask for nuke coords: int cX = 0; int cY = 0; DrawWon(" ",70,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); cout << "X?" << endl; DrawWon(" ",70,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); cin >> cX; if((!cin)||(cX < 0) || (cX > 68)) { cin.clear(); //suddar cin cin.ignore(10000, '\n'); //suddar 10 000 tecken i cin plus nyrad-tecknet cX = 25; } DrawWon(" ",70,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",70,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",70,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",70,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",70,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); cout << "Y?" << endl; DrawWon(" ",70,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); cin >> cY; DrawWon(" ",70,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",70,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); if((!cin)||(cY < 0)||(cY > 23)) { cin.clear(); //suddar cin cin.ignore(10000, '\n'); //suddar 10 000 tecken i cin plus nyrad-tecknet cY = 8; } COORD Nhit = {cX, cY }; Friend.SetTarget(Nhit); //executes when press Esc button in Handle Input Nuked = false; //reset from previous Nuke run NCharge = false; NukeAuthorized = true; //enables esc button } //end if power fact ncharge else { DrawWon(" ",70,0, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("No",70,0, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("nukes.",70,1, FOREGROUND_RED | FOREGROUND_INTENSITY); } } //end if N else if((sWhat == "B") || (sWhat == "b")) { //system("color A2");//grön, reset Menumode = false; //reset } else { //system("color A2");//grön, reset Menumode = false; //reset } //and always reset afterwards: //system("color A2");//grön, reset Menumode = false; //reset }//end menumode //Nuke: if(Nuke) //add timer and priviledge checker (need Factory and a lot of power from several power plants { COORD Hit = Friend.GetTarget();//set by Nuke in handle input Nuke = false; //reset after a timer, so can add fading effects: Nuked = true; //to tell drawworld not to overwrite with H at center. NukeAuthorized = false; //reset esc button block WillFade = true; Nuked1 = GetTickCount(); //after nuke fader NukeTime1 = GetTickCount();//reset NukeElapsed = 0;//reset std::thread tNu(NukeBlast); tNu.join(); //Sleep(2000); DrawWon("N ",70,0, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("Nuke",70,0, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("charging.",70,1, FOREGROUND_RED | FOREGROUND_INTENSITY); screenBuffer[Hit.X + Hit.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[Hit.X + Hit.Y * SCREEN_WIDTH].Attributes = BACKGROUND_RED | BACKGROUND_INTENSITY; //determine distance to borders and fill it out, but max 5 pixels:... int testR = SCREEN_WIDTH - Hit.X; int testL = Hit.X - 0; //duh.. int testT = Hit.Y - 0; // duh.. int testB = SCREEN_HEIGHT - Hit.Y; switch(testR) { case 0: HX = Hit.X; break; case 1: HX = Hit.X + 1; break; case 2: HX = Hit.X + 2; break; case 3: HX = Hit.X + 3; break; case 4: HX = Hit.X + 4; break; case 5: HX = Hit.X + 5; break; default: HX = Hit.X + 5; break; }//end sw testR switch(testL) { case 0: HX2 = Hit.X; break; case 1: HX2 = Hit.X - 1; break; case 2: HX2 = Hit.X - 2; break; case 3: HX2 = Hit.X - 3; break; case 4: HX2 = Hit.X - 4; break; default: HX2 = Hit.X - 5; break; //5 and higher }//end sw testL switch(testT) { case 0: HY2 = Hit.Y; break; case 1: HY2 = Hit.Y - 1; break; case 2: HY2 = Hit.Y - 2; break; case 3: HY2 = Hit.Y - 3; break; case 4: HY2 = Hit.Y - 4; break; default: HY2 = Hit.Y - 5; break;//5 and higher }//end sw testT switch(testB) { case 0: HY = Hit.Y; break; case 1: HY = Hit.Y + 1; break; case 2: HY = Hit.Y + 2; break; case 3: HY = Hit.Y + 3; break; case 4: HY = Hit.Y + 4; break; default: HY = Hit.Y + 5; break;//5 and higher }//end sw testB //save for fader below: Nux1 = HX; Nux2 = HX2; Nuy1 = HY; Nuy2 = HY2; for(int x1 = HX2; x1 < (HX+1); x1++ ) { for(int y1 = HY2; y1 < (HY+1); y1++) { screenBuffer[x1 + y1 * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[x1 + y1 * SCREEN_WIDTH].Attributes = BACKGROUND_RED | BACKGROUND_INTENSITY; //loop through and destroy hit enemy buildings: COORD cVE; for(int vE = 1; vE < 9; vE++)//have only 8 E bases { //cVE = vEbases[vE]; cVE = Enemy.GetCoord(vE); if((cVE.X)==(x1)&&(cVE.Y)==(y1)) { Enemy.HitMe(vE); /* blocks nuke sound, which is cooler.. std::thread tKillN(Hit_E); tKillN.join(); */ } } } } //testing E destruction: //int Test = vEbases.size(); int Test = Enemy.getIntegrity(1) + Enemy.getIntegrity(2) + Enemy.getIntegrity(3) + Enemy.getIntegrity(4) + Enemy.getIntegrity(5) + Enemy.getIntegrity(6) + Enemy.getIntegrity(7) + Enemy.getIntegrity(8); //DrawWon("E bases:",70,8, FOREGROUND_RED | FOREGROUND_INTENSITY); //moved to main to stop blinking DrawWon(" :",70,9, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon(" ",70,10, FOREGROUND_RED | FOREGROUND_INTENSITY); Test = Test/10; //display building counts, not integrity value sum cout << Test; //was: 80 if all E bases intact, 0 if all dead DrawWon(" ",70,11, FOREGROUND_RED | FOREGROUND_INTENSITY); }//end if nuke if(WillFade) { Nuked2 = GetTickCount(); BeenNukedElapsed = Nuked2 - Nuked1; if(BeenNukedElapsed > 400) { for(int nx1 = Nux2; nx1 < (Nux1+1); nx1++ ) { for(int ny1 = Nuy2; ny1 < (Nuy1+1); ny1++) { screenBuffer[nx1 + ny1 * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[nx1 + ny1 * SCREEN_WIDTH].Attributes = BACKGROUND_RED; } } } //end if bennnukedelapsd 200 Nuked2 = GetTickCount(); BeenNukedElapsed = Nuked2 - Nuked1; if(BeenNukedElapsed > 800) { WillFade = false; //resets BeenNukedElapsed = 0; Nuked2 = 0; Nuked1 = 0; for(int nx1b = Nux2; nx1b < (Nux1+1); nx1b++ ) { for(int ny1b = Nuy2; ny1b < (Nuy1+1); ny1b++) { //can't leave completely black, need to remember where nuked previously.. screenBuffer[nx1b + ny1b * SCREEN_WIDTH].Char.AsciiChar = '.'; screenBuffer[nx1b + ny1b * SCREEN_WIDTH].Attributes = FOREGROUND_BLUE; } } } //end if bennnukedelapsd 400 } //end if willfade ////////////////////// LAUNCH TANKS /////////////////////////////// ////////////////////// LAUNCH TANKS /////////////////////////////// ////////////////////// LAUNCH TANKS /////////////////////////////// if((Power > 5)&&(Fact)&&(TLaunchOnce)) //enough power, and have a factory, and run this only once { for(int Fc = 1; Fc < 11; Fc++) { int Fq = Friend.GetType(Fc); if(Fq == 5) { TLaunch = Friend.GetCoord(Fc); //GetCoord will remember this later! TLaunchOnce = false; //only do this once } } }//end if power, fact, TlaunchOnce FT_Time2 = GetTickCount(); FT_Elapsed = FT_Time2 - FT_Time1; if((TLaunchOnce == false) && (FT_Elapsed > 8000))//later: change timer to 2 min? { FT_Time1 = GetTickCount();//reset spawn timer FT_Elapsed = 0; //reset }//end if Tlaunchonce, TElapsed FT_Time2b = GetTickCount(); FT_Elapsedb = FT_Time2b - FT_Time1b; if((FT_Elapsedb > 1000)&&(Tsend))//delay // if(Tsend)//delay below, before each tank launch { //Tsend = false; //reset : step-by-step for all.. FT_Time1b = GetTickCount();//reset spawn timer FT_Elapsedb = 0; //reset int iArmy = 0; if((Power < 10)&&(Fact)) {iArmy = 5; Friend.setTankKill(5); Friend.setTankKill(6); Friend.setTankKill(7); Friend.setTankKill(8); Friend.setTankKill(9); Friend.setTankKill(10);} //4 tanks else if((Power > 9)&&(Power < 20) &&(Fact)) { iArmy = 8; Friend.setTankKill(8); Friend.setTankKill(9); Friend.setTankKill(10); } //7 tanks else if ((Power > 19)&&(Fact)) iArmy = 11; //max: 10 tanks for(int Ta = 1; Ta < iArmy; Ta++) { COORD Est; Est = Friend.GetT_Coord(Ta); //first step: //if(Est.X == 1) //BUG: this seems to launch all at the same time...want 2 sec delay here if(Est.X == 0) { Sleep(1); srand(GetTickCount()); //'seeding' the rand function with tick count int iRanT1 = ((rand() % 4) + 1); // 1-4? up/up-left/up-right/right //test: // iRanT1 = 1; switch(iRanT1) { case 1: { //no need for safe border limits as start from home zone screenBuffer[TLaunch.X + (TLaunch.Y -1) * SCREEN_WIDTH].Char.AsciiChar = 'T'; screenBuffer[TLaunch.X + (TLaunch.Y -1) * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY; /* do not erase Factory! screenBuffer[test.X + test.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[test.X + test.Y * SCREEN_WIDTH].Attributes = 0; */ Est.X = TLaunch.X; Est.Y = (TLaunch.Y - 1);//first step stored for next step, locally, Friend.TankMoves(Ta,Est);//store this tanks current pos in the Friend object }break; case 2: { //no need for safe border limits as start from home zone screenBuffer[(TLaunch.X - 1) + (TLaunch.Y -1) * SCREEN_WIDTH].Char.AsciiChar = 'T'; screenBuffer[(TLaunch.X - 1) + (TLaunch.Y -1) * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN |FOREGROUND_INTENSITY; /* do not erase Factory! */ Est.X = (TLaunch.X -1) ; Est.Y = (TLaunch.Y - 1);//first step stored for next step, locally, Friend.TankMoves(Ta,Est);//store this tanks current pos in the Friend object }break; case 3: { //no need for safe border limits as start from home zone screenBuffer[(TLaunch.X + 1) + (TLaunch.Y -1) * SCREEN_WIDTH].Char.AsciiChar = 'T'; screenBuffer[(TLaunch.X + 1) + (TLaunch.Y -1) * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY; /* do not erase Factory! */ Est.X = (TLaunch.X + 1) ; Est.Y = (TLaunch.Y + 1);//first step stored for next step, locally, Friend.TankMoves(Ta,Est);//store this tanks current pos in the Friend object }break; case 4: { //no need for safe border limits as start from home zone screenBuffer[(TLaunch.X - 1) + (TLaunch.Y + 1) * SCREEN_WIDTH].Char.AsciiChar = 'T'; screenBuffer[(TLaunch.X - 1) + (TLaunch.Y + 1) * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY; /* do not erase Factory! */ Est.X = (TLaunch.X -1) ; Est.Y = (TLaunch.Y + 1);//first step stored for next step, locally, Friend.TankMoves(Ta,Est);//store this tanks current pos in the Friend object }break; default: { cout << "def_1" << endl; Sleep(2000), Beep(700,800); } break; }//end sw irant1 }//end if Est.X == 1 //else if(FT_Elapsedb > 1000) //all next steps: else { //FT_Time1b = GetTickCount();//reset spawn timer //FT_Elapsedb = 0; //reset Sleep(1); srand(GetTickCount()); //'seeding' the rand function with tick count int iRanT1b = ((rand() % 4) + 1); // 1-4? up/up-left/up-right/right //test: //iRanT1b = 1; // if((North)||(South)||(East)||(West) && (FT_Elapsedb > 2000))//pushed space bar if((North)||(South)||(East)||(West))//pushed space bar iRanT1b = 5; //TESTING: // iRanT1b = 4; //WTF? case 4 re-spawns repeatedly after all hit wall??? switch(iRanT1b)//all next steps { case 1: { COORD old = Est; bool LiveTank = Friend.IsTankAlive(Ta); //is current tank alive? //beware of borders! if(((Est.X +1)< SCREEN_WIDTH) && ((Est.Y -1) > 0)&& (LiveTank) ) { //dead tanks don't move... Est.X++; Est.Y--; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Char.AsciiChar = 'T'; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY; screenBuffer[old.X + old.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[old.X + old.Y * SCREEN_WIDTH].Attributes = BACKGROUND_GREEN; Friend.TankMoves(Ta,Est); } else //disappears beyond border and dies... { screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Attributes = 0; Friend.setTankKill(Ta); } } break; //end case 1 sw iranT1b case 2: { COORD old = Est; bool LiveTank = Friend.IsTankAlive(Ta); //is current tank alive? //beware of borders! if(((Est.X +1)< SCREEN_WIDTH) && ((Est.Y +1) < SCREEN_HEIGHT) && (LiveTank) ) { Est.X++; Est.Y++; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Char.AsciiChar = 'T'; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY; screenBuffer[old.X + old.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[old.X + old.Y * SCREEN_WIDTH].Attributes = BACKGROUND_GREEN; Friend.TankMoves(Ta,Est); } else //disappears beyond border and dies... { screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Attributes = 0; Friend.setTankKill(Ta); } } break; //end case 2 sw iranT1b case 3: { COORD old = Est; bool LiveTank = Friend.IsTankAlive(Ta); //is current tank alive? //beware of borders! if(((Est.X +1)< SCREEN_WIDTH) && ((Est.Y -1) > 0) && (LiveTank) ) { //Est.X++; Est.Y++; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Char.AsciiChar = 'T'; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY; screenBuffer[old.X + old.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[old.X + old.Y * SCREEN_WIDTH].Attributes = BACKGROUND_GREEN; Friend.TankMoves(Ta,Est); } else //disappears beyond border and dies... { screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Attributes = 0; Friend.setTankKill(Ta); } } break; //end case 3 sw iranT1b case 4: { COORD old = Est; bool LiveTank = Friend.IsTankAlive(Ta); //is current tank alive? //beware of borders! if(((Est.X -1) > 0) && ((Est.Y -1) > 0) && (LiveTank) ) { Est.X--; Est.Y--; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Char.AsciiChar = 'T'; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY; screenBuffer[old.X + old.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[old.X + old.Y * SCREEN_WIDTH].Attributes = BACKGROUND_GREEN; Friend.TankMoves(Ta,Est); } else //disappears beyond border and dies.. { screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[Est.X + Est.Y * SCREEN_WIDTH].Attributes = 0; Friend.setTankKill(Ta); } } break; //end case 4 sw iranT1b case 5: //manual override from space bar { COORD old = Est; bool LiveTank = Friend.IsTankAlive(Ta); //is current tank alive? //beware of borders! if((((Est.X +1)< SCREEN_WIDTH) && ((Est.Y -1) > 0)&&((Est.X -1)>0) &&((Est.Y+1) 0 ////////// FIGHTS /////////////////////////////// ////////// FIGHTS /////////////////////////////// ////////// FIGHTS /////////////////////////////// //collision detection Friend Tank vs E building: //loop through all Tank coords and see if a Tank is close to an enemy building (E): //but only after started deploying tanks, or get out-of-frame screenbuffer runtime errors! if(TLaunchOnce == false) //have Factory and have started launching tanks { COORD Nakt = {0,0}; COORD Efound = {0,0}; COORD NaktK = {0,0}; int T = 0; bool Encounter = false; int EE = 0; //new collision detection allows all Es to be hidden: for(int Tc = 1; Tc < 11; Tc++) //have max 10 tanks { if(Friend.IsTankAlive(Tc)) //not with a dead tank { for(int dE = 1; dE < 9; dE++) //have 8 Es { //not with dead E: if (Enemy.getIntegrity(dE) > 0) { Efound = Enemy.GetCoord(dE); //get current E coord Nakt = Friend.GetT_Coord(Tc); //get current tank coord if((Nakt.X == Efound.X)&&((Nakt.Y -1) == (Efound.Y))) //E above Tank { NaktK = Nakt; T = Tc; //remember Tank coords and number EE = dE; //remember E number! Encounter = true; //also remember this efound: daE = Efound; //briefly show it, or it may never be seen (if destroyed right after)!!: screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Char.AsciiChar = 'E'; screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(500); } else if((Nakt.X == Efound.X)&&((Nakt.Y + 1) == (Efound.Y))) //E below Tank { NaktK = Nakt; T = Tc; //remember Tank coords and number EE = dE; //remember E number! Encounter = true; //also remember this efound: daE = Efound; //briefly show it, or it will never be seen!!: screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Char.AsciiChar = 'E'; screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(500); } else if(((Nakt.X + 1) == Efound.X)&&((Nakt.Y) == (Efound.Y))) //E to the right of Tank { NaktK = Nakt; T = Tc; //remember Tank coords and number EE = dE; //remember E number! Encounter = true; //also remember this efound: daE = Efound; //briefly show it, or it will never be seen!!: screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Char.AsciiChar = 'E'; screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(500); } else if(((Nakt.X - 1) == Efound.X)&&((Nakt.Y) == (Efound.Y))) //E to the left of Tank { NaktK = Nakt; T = Tc; //remember Tank coords and number EE = dE; //remember E number! Encounter = true; //also remember this efound: daE = Efound; //briefly show it, or it will never be seen!!: screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Char.AsciiChar = 'E'; screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(500); } else if (((Nakt.X - 1) == Efound.X)&&((Nakt.Y - 1) == (Efound.Y))) //E to the upper left of Tank { NaktK = Nakt; T = Tc; //remember Tank coords and number EE = dE; //remember E number! Encounter = true; //also remember this efound: daE = Efound; //briefly show it, or it will never be seen!!: screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Char.AsciiChar = 'E'; screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(500); } else if (((Nakt.X - 1) == Efound.X)&&((Nakt.Y + 1) == (Efound.Y))) //E to the lower left of Tank { NaktK = Nakt; T = Tc; //remember Tank coords and number EE = dE; //remember E number! Encounter = true; //also remember this efound: daE = Efound; //briefly show it, or it will never be seen!!: screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Char.AsciiChar = 'E'; screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(500); } else if (((Nakt.X + 1) == Efound.X)&&((Nakt.Y + 1) == (Efound.Y))) //E to the lower right of Tank { NaktK = Nakt; T = Tc; //remember Tank coords and number EE = dE; //remember E number! Encounter = true; //also remember this efound: daE = Efound; //briefly show it, or it will never be seen!!: screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Char.AsciiChar = 'E'; screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(500); } else if (((Nakt.X + 1) == Efound.X)&&((Nakt.Y - 1) == (Efound.Y))) //E to the upper right of Tank { NaktK = Nakt; T = Tc; //remember Tank coords and number EE = dE; //remember E number! Encounter = true; //also remember this efound: daE = Efound; //briefly show it, or it will never be seen!!: screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Char.AsciiChar = 'E'; screenBuffer[Efound.X + Efound.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(500); } } //if E alive }//for dE } // end if(Friend.IsTankAlive(Tc)) } // end for(int Tc = 1; Tc < 11; Tc++) //Fight, and either erase Tank or Enemy building E: //int Strength = 200; //=Tank strength, can later modify this based on some factors (points, money, power, etc) //test: //Strength = 50; Strength = (Gold + Power) * BMax; //current gold + power left from power plants X number of buildings if(Encounter)//if an E building was found by a Tank { if(Fight(Strength)) //true = Tank won, E lost { //destroy the E from screenbuffer: //and add some animated debris screenBuffer[daE.X + daE.Y * SCREEN_WIDTH].Char.AsciiChar = '.'; screenBuffer[daE.X + daE.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; //debris, but safely inside borders: if(((daE.Y +2) < SCREEN_HEIGHT) && ((daE.X - 1) > 0) && ((daE.Y -2) > 0)&& ((daE.X + 1) < SCREEN_WIDTH)) { screenBuffer[(daE.X + 1) + daE.Y * SCREEN_WIDTH].Char.AsciiChar = '-'; screenBuffer[(daE.X + 1) + daE.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; screenBuffer[daE.X + (daE.Y +2) * SCREEN_WIDTH].Char.AsciiChar = 'I'; screenBuffer[daE.X + (daE.Y +2) * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; screenBuffer[(daE.X - 1) + (daE.Y -2) * SCREEN_WIDTH].Char.AsciiChar = '.'; screenBuffer[(daE.X - 1) + (daE.Y -2) * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(400); screenBuffer[(daE.X + 1) + daE.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[(daE.X + 1) + daE.Y * SCREEN_WIDTH].Attributes = 0; screenBuffer[daE.X + (daE.Y +2) * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[daE.X + (daE.Y +2) * SCREEN_WIDTH].Attributes = 0; screenBuffer[(daE.X - 1) + (daE.Y -2) * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[(daE.X - 1) + (daE.Y -2) * SCREEN_WIDTH].Attributes = 0; DrawWorld(screenBuffer, iChose); } //destroy its Integrity: //but slightly more elegant; already know E number from above: Enemy.HitMe(EE); std::thread tThe(Hit_E); tThe.join(); } else { //destroy the Tank: screenBuffer[NaktK.X + NaktK.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[NaktK.X + NaktK.Y * SCREEN_WIDTH].Attributes = 0; //need to check it for all movement loops?....no seems to work anyway Friend.setTankKill(T); std::thread tKillT(Hit_Tank); tKillT.join(); } }//end if encounter }//end if TLaunceOnce false //testing E destruction: //int Test = vEbases.size(); int Test2 = Enemy.getIntegrity(1) + Enemy.getIntegrity(2) + Enemy.getIntegrity(3) + Enemy.getIntegrity(4) + Enemy.getIntegrity(5) + Enemy.getIntegrity(6) + Enemy.getIntegrity(7) + Enemy.getIntegrity(8); //DrawWon("E bases:",70,8, FOREGROUND_RED | FOREGROUND_INTENSITY); // moved to main to stop blinking DrawWon(" :",70,9, FOREGROUND_RED | FOREGROUND_INTENSITY); //DrawWon(" ",70,10, FOREGROUND_RED | FOREGROUND_INTENSITY); Test2 = Test2/10; //number of bases, not their integrity sum cout << Test2; //80 if all E bases intact, 0 if all dead //DrawWon(" ",70,11, FOREGROUND_RED | FOREGROUND_INTENSITY); //If have Harvester, increase Gold with a certain delay. //More Harvesters = more Gold per cycle //More Gold => buy stuff? Use for all new buildings? //Gold impacts Strength of Tanks? GoldTime2 = GetTickCount(); GoldElapsed = GoldTime2 - GoldTime1; if((Bling > 0)&&(GoldElapsed > 5000)) //bling = if have harvester { GoldTime1 = GetTickCount();//reset gold timer GoldElapsed = 0; //reset //Gold = Gold + (Bling * 20); Gold = Gold + (Bling * 8); DrawWon(" ",70,18, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("Gold ",70,18, FOREGROUND_RED | FOREGROUND_INTENSITY); cout << Gold; DrawWon(" ",70,19, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("Power ",70,19, FOREGROUND_RED | FOREGROUND_INTENSITY); cout << Power; } //Enemy bombs green home area for as long as there are E bases left: //Wall should give some protection. //Spy should pause for a while. if(Spy) { BombTime2 = GetTickCount(); BombElapsed = BombTime2 - BombTime1; if(BombElapsed > 8000) //bombing pauses { Spy = false; Spied = true; BombTime1 = GetTickCount();//reset BombElapsed = 0; BombTime2 = 0; DrawWon(" ",70,23, FOREGROUND_GREEN | FOREGROUND_INTENSITY); //remove E preview: for(int seb = 1; seb < 9; seb++) { int Etest = Enemy.getIntegrity(seb); if(Etest > 0) { COORD SEbb = Enemy.GetCoord(seb); screenBuffer[SEbb.X + SEbb.Y * SCREEN_WIDTH].Char.AsciiChar = ' ' ; screenBuffer[SEbb.X + SEbb.Y * SCREEN_WIDTH].Attributes = 0; } } } } else //no spy { BombTime2 = GetTickCount(); BombElapsed = BombTime2 - BombTime1; //progressively faster bombing: int Wait = 0; switch(BMax)//number of buildings ordered { case 0: Wait = 50000;break; case 1: Wait = 40000; break; case 2: Wait = 20000; break; case 3: Wait = 15000; break; case 4: Wait = 7000; break; case 5: Wait = 6000; break; case 6: Wait = 5000; break; case 7: Wait = 4000; break; case 8: Wait = 3500; break; case 9: Wait = 3000; break; //too frequent bombing blocks other sound effects... case 10: Wait = 2500; break; default: cout << "def sw bmax bombings" << endl; }//end sw bmax if(BombElapsed > Wait) { BombTime1 = GetTickCount();//reset BombElapsed = 0; BombTime2 = 0; std::random_shuffle ( vXbomb.begin(), vXbomb.end() ); int BombX = vXbomb[0]; std::random_shuffle ( vYbomb.begin(), vYbomb.end() ); int BombY = vYbomb[0]; screenBuffer[BombX + BombY * SCREEN_WIDTH].Char.AsciiChar = '#'; screenBuffer[BombX + BombY * SCREEN_WIDTH].Attributes = BACKGROUND_BLUE; std::thread tEb(E_bombs); tEb.join(); //check if hit a building, if so destroy it, and reduce gold, bling, and power: COORD CheckB; //for(int b = 1; b < 11; b++)//all potential 10 buildings for(int b = 1; b < (BMax + 1); b++)//all actual built buildings { CheckB = Friend.GetCoord(b); if((Friend.getIntegrity(b) > 0) && (CheckB.X == BombX) && (CheckB.Y == BombY)) //still intact, and hit now { std::thread tHb(Hit_Base); tHb.join(); switch(Walls) //more walls; more protection: { case 0: { Friend.HitMe(b); //destroy the integrity if(Friend.GetType(b) == 4) Art = false; //kill own artillery if that was hit //else if(Friend.GetType(b) == 3) Walls--; //wall's protection reduced when hit else if(Friend.GetType(b) == 1) {Power = ((Power -2)/4); Gold = Gold - 5;} else if(Friend.GetType(b) == 2) {Gold = ((Gold - 200)/4); Bling--; } else if(Friend.GetType(b) == 5) Fact = false; } break; case 1: { Friend.HitMe(b); //destroy the integrity if(Friend.GetType(b) == 4) Art = false; //kill own artillery if that was hit else if(Friend.GetType(b) == 3) Walls--; //wall's protection reduced when hit else if(Friend.GetType(b) == 1) {Power = (Power/2) - 1; Gold = Gold - 3;} else if(Friend.GetType(b) == 2) {Gold = (Gold/3) - 100; Bling--;} else if(Friend.GetType(b) == 5) { Gold --; Power--;} } break; case 2: { Friend.HitMe(b); //destroy the integrity if(Friend.GetType(b) == 4) Gold = Gold -150; else if(Friend.GetType(b) == 3) Walls--; //wall's protection reduced when hit else if(Friend.GetType(b) == 1) {Power = (Power/2); Gold = Gold - 2;} else if(Friend.GetType(b) == 2) Gold = (Gold/3); else if(Friend.GetType(b) == 5) Gold = Gold - 200; } break; case 3: { //Friend.HitMe(b); //destroy the integrity Gold = Gold - 4; Power = Power - 2; Walls--; //the effect wears off... } break; default: //more than 3 walls { //Friend.HitMe(b); //destroy the integrity Gold = Gold - 2; Power = Power - 1; Walls--; //the effect wears off... } break; } DrawWon(" ",70,18, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("Gold ",70,18, FOREGROUND_RED | FOREGROUND_INTENSITY); cout << Gold; } //end if still intact and hit now if(BMax > 8) //late stage: increase accuracy of enemy bombs: { vectorvESharpX; vectorvESharpY; //load them with current coords of live buildings: COORD Base; for(int xb = 1; xb < (BMax+1); xb++) { if(Friend.getIntegrity(xb) > 0) { Base = Friend.GetCoord(xb); vESharpX.push_back(Base.X); vESharpY.push_back(Base.Y); } } //..but not too scary accurate: vESharpX.push_back(18); //vESharpX.push_back(20); //vESharpX.push_back(10); vESharpY.push_back(12); //vESharpY.push_back(14); //vESharpY.push_back(19); vXbomb = vESharpX; //re-assign with new content vYbomb = vESharpY; //re-assign with new content } } }//end if bombelapsed }//end else, no spy //Artillery: //if built at least one: ArtTime2 = GetTickCount(); ArtElapsed = ArtTime2 - ArtTime1; //tests if((Art)&& (ArtElapsed > 1000)) // if((Art)&& (ArtElapsed > 5000)) { ArtTime1 = GetTickCount();//reset ArtElapsed = 0; ArtTime2 = 0; if(Spied) //know where enemy bases are... { vectorvGotchaX; vectorvGotchaY; COORD ArtTarget; for(int sp = 1; sp < 9; sp++) { ArtTarget = Enemy.GetCoord(sp); vGotchaX.push_back(ArtTarget.X); vGotchaY.push_back(ArtTarget.Y); }//end for sp //add extra misses ints in vectors here? std::random_shuffle ( vGotchaX.begin(), vGotchaX.end() ); int ArtXaS = vGotchaX[0]; std::random_shuffle ( vGotchaY.begin(), vGotchaY.end() ); int ArtYaS = vGotchaY[0]; screenBuffer[ArtXaS + ArtYaS * SCREEN_WIDTH].Char.AsciiChar = 'X'; screenBuffer[ArtXaS + ArtYaS * SCREEN_WIDTH].Attributes = FOREGROUND_BLUE; //std::thread tArt(Artillery); //tArt.join(); COORD CheckBeS; for(int beS = 1; beS < 9; beS++)//all E buildings { CheckBeS = Enemy.GetCoord(beS); if((Enemy.getIntegrity(beS) > 0) && ((CheckBeS.X == ArtXaS) && (CheckBeS.Y == ArtYaS)) ) //still intact, and hit now { Enemy.HitMe(beS); std::thread tArtHit(Hit_E); tArtHit.join(); //debris, but safely inside borders: if(((ArtYaS +2) < SCREEN_HEIGHT) && ((ArtXaS - 1) > 0) && ((ArtYaS -2) > 0)&& ((ArtXaS + 1) < SCREEN_WIDTH)) { screenBuffer[(ArtXaS + 1) + ArtYaS * SCREEN_WIDTH].Char.AsciiChar = ']'; screenBuffer[(ArtXaS + 1) + ArtYaS * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; screenBuffer[ArtXaS + (ArtYaS +2) * SCREEN_WIDTH].Char.AsciiChar = '.'; screenBuffer[ArtXaS + (ArtYaS +2) * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; screenBuffer[(ArtXaS - 1) + (ArtYaS -2) * SCREEN_WIDTH].Char.AsciiChar = '-'; screenBuffer[(ArtXaS - 1) + (ArtYaS -2) * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(400); screenBuffer[(ArtXaS + 1) + ArtYaS * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[(ArtXaS + 1) + ArtYaS * SCREEN_WIDTH].Attributes = 0; screenBuffer[ArtXaS + (ArtYaS +2) * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[ArtXaS + (ArtYaS +2) * SCREEN_WIDTH].Attributes = 0; screenBuffer[(ArtXaS - 1) + (ArtYaS -2) * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[(ArtXaS - 1) + (ArtYaS -2) * SCREEN_WIDTH].Attributes = 0; DrawWorld(screenBuffer, iChose); } } }//end for be }// end if spied else //toggle between 4 areas using backspace button: { if(Area1) { std::random_shuffle ( vXArt1.begin(), vXArt1.end() ); ArtXa = vXArt1[0]; std::random_shuffle ( vYArt1.begin(), vYArt1.end() ); ArtYa = vYArt1[0]; } else if(Area2) { std::random_shuffle ( vXArt2.begin(), vXArt2.end() ); ArtXa = vXArt2[0]; std::random_shuffle ( vYArt2.begin(), vYArt2.end() ); ArtYa = vYArt2[0]; } else if(Area3) { std::random_shuffle ( vXArt3.begin(), vXArt3.end() ); ArtXa = vXArt3[0]; std::random_shuffle ( vYArt3.begin(), vYArt3.end() ); ArtYa = vYArt3[0]; } else if(Area4) { std::random_shuffle ( vXArt4.begin(), vXArt4.end() ); ArtXa = vXArt4[0]; std::random_shuffle ( vYArt4.begin(), vYArt4.end() ); ArtYa = vYArt4[0]; } else if(Area5) { std::random_shuffle ( vXArt5.begin(), vXArt5.end() ); ArtXa = vXArt5[0]; std::random_shuffle ( vYArt5.begin(), vYArt5.end() ); ArtYa = vYArt5[0]; } screenBuffer[ArtXa + ArtYa * SCREEN_WIDTH].Char.AsciiChar = 'X'; screenBuffer[ArtXa + ArtYa * SCREEN_WIDTH].Attributes = FOREGROUND_BLUE; COORD CheckBe; for(int be = 1; be < 9; be++)//all E buildings { CheckBe = Enemy.GetCoord(be); if((Enemy.getIntegrity(be) > 0) && ((CheckBe.X == ArtXa) && (CheckBe.Y == ArtYa))) //still intact, and hit now { Enemy.HitMe(be); std::thread tArtHitB(Hit_E); tArtHitB.join(); //debris, but safely inside borders: if(((ArtYa +2) < SCREEN_HEIGHT) && ((ArtXa - 1) > 0) && ((ArtYa -2) > 0)&& ((ArtXa + 1) < SCREEN_WIDTH)) { screenBuffer[(ArtXa + 1) + ArtYa * SCREEN_WIDTH].Char.AsciiChar = ']'; screenBuffer[(ArtXa + 1) + ArtYa * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; screenBuffer[ArtXa + (ArtYa +2) * SCREEN_WIDTH].Char.AsciiChar = '.'; screenBuffer[ArtXa + (ArtYa +2) * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; screenBuffer[(ArtXa - 1) + (ArtYa -2) * SCREEN_WIDTH].Char.AsciiChar = '-'; screenBuffer[(ArtXa - 1) + (ArtYa -2) * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; DrawWorld(screenBuffer, iChose); Sleep(400); screenBuffer[(ArtXa + 1) + ArtYa * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[(ArtXa + 1) + ArtYa * SCREEN_WIDTH].Attributes = 0; screenBuffer[ArtXa + (ArtYa +2) * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[ArtXa + (ArtYa +2) * SCREEN_WIDTH].Attributes = 0; screenBuffer[(ArtXa - 1) + (ArtYa -2) * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[(ArtXa - 1) + (ArtYa -2) * SCREEN_WIDTH].Attributes = 0; DrawWorld(screenBuffer, iChose); } } }//end for be }//end else; have not spied } //if art //die if all own buildings gone: int DeadCount = 0; for(int L = 1; L < (BMax + 1); L++ ) //check only those buildings that were planted = were active { DeadCount = DeadCount + Friend.getIntegrity(L); } //..but only after game has properly started... if((DeadCount < 1)&& (BMax > 0)) //all own buildings dead but had built some before { Sleep(3000); system("color 8");//mörkgrå std::thread tLose(Lost); tLose.join(); DrawWon("YOU LOST.......",8,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("****************************",8,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); Sleep(7000); return(0); } //regardless, monitor all own Tanks and show how many are still alive //after each frame (out-of-border, shot by E base, shot by enemy tank etc): int LiveTs = 0; bool StillThere = false; for(int Tcheck = 1; Tcheck < 11; Tcheck++) { StillThere = Friend.IsTankAlive(Tcheck); if(StillThere) LiveTs++; } if((Fact) && (Tsend))//have built factory, and have sent out tanks { DrawWon(" ",70,13, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("Tanks:",70,12, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon(" ",70,13, FOREGROUND_RED | FOREGROUND_INTENSITY); cout << LiveTs; //but only after tank launch?? } if((Enemy.getIntegrity(1) < 1)&& (Enemy.getIntegrity(2) < 1) && (Enemy.getIntegrity(3) < 1) && (Enemy.getIntegrity(4) < 1) && (Enemy.getIntegrity(5) < 1)&& (Enemy.getIntegrity(6) < 1)&& (Enemy.getIntegrity(7) < 1)&& (Enemy.getIntegrity(8) < 1)) { Sleep(3000); system("color 8");//mörkgrå std::thread tWin(Won); tWin.join(); DrawWon("YOU ARE VICTORIOUS!",8,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("****************************",8,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); TotalTime2 = GetTickCount(); TotalElapsed = TotalTime2 - TotalTime1; //testing: DrawWon("Points:",8,8, FOREGROUND_GREEN | FOREGROUND_INTENSITY); //cout << TotalElapsed; //314545 //Points = 5000 - (TotalElapsed / 1000); //314545 => 4685 points //455000 => 4545 points //652300 => 4348 points Points = 1000 - (TotalElapsed / 1000); //314545 => 686 points //455000 => 545 points if(Points < 0) //652300 => 348 points Points = 2000 - (TotalElapsed / 1000); cout << Points; fHighscores(); Sleep(5000); return(0); } Sleep(2); //fast framerate } //end while 1 return 0; } //////////////////////////////// DRAW WORLD ///////////////////////////////// ///// ///// draws screenBuffer to the screen ///// //////////////////////////////// DRAW WORLD ///////////////////////////////// void DrawWorld(CHAR_INFO screenBuffer[], int iWhich) { SMALL_RECT drawRect = {0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1}; COORD bufferSize = {SCREEN_WIDTH , SCREEN_HEIGHT}; COORD zeroZero = {0, 0}; HANDLE hOutput; hOutput = GetStdHandle(STD_OUTPUT_HANDLE); // Draw the vehicle at the position by pointer: COORD Pos = *pUrban; //switch on int passed in to draw correct vehicle symbol: switch(iWhich) { case 1: { screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Char.AsciiChar = 'P'; screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white }break; case 2: { screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Char.AsciiChar = 'H'; screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN| FOREGROUND_INTENSITY;}break; case 3: { screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Char.AsciiChar = 'W'; screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Attributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY;}break; case 4: { screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Char.AsciiChar = 'A'; screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY;}break; case 5: { screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Char.AsciiChar = 'F'; screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Attributes = FOREGROUND_BLUE | FOREGROUND_INTENSITY;}break; case 6: { screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Char.AsciiChar = '?'; //for start scene screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY;}break; case 7: { if(Nuked == false) { screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Char.AsciiChar = 'N'; screenBuffer[Pos.X + Pos.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY;}break; } default: { cout << "default sw iWhich" << endl; } break; } WriteConsoleOutput(hOutput, screenBuffer, bufferSize, zeroZero, &drawRect); } //////////////////////////////// DRAW Won ///////////////////////////////// //for displaying current points etc //////////////////////////////// DRAW Won ///////////////////////////////// void DrawWon(string Str, int X, int Y, WORD color) { HANDLE OutputH; COORD position = {X, Y}; OutputH = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(OutputH, color); SetConsoleCursorPosition(OutputH, position); cout << Str; //display text } //////////////////////// check input //////////////////////////////////////// //////////////////CHECK INPUT////////////////////////////////////////////// bool CheckInput() { DWORD events=0; HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); INPUT_RECORD InputRecord; GetNumberOfConsoleInputEvents(hInput, &events); if(!events) return false; ReadConsoleInput(hInput, &InputRecord, 1, &events); bKeyDown = InputRecord.Event.KeyEvent.bKeyDown; DaKeyCode = InputRecord.Event.KeyEvent.wVirtualKeyCode; return true; } ////////////////////// Handle Input //////////////////////////////////// //************************************************************************// ////////////////////// Handle Input //////////////////////////////////// void HandleGameInput(CHAR_INFO screenBuffer[]) //coord now by global pointer! { bool Safe = true; //resets each time pressed a button COORD vePos = *pUrban; //whatever vehicle chosen in main, its position //but it is now a local copy here COORD oldPosition = vePos; if((DaKeyCode > 0) && (bKeyDown > 0) && (BMax < 11)) { if((DaKeyCode == VK_UP)&& (Target == false)) { // fly up if(vePos.Y > 15) // do not allow cursor outside of homebase area { //check that not collide/erase any existing buildings: for(int bu = 1; bu < 11; bu++) { COORD bCheck = Friend.GetCoord(bu); if(((vePos.Y -2) == (bCheck.Y))&&(vePos.X == bCheck.X)) Safe = false; //not safe to move there else if(((vePos.Y -1) == (bCheck.Y))&&(vePos.X == bCheck.X)) Safe = false; //not safe to move there } //-2 or else green 'see' view erases it if(Safe) { vePos.Y--; *pUrban = vePos; //changes coord of whatever vehicle chosen in main! } } }//end vk up else if((DaKeyCode == VK_DOWN)&& (Target == false)) { // fly down if(vePos.Y < (SCREEN_HEIGHT - 1) ) // do not allow cursor outside of homebase area { for(int bu2 = 1; bu2 < 11; bu2++) { COORD bCheck2 = Friend.GetCoord(bu2); if(((vePos.Y +2) == (bCheck2.Y))&&(vePos.X == bCheck2.X)) Safe = false; //not safe to move there else if(((vePos.Y +1) == (bCheck2.Y))&&(vePos.X == bCheck2.X)) Safe = false; //not safe to move there } if(Safe) { vePos.Y++; *pUrban = vePos; } } }//end vk down else if((DaKeyCode == VK_LEFT)&& (Target == false)) { // Fly left: if(vePos.X > 0) // do not allow cursor outside of homebase area { for(int bu3 = 1; bu3 < 11; bu3++) { COORD bCheck3 = Friend.GetCoord(bu3); if(((vePos.X -2) == (bCheck3.X))&&(vePos.Y == bCheck3.Y)) Safe = false; //not safe to move there if(((vePos.X -1) == (bCheck3.X))&&(vePos.Y == bCheck3.Y)) Safe = false; //not safe to move there } if(Safe) { vePos.X--; *pUrban = vePos; } } }// end vk left else if((DaKeyCode == VK_RIGHT)&& (Target == false)) { // Fly right if(vePos.X < 16 ) // do not allow cursor outside of homebase area { for(int bu4 = 1; bu4 < 11; bu4++) { COORD bCheck4 = Friend.GetCoord(bu4); if(((vePos.X +2) == (bCheck4.X))&&(vePos.Y == bCheck4.Y)) Safe = false; //not safe to move there else if(((vePos.X +1) == (bCheck4.X))&&(vePos.Y == bCheck4.Y)) Safe = false; //not safe to move there } if(Safe) { vePos.X++; *pUrban = vePos; } } }//end vk right else if((DaKeyCode == VK_SPACE)&& (Fact)) //Tank launch if Factory built and not destroyed { Tselect++; //Beep(800,100); Tsend = true; switch(Tselect) { case 2: {North = true; South = false; East = false; West = false; DrawWon("N",70,17, FOREGROUND_RED | FOREGROUND_INTENSITY); } break; case 3: {North = false; South = true; East = false; West = false; DrawWon("S",70,17, FOREGROUND_RED | FOREGROUND_INTENSITY); } break; case 4: {North = false; South = false; East = true; West = false; DrawWon("E",70,17, FOREGROUND_RED | FOREGROUND_INTENSITY); } break; case 5: {North = false; South = false; East = false; West = true; DrawWon("W",70,17, FOREGROUND_RED | FOREGROUND_INTENSITY); } break; case 6: {Tselect = 1; North = false; South = false; East = false; West = false; DrawWon("?",70,17, FOREGROUND_RED | FOREGROUND_INTENSITY); } break; }//end sw tselect } else if((DaKeyCode == VK_ESCAPE) && (NukeAuthorized)) //nuke { //Beep(700,100); Nuke = true; Target = true; //blocks arrow movement //Friend.SetTarget(vePos); DrawWon("Nuke",70,0, FOREGROUND_RED | FOREGROUND_INTENSITY); DrawWon("charging.",70,1, FOREGROUND_RED | FOREGROUND_INTENSITY); } else if(DaKeyCode == VK_CONTROL) // Ctrl key { Menumode = true; } else if((DaKeyCode == VK_SHIFT) && (BMax < 10)) { //Beep(500,70); Target = true; BMax++; //put it here instead, remove from main build menu std::thread tBuild(Plant_Build); tBuild.join(); //max 10 buildings: //need bmax++ before this, at building choice at menu if(BMax < 11) { Friend.Plant(BMax,vePos,iChose);//stores number, coord, type in class if(iChose == 3)//build wall: { Walls++; } } } else if(DaKeyCode == VK_TAB) //help { //help: string sBack; system("color 8");//mörkgrå std::thread tHeMe(MenuSound); tHeMe.join(); DrawWon("Ctrl: the build menu. ",2,5, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Tab: this help menu.",2,6, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Arrow keys: for placing new buildings in staging area (green). ",2,7, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Shift: lock down where a building should sit. ",2,8, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Esc: launch nuke. ",2,9, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Space bar: launches Tanks from Factory, then steer by toggle:",2,10, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("North, South, East, West, Random, repeats.",2,11, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Random mode (? sign) helps to spread out Tanks.",2,12, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("More power means more Tanks, but you can only launch them once.",2,13, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("The Tanks become stronger the more gold and buildings you have,",2,14, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("even after the Tanks have been launched.",2,15, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("You need Harvester buildings to generate gold.",2,16, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("You need a Factory and enough power to launch nukes.",2,17, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Artillery shoots randomly at areas (toggle: backspace key).",2,18, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("If you sent out a Spy, artillery aims better.",2,19, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Walls give some protection against enemy bombings.",2,20, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon(" ",2,21, FOREGROUND_GREEN | FOREGROUND_INTENSITY); DrawWon("Press any key and 'enter key' to continue.",2,22, FOREGROUND_GREEN | FOREGROUND_INTENSITY); cin >> sBack; } else if((DaKeyCode == VK_BACK) && (Art))//backspace key and have artillery { //toggles artillery focus area: Artselect++; switch(Artselect) { case 1: {Area1 = true; Area2 = false; Area3 = false; Area4 = false; Area5 = false; DrawWon("Art: 1",70,21, FOREGROUND_RED | FOREGROUND_INTENSITY); } break; case 2: {Area1 = false; Area2 = true; Area3 = false; Area4 = false; Area5 = false; DrawWon("Art: 2",70,21, FOREGROUND_RED | FOREGROUND_INTENSITY); } break; case 3: {Area1 = false; Area2 = false; Area3 = true; Area4 = false; Area5 = false; DrawWon("Art: 3",70,21, FOREGROUND_RED | FOREGROUND_INTENSITY); } break; case 4: {Area1 = false; Area2 = false; Area3 = false; Area4 = true; Area5 = false; DrawWon("Art: 4",70,21, FOREGROUND_RED | FOREGROUND_INTENSITY); } break; case 5: {Area1 = false; Area2 = false; Area3 = false; Area4 = false; Area5 = true; DrawWon("Art: 5",70,21, FOREGROUND_RED | FOREGROUND_INTENSITY); Artselect = 0; } break; }//end sw tselect } if(DaKeyCode == VK_RIGHT || DaKeyCode == VK_LEFT || DaKeyCode == VK_UP || DaKeyCode == VK_DOWN ) { // Erase the old position of the player with a space: screenBuffer[oldPosition.X + oldPosition.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[oldPosition.X + oldPosition.Y * SCREEN_WIDTH].Attributes = BACKGROUND_GREEN; } } }//end handle input bool Fight(int Armor) //Armor/integrity of attacker { //enemy buildings and vehicle have same armor/integrity (450) and guns (1)? //Armor can also be Integrity of friendly building srand(GetTickCount()); //'seeding' the rand function with tick count int Roll = ((rand() % 6) + 1); //(1-6) //Armor = (Armor * Roll) - 450; // Tanks win too easily //Armor = (Armor * Roll) - 550; //Armor = (Armor * Roll) - 850; //Armor = (Armor * Roll) - 1000; //Armor = (Armor * Roll) - 1200; //Armor = (Armor * Roll) - 1000; //Armor = (Armor * Roll) - 2500; Armor = (Armor * Roll) - 3500; if((Armor > 0) || (Armor == 0)) return true; //attacker won else return false; //attacker lost }//end Fight //////////////// FUNCTION HIGHSCORES ///////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// void fHighscores(void) { vectorvHighscores(25000); //fast vector för highscores vectorvUsers; vectorAllUsersIn; vectoriPointsIn; vectoriPoints; vectorAllUsers; int Score = 0; if (Points < 1) Points = 1; //annars vektorkrash string sTest; int Empty = 0; int Placer = 0; //uppdatera highscorelista från gamla filer, printa sedan ny: //retreive stored names in order: ifstream finStrings("NameScores.txt"); if (!finStrings) { ofstream foutStrings("NameScores.txt"); foutStrings.close(); } while (finStrings >> sTest) AllUsersIn.push_back(sTest);//the list has already been sorted in order, but push_back reverses it!!! //Now need to reverse it again: finStrings.close(); //same thing, but for stored scores; int Tempoint = 0; ifstream finInts("IntScores.txt"); if (!finInts) { ofstream foutInts("IntScores.txt"); foutInts.close(); } while (finInts >> Tempoint) iPointsIn.push_back(Tempoint);//already been sorted in order, push_back reverses finInts.close(); int est = 0; // re-assemble the past highscore list: for (int n = 0; n < AllUsersIn.size(); n++)// { est = iPointsIn[n]; vHighscores[est] = AllUsersIn[n]; //put name at [points in] position, biggest first }//end for n //Load current name to pre-existing lists: if (Points > 25000) { Points = 25000; }//så inte går över max Points = (25000 - Points); //omdefinierat så hamnar högt upp på listan med hög poäng if (vHighscores[Points].empty())//om ledigt... vHighscores[Points] = sNamn; //sätt namnet där, vid sin poäng! //Tar bort delade platser, blir bugg när laddar in sparade filer igen då; olika vektorstorlakar. //Kompensera med poäng även baserad på steg; mer osannolikt att flera får samma poäng. //och om någon annan får samma poäng kommer de inte in på highscorelistan; någon annan kom före på den poängen. //else //{//om redan finns nån med samma poäng, sätt på samma plats: //string sDelad = vHighscores[Points] + " OCH " + sNamn; //vHighscores[Points] = sDelad; //} //store the now udated names and points in files: ofstream foutStoreN("NameScores.txt"); for (int p = 0; p < vHighscores.size(); p++) { if (vHighscores[p].empty()) Empty++; //do not print empty positions else { string sOutAll = vHighscores[p]; foutStoreN << sOutAll << endl; } } foutStoreN.close(); ofstream foutStoreI("IntScores.txt"); for (int q = 0; q < vHighscores.size(); q++) { if (vHighscores[q].empty()) Empty++; //do not print empty positions else { foutStoreI << q << endl; } }//end for q foutStoreI.close(); //output sHighscores vector to Highskor.txt file: ofstream fHigh("Highskor.txt"); //inte ::app, vill ha ny varje gång //use only those positions that are occupied with a name!: //the for loops also serve to reverse the order, printing last first...: fHigh << " HIGHSCORES:" << endl; for (int y = 0; y < vHighscores.size(); y++)// { if (vHighscores[y].empty()) Empty++;//do not print empty positions else { Placer++;//translate to first, second, third etc place! // and translate to a high score for the best: int Score = 25000 - y; // \t är tabulering, sätter ut ett stort mellanrum: if (Placer < 11)//only top 10 on Highscore list { fHigh << Placer << ":" << "\t" << vHighscores[y] << " (" << Score << " poeng)." << endl; } }//end else Placer }// end for y fHigh.close(); Placer = 0; //Visa highscorelista på skärmen också: //But only top 10 on Highscore list!: cout << endl; cout << "*********************************" << endl; cout << " HIGHSCORES:" << endl; for (int z = 0; z < vHighscores.size(); z++)// { if (vHighscores[z].empty()) Empty++;//do not print empty positions else { Placer++;//translate to first, second, third etc place! int screenScore = 25000 - z; // translate to a high score for the best if (Placer < 11)//only top 10 on Highscore list { cout << setw(3) << Placer << ":" << "\t" << vHighscores[z] << " (" << screenScore << " poeng)." << endl; } //setw adjusts spacing }//end else Placer }// end for z Placer = 0; cout << "*********************************" << endl; Sleep(4000); }//end funktion highscores