// This routine handles one combat round. // fleets[2] are the combatants. // msgs[0] is sent to the owner of fleet1, // msgs[1] is sent to the owner of fleet2. // // Assume that 'number of missiles/torpedoes a ship can carry' // really means 'number of missiles/torpedoes a ship can fire in one round'. // Ships have an infinite amount of ammunition. // // Further assume that everyone fires his/her full load, // then all the damage is done. No 'this ship was destroyed // in this round, so it can't fire any missiles'. // // I keep (for now) the policy of always targetting the largest // ship. // // Likelihood of (correct) impact is 100% for missiles, and // (1-dodge likelihood) for torpedoes. // // How about armor as a recurring damage absorber? Like // 20HP of damage hitting a ship that has 5HP of armor // results in only 15HP of damage to that ship. The next // round, another 15HP of damage hits the ship, resulting // in another 10HP of damage. The armor itself is not // damaged until the ship is destroyed. // // Keep the same damage effects? Ships are at full // capacity until they are destroyed? // // All that being said, I decreased the damage the two sides // do to each other by a random 0-39% because I wanted some // randomness involved. bool AVACombat::doCombatRound( Fleet* fleet1, Message::Ptr msg1, Fleet* fleet2, Message::Ptr msg2) { Logger::getLogger()->debug("doCombatRound Entering"); Game* game = Game::getGame(); DesignStore::Ptr ds = game->getDesignStore(); ResourceManager::Ptr resman = game->getResourceManager(); typedef std::map<uint32_t, std::pair<uint32_t, uint32_t> > weaponList; // ID/TYPE AMOUNT typedef std::map<uint32_t, uint32_t> shipList; std::map<uint32_t, std::string> tubes; tubes[ds->getPropertyByName("AlphaMissileTube")] = "AlphaMissileTube"; tubes[ds->getPropertyByName("BetaMissileTube")] = "BetaMissileTube"; tubes[ds->getPropertyByName("GammaMissileTube")] = "GammaMissileTube"; tubes[ds->getPropertyByName("DeltaMissileTube")] = "DeltaMissileTube"; tubes[ds->getPropertyByName("EpsilonMissileTube")] = "EpsilonMissileTube"; tubes[ds->getPropertyByName("OmegaTorpedoeTube")] = "OmegaTorpedoeTube"; tubes[ds->getPropertyByName("UpsilonTorpedoeTube")] = "UpsilonTorpedoeTube"; tubes[ds->getPropertyByName("TauTorpedoeTube")] = "TauTorpedoeTube"; tubes[ds->getPropertyByName("SigmaTorpedoeTube")] = "SigmaTorpedoeTube"; tubes[ds->getPropertyByName("RhoTorpedoeTube")] = "RhoTorpedoeTube"; tubes[ds->getPropertyByName("XiTorpedoeTube")] = "XiTorpedoeTube"; std::map<uint32_t, uint32_t> tubeList; std::set<Design::Ptr> designList; weaponList fleetweaponry[2]; shipList fleetships[2]; Fleet* fleets[2]; std::map<uint32_t, std::pair<std::string, uint32_t> > fleettubes[2]; std::map<uint32_t, uint32_t> fleetusable[2]; // resourceid, designid fleetweaponry[0] = fleet1->getResources(); fleetweaponry[1] = fleet2->getResources(); fleetships[0] = fleet1->getShips(); fleetships[1] = fleet2->getShips(); fleets[0] = fleet1; fleets[1] = fleet2; uint32_t damage[2] = {0}; for (int i=0; i < 2; i++) { for (shipList::iterator itcurr = fleetships[i].begin(); itcurr != fleetships[i].end(); ++itcurr) { for (std::map<uint32_t, std::string>::iterator tubeit = tubes.begin(); tubeit != tubes.end(); ++tubeit) { if (ds->getDesign(itcurr->first)->getPropertyValue(tubeit->first) > 0.0) { Logger::getLogger()->debug("Found usable Tube %s, inserting into Fleet %d", tubeit->second.c_str(), i); //size of weapon uint32_t weapSizePropID = ds->getPropertyByName(tubeit->second); uint32_t weapNumPropID = ds->getPropertyByName("num-" + tubeit->second); uint32_t weapSizePropValue = static_cast<uint32_t>(ds->getDesign(itcurr->first)->getPropertyValue(weapSizePropID)); uint32_t weapNumPropValue = static_cast<uint32_t>(ds->getDesign(itcurr->first)->getPropertyValue(weapNumPropID)); if (fleettubes[i].find(weapSizePropValue) != fleettubes[i].end()) { std::pair<std::string, uint32_t>fleetpair = fleettubes[i][weapSizePropValue]; fleetpair.second += weapNumPropValue; fleettubes[i][weapSizePropValue] = fleetpair; Logger::getLogger()->debug("Adding %d into Tube List", weapSizePropValue); } else { fleettubes[i][weapSizePropValue] = std::pair<std::string, uint32_t> (tubeit->second, weapNumPropValue); } } } for (weaponList::iterator weapit = fleetweaponry[i].begin(); weapit != fleetweaponry[i].end(); ++weapit) { Design::Ptr weapDesign; std::string weapName = resman->getResourceDescription(weapit->first)->getNameSingular(); std::set<uint32_t>dIDs = ds->getDesignIds(); for (std::set<uint32_t>::iterator dit = dIDs.begin(); dit != dIDs.end(); ++dit) { if (weapName == ds->getDesign(*dit)->getName()) { weapDesign = ds->getDesign(*dit); Logger::getLogger()->debug("Found design %s", weapDesign->getName().c_str()); for (std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator tubeit = fleettubes[i].begin(); tubeit != fleettubes[i].end(); ++tubeit) { //property ID, name of the TUBE uint32_t propID = ds->getPropertyByName("MissileSize"); //Logger::getLogger()->debug("Checking fleettubes list for propID %s", ds->getProperty(propID)->getName().c_str()); uint32_t weapPropVal = static_cast<uint32_t>(weapDesign->getPropertyValue(propID)); if (fleettubes[i].find(weapPropVal) != fleettubes[i].end()) { Logger::getLogger()->debug("Found it, trying to remove resource %d from fleet", weapit->first); fleetusable[i][weapit->first] = weapDesign->getDesignId(); if (fleets[i]->removeResource(weapit->first, 1)) { uint32_t explPropID = ds->getPropertyByName("AmmoExplosiveness"); //damage to be deliveredt damage[!i] += static_cast<uint32_t>(weapDesign->getPropertyValue(explPropID)); Logger::getLogger()->debug("Adding Damage (%d) Total (%d)", static_cast<uint32_t>(weapDesign->getPropertyValue(explPropID)), damage[!i]); } else { Logger::getLogger()->debug("No available Weapon for this tube!"); } } } } } } } } fleet1->setDamage(damage[0]); fleet2->setDamage(damage[1]); resolveCombat(fleet1); resolveCombat(fleet2); //Tube format: std::map<double, std::pair<std::string, uint32_t> > // tube size name number bool tte = false; std::string body[2]; if (fleet1->totalShips() == 0) { body[0] += "Your fleet was destroyed. "; body[1] += "You destroyed their fleet. "; c1.reset(); tte = true; }; if (fleet2->totalShips() == 0) { body[0] += "Your fleet was destroyed."; body[1] += "You destroyed their fleet."; c2.reset(); tte = true; } if ( tte) { msg1->setBody( body[0]); msg2->setBody( body[1]); } Logger::getLogger()->debug("doCombatRound Exiting"); return false; }
//Award artifacts to any players who have a merchant leader //in a region with two artifacts void TaeTurn::awardArtifacts() { Game* game = Game::getGame(); ObjectTypeManager* obtm = game->getObjectTypeManager(); ObjectManager* objectmanager = game->getObjectManager(); std::set<uint32_t> artifacts; std::set<uint32_t> regions; std::set<uint32_t> objects = objectmanager->getAllIds(); std::set<uint32_t>::iterator itcurr; //Find any regions with 2 or more alien artifacts for(itcurr = objects.begin(); itcurr != objects.end(); ++itcurr) { IGObject::Ptr ob = objectmanager->getObject(*itcurr); if(ob->getType() == obtm->getObjectTypeByName("Planet")) { Planet* p = (Planet*) ob->getObjectBehaviour(); if(p->getResource(3) > 0) { StarSystem* sys = (StarSystem*)(objectmanager->getObject(ob->getParent())->getObjectBehaviour()); if(sys->getRegion() != 0) { if(regions.count(sys->getRegion()) > 0) { artifacts.insert(*itcurr); } else { regions.insert(sys->getRegion()); } } } } } if(!artifacts.empty()) { uint32_t type; DesignStore::Ptr ds = game->getDesignStore(); PlayerManager::Ptr pm = game->getPlayerManager(); std::set<uint32_t> designs = ds->getDesignIds(); //get leader ID for(itcurr = designs.begin(); itcurr != designs.end(); ++itcurr) { if(ds->getDesign(*itcurr)->getName().compare("MerchantLeaderShip")) { type = *itcurr; } } //Search the objects for a merchant leader for(itcurr = objects.begin(); itcurr != objects.end(); ++itcurr) { IGObject::Ptr ob = objectmanager->getObject(*itcurr); if(ob->getType() == obtm->getObjectTypeByName("Fleet")) { Fleet* f = (Fleet*) (ob->getObjectBehaviour()); if(f->getShips().count(type) > 0) { IGObject::Ptr parent = objectmanager->getObject(ob->getParent()); if(parent->getType() == obtm->getObjectTypeByName("Star System")) { StarSystem* parentData = (StarSystem*) (parent->getObjectBehaviour()); //See if this leader is in a region with //2 or more alien artifacts for(std::set<uint32_t>::iterator i = artifacts.begin(); i != artifacts.end(); ++i) { IGObject::Ptr obj = objectmanager->getObject(*i); Planet* p = (Planet*) obj->getObjectBehaviour(); StarSystem* sys = (StarSystem*)(objectmanager->getObject(obj->getParent())->getObjectBehaviour()); if(sys->getRegion() == parentData->getRegion()) { //+1 to leader's owner's artifact score Player::Ptr owner = pm->getPlayer(f->getOwner()); owner->setScore(5, owner->getScore(5) + 1); p->removeResource(3, 1); artifacts.erase(*i); } } } } } } } }
// Combat always takes place between two fleets. If one combatant // or the other is actually a planet, the planet simulated by two // battleships. void AVACombat::doCombat() { Logger::getLogger()->debug("AVACombat::doCombat : Entering"); Fleet *fleets[2]; Game* game = Game::getGame(); DesignStore::Ptr ds = game->getDesignStore(); uint32_t obT_Fleet = game->getObjectTypeManager()->getObjectTypeByName("Fleet"); uint32_t obT_Planet = game->getObjectTypeManager()->getObjectTypeByName("Planet"); // If one combatant or the other is actually a planet, // simulate this with two battleships. if ( c1->getType() == obT_Fleet) { fleets[0] = dynamic_cast<Fleet*>( c1->getObjectBehaviour()); } else if ( c1->getType() == obT_Planet) { fleets[0] = new DummyFleet(); std::set<uint32_t> dIDs = ds->getDesignIds(); uint32_t scoutID=0; for (std::set<uint32_t>::iterator it = dIDs.begin(); it != dIDs.end(); ++it) { if (ds->getDesign(*it)->getName() == "Scout") { scoutID = *it; } } fleets[0] = new DummyFleet(); fleets[0]->addShips(scoutID , 2); fleets[0]->setOwner( dynamic_cast<Planet*>(c1->getObjectBehaviour())->getOwner()); } if ( c2->getType() == obT_Fleet) { fleets[1] = dynamic_cast<Fleet*>( c2->getObjectBehaviour()); } else if ( c2->getType() == obT_Planet) { std::set<uint32_t> dIDs = ds->getDesignIds(); uint32_t scoutID=0; for (std::set<uint32_t>::iterator it = dIDs.begin(); it != dIDs.end(); ++it) { if (ds->getDesign(*it)->getName() == "Scout") { scoutID = *it; } } fleets[1] = new DummyFleet(); fleets[1]->addShips(scoutID, 2); fleets[1]->setOwner( dynamic_cast<Planet*>(c2->getObjectBehaviour())->getOwner()); } if ( fleets[0] == NULL || fleets[1] == NULL) { return; } Message::Ptr msg1( new Message() ); Message::Ptr msg2( new Message() ); msg1->setSubject( "Combat"); msg2->setSubject( "Combat"); msg1->addReference( rst_Object, c1->getID()); msg1->addReference( rst_Object, c2->getID()); msg1->addReference( rst_Player, fleets[1]->getOwner()); msg2->addReference( rst_Object, c2->getID()); msg2->addReference( rst_Object, c1->getID()); msg2->addReference( rst_Player, fleets[0]->getOwner()); while ( doCombatRound( fleets[0], msg1, fleets[1], msg2)) { ; } Game::getGame()->getPlayerManager()->getPlayer( fleets[0]->getOwner())->postToBoard( msg1); Game::getGame()->getPlayerManager()->getPlayer( fleets[1]->getOwner())->postToBoard( msg2); return; }