From 56fcbeb227983c702f46fee56fdd5c0dfc2cd879 Mon Sep 17 00:00:00 2001 From: JT Traub Date: Mon, 7 Oct 2024 00:24:02 -0700 Subject: [PATCH] Remove AList usage from all orders This modifies all orders to no longer be ALists. Also moves them to be shared_ptr rather than using raw pointers with new/delete. In most cases, I chose to use std::vector for the list of orders but in some (two) cases I chose std::list since there was a need to insert at the head. Choosing vector over list is preferred in general as it has better speed, but it makes inserting at the head harder. --- faction.cpp | 14 +- game.h | 8 +- monthorders.cpp | 441 +++++++++++++------------------- orders.cpp | 9 + orders.h | 68 ++--- parseorders.cpp | 204 ++++++--------- runorders.cpp | 312 ++++++++++------------ spells.cpp | 139 ++++------ unit.cpp | 129 ++++------ unit.h | 39 ++- unittest/quartermaster_test.cpp | 12 +- 11 files changed, 575 insertions(+), 800 deletions(-) diff --git a/faction.cpp b/faction.cpp index 732ed3fc..91f0c0b5 100644 --- a/faction.cpp +++ b/faction.cpp @@ -104,11 +104,11 @@ Faction::Faction() { exists = 1; name = 0; - + for (auto &ft : *FactionTypes) { type[ft] = 1; } - + lastchange = -6; address = 0; password = 0; @@ -129,7 +129,7 @@ Faction::Faction(int n) { exists = 1; num = n; - + for (auto &ft : *FactionTypes) { type[ft] = 1; } @@ -211,7 +211,7 @@ void Faction::Readin(istream& f) name = new AString(tmp); AString *temp = name->stripnumber(); SetName(temp); - + f >> ws >> tmp; address = new AString(tmp); f >> ws >> tmp; @@ -675,10 +675,10 @@ int Faction::CanSee(ARegion* r, Unit* u, int practice) // penalty of 2 to stealth if assassinating and 1 if stealing // TODO: not sure about the reasoning behind the IMPROVED_AMTS part int stealpenalty = 0; - if (Globals->HARDER_ASSASSINATION && u->stealorders){ - if (u->stealorders->type == O_STEAL) { + if (Globals->HARDER_ASSASSINATION && u->stealthorders){ + if (u->stealthorders->type == O_STEAL) { stealpenalty = 1; - } else if (u->stealorders->type == O_ASSASSINATE) { + } else if (u->stealthorders->type == O_ASSASSINATE) { if (Globals->IMPROVED_AMTS){ stealpenalty = 1; } else { diff --git a/game.h b/game.h index d1db1dbe..a0dd31d4 100644 --- a/game.h +++ b/game.h @@ -423,7 +423,7 @@ class Game void WriteTimesArticle(AString); void DoExchangeOrders(); - void DoExchangeOrder(ARegion *, Unit *, ExchangeOrder *); + void DoExchangeOrder(ARegion *r, Unit *u, std::shared_ptr o); // // Faction limit functions. @@ -444,12 +444,12 @@ class Game // The DoGiveOrder returns 0 normally, or 1 if no more GIVE orders // should be allowed // - int DoGiveOrder(ARegion *, Unit *, GiveOrder *); + int DoGiveOrder(ARegion *r, Unit *u, std::shared_ptr o); // // The DoWithdrawOrder returns 0 normally, or 1 if no more WITHDRAW // orders should be allowed // - int DoWithdrawOrder(ARegion *, Unit *, WithdrawOrder *); + int DoWithdrawOrder(ARegion *r, Unit *u, std::shared_ptr o); // // These are game specific, and can be found in extra.cpp @@ -557,7 +557,7 @@ class Game void RunSacrificeOrders(); void CollectInterQMTransportItems(); void CheckTransportOrders(); - AList *CanSeeSteal(ARegion *, Unit *); + std::vector> CanSeeSteal(ARegion *, Unit *); void Do1Steal(ARegion *, Object *, Unit *); void Do1Assassinate(ARegion *, Object *, Unit *); void Do1Annihilate(ARegion *reg); diff --git a/monthorders.cpp b/monthorders.cpp index fc3ce08f..e6723e79 100644 --- a/monthorders.cpp +++ b/monthorders.cpp @@ -31,6 +31,7 @@ #include #include +#include #include "game.h" #include "gamedata.h" @@ -45,9 +46,6 @@ void Game::RunMovementOrders() Object *o; AList locs; Location *l; - MoveOrder *mo; - SailOrder *so; - MoveDir *d; AString order, *tOrder; for (phase = 0; phase < Globals->MAX_SPEED; phase++) { @@ -103,8 +101,7 @@ void Game::RunMovementOrders() u->error("SAIL: Fleet is too damaged to sail."); break; } - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; } } } @@ -158,58 +155,53 @@ void Game::RunMovementOrders() forlist(&r->objects) { o = (Object *) elem; for(auto u: o->units) { - mo = (MoveOrder *) u->monthorders; - if (!u->nomove && - u->monthorders && - (u->monthorders->type == O_MOVE || - u->monthorders->type == O_ADVANCE) && - mo->dirs.Num() > 0) { - d = (MoveDir *) mo->dirs.First(); - if (u->savedmovedir != d->dir) - u->savedmovement = 0; - u->savedmovement += u->movepoints / Globals->MAX_SPEED; - u->savedmovedir = d->dir; - } else { - u->savedmovement = 0; + if (!u->monthorders || (u->monthorders->type != O_MOVE && u->monthorders->type != O_ADVANCE)) { u->savedmovedir = -1; + u->savedmovement = 0; + continue; } - if (u->monthorders && - (u->monthorders->type == O_MOVE || - u->monthorders->type == O_ADVANCE)) { - mo = (MoveOrder *) u->monthorders; - if (mo->dirs.Num() > 0) { - string type = (mo->advancing ? "ADVANCE" : "MOVE"); - string temp = type + ": Unit has insufficient movement points; remaining moves queued."; - u->event(temp, "movement"); - tOrder = new AString(type); - forlist(&mo->dirs) { - d = (MoveDir *) elem; - *tOrder += " "; - if (d->dir < NDIRS) *tOrder += DirectionAbrs[d->dir]; - else if (d->dir == MOVE_IN) *tOrder += "IN"; - else if (d->dir == MOVE_OUT) *tOrder += "OUT"; - else if (d->dir == MOVE_PAUSE) *tOrder += "P"; - else *tOrder += d->dir - MOVE_ENTER; - } - u->oldorders.push_front(tOrder->const_str()); + + std::shared_ptr mo = std::dynamic_pointer_cast(u->monthorders); + if (mo->dirs.size() > 0) { + if (!u->nomove) { + MoveDir d = mo->dirs[0]; + if (u->savedmovedir != d.dir) + u->savedmovement = 0; + u->savedmovement += u->movepoints / Globals->MAX_SPEED; + u->savedmovedir = d.dir; + } else { + u->savedmovement = 0; + u->savedmovedir = -1; + } + + string type = (mo->advancing ? "ADVANCE" : "MOVE"); + string temp = type + ": Unit has insufficient movement points; remaining moves queued."; + u->event(temp, "movement"); + tOrder = new AString(type); + for(auto d: mo->dirs) { + *tOrder += " "; + if (d.dir < NDIRS) *tOrder += DirectionAbrs[d.dir]; + else if (d.dir == MOVE_IN) *tOrder += "IN"; + else if (d.dir == MOVE_OUT) *tOrder += "OUT"; + else if (d.dir == MOVE_PAUSE) *tOrder += "P"; + else *tOrder += d.dir - MOVE_ENTER; } + u->oldorders.push_front(tOrder->const_str()); } } + Unit *u = o->GetOwner(); - if (o->IsFleet() && u && !u->nomove && - u->monthorders && - u->monthorders->type == O_SAIL) { - so = (SailOrder *) u->monthorders; - if (so->dirs.Num() > 0) { + if (o->IsFleet() && u && !u->nomove && u->monthorders && u->monthorders->type == O_SAIL) { + std::shared_ptr so = std::dynamic_pointer_cast(u->monthorders); + if (so->dirs.size() > 0) { u->event("SAIL: Can't sail that far; remaining moves queued.", "movement"); tOrder = new AString("SAIL"); - forlist(&so->dirs) { - d = (MoveDir *) elem; + for(auto d: so->dirs) { *tOrder += " "; - if (d->dir == MOVE_PAUSE) + if (d.dir == MOVE_PAUSE) *tOrder += "P"; else - *tOrder += DirectionAbrs[d->dir]; + *tOrder += DirectionAbrs[d.dir]; } u->oldorders.push_front(tOrder->const_str()); } @@ -220,11 +212,10 @@ void Game::RunMovementOrders() Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) { - SailOrder *o = (SailOrder *) cap->monthorders; + std::shared_ptr o = std::dynamic_pointer_cast(cap->monthorders); int stop, wgt, slr, nomove, cost; AList facs; ARegion *newreg; - MoveDir *x; Location *loc; fleet->movepoints += fleet->GetFleetSpeed(0); @@ -257,15 +248,15 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) } else if (slr < fleet->GetFleetSize()) { cap->error("SAIL: Not enough sailors."); stop = 1; - } else if (!o->dirs.Num()) { + } else if (!o->dirs.size()) { // no more moves? stop = 1; } else { - x = (MoveDir *) o->dirs.First(); - if (x->dir == MOVE_PAUSE) { + MoveDir x = o->dirs[0]; + if (x.dir == MOVE_PAUSE) { newreg = reg; } else { - newreg = reg->neighbors[x->dir]; + newreg = reg->neighbors[x.dir]; } cost = 1; @@ -279,7 +270,7 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) !newreg->clearskies) cost = 2; } - if (x->dir == MOVE_PAUSE) { + if (x.dir == MOVE_PAUSE) { cost = 1; } // We probably shouldn't see terrain-based errors until @@ -289,7 +280,7 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) if (!newreg) { cap->error("SAIL: Can't sail that way."); stop = 1; - } else if (x->dir == MOVE_PAUSE) { + } else if (x.dir == MOVE_PAUSE) { // Can always do maneuvers } else if (fleet->flying < 1 && !newreg->IsCoastalOrLakeside()) { cap->error("SAIL: Can't sail inland."); @@ -299,8 +290,8 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) (TerrainDefs[newreg->type].similar_type != R_OCEAN)) { cap->error("SAIL: Can't sail inland."); stop = 1; - } else if (fleet->SailThroughCheck(x->dir) < 1) { - cap->error("SAIL: Could not sail " + DirectionStrs[x->dir] + " from " + + } else if (fleet->SailThroughCheck(x.dir) < 1) { + cap->error("SAIL: Could not sail " + DirectionStrs[x.dir] + " from " + reg->ShortPrint().const_str() + ". Cannot sail through land."); stop = 1; } @@ -322,7 +313,7 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) } } if (!has_key) { - cap->error("SAIL: Can't sail " + DirectionStrs[x->dir] + " from " + + cap->error("SAIL: Can't sail " + DirectionStrs[x.dir] + " from " + reg->ShortPrint().const_str() + " due to mystical barrier."); stop = 1; } @@ -330,9 +321,9 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) if (!stop) { fleet->movepoints -= cost * Globals->MAX_SPEED; - if (x->dir != MOVE_PAUSE) { + if (x.dir != MOVE_PAUSE) { fleet->MoveObject(newreg); - fleet->SetPrevDir(reg->GetRealDirComp(x->dir)); + fleet->SetPrevDir(reg->GetRealDirComp(x.dir)); } for(auto unit: fleet->units) { unit->moved += cost; @@ -344,8 +335,7 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) if (unit->monthorders->type == O_SAIL) unit->Practice(S_SAILING); if (unit->monthorders->type == O_MOVE) { - delete unit->monthorders; - unit->monthorders = 0; + unit->monthorders = nullptr; } } unit->DiscardUnfinishedShips(); @@ -359,15 +349,14 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) forlist_reuse(&facs) { Faction * f = ((FactionPtr *) elem)->ptr; string temp = fleet->name->const_str(); - temp += (x->dir == MOVE_PAUSE ? " performs maneuvers in " : " sails from ") + + temp += (x.dir == MOVE_PAUSE ? " performs maneuvers in " : " sails from ") + string(reg->ShortPrint().const_str()); - if(x->dir != MOVE_PAUSE) { + if(x.dir != MOVE_PAUSE) { temp += " to " + string(newreg->ShortPrint().const_str()); } f->event(temp, "sail"); } - if (Globals->TRANSIT_REPORT != GameDefs::REPORT_NOTHING && - x->dir != MOVE_PAUSE) { + if (Globals->TRANSIT_REPORT != GameDefs::REPORT_NOTHING && x.dir != MOVE_PAUSE) { if (!(cap->faction->is_npc)) newreg->visited = 1; for(auto unit: fleet->units) { // Everyone onboard gets to see the sights @@ -377,7 +366,7 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) f = (Farsight *)elem; if (f->unit == unit) { // We moved into here this turn - f->exits_used[x->dir] = 1; + f->exits_used[x.dir] = 1; } } // And mark the hex being entered @@ -385,7 +374,7 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) f->faction = unit->faction; f->level = 0; f->unit = unit; - f->exits_used[reg->GetRealDirComp(x->dir)] = 1; + f->exits_used[reg->GetRealDirComp(x.dir)] = 1; newreg->passers.Add(f); } } @@ -396,18 +385,15 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap) cap->faction->event(temp, "sail"); stop = 1; } - o->dirs.Remove(x); - delete x; + std::erase(o->dirs, x); } } if (stop) { // Clear out everyone's orders for(auto unit: fleet->units) { - if (unit->monthorders && - unit->monthorders->type == O_SAIL) { - delete unit->monthorders; - unit->monthorders = 0; + if (unit->monthorders && unit->monthorders->type == O_SAIL) { + unit->monthorders = nullptr; } } } @@ -429,8 +415,7 @@ void Game::RunTeachOrders() if (u->monthorders) { if (u->monthorders->type == O_TEACH) { Do1TeachOrder(r,u); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; } } } @@ -438,7 +423,7 @@ void Game::RunTeachOrders() } } -void Game::Do1TeachOrder(ARegion * reg,Unit * unit) +void Game::Do1TeachOrder(ARegion * reg, Unit * unit) { /* First pass, find how many to teach */ if (Globals->LEADERS_EXIST && !unit->IsLeader()) { @@ -452,7 +437,7 @@ void Game::Do1TeachOrder(ARegion * reg,Unit * unit) } int students = 0; - TeachOrder * order = (TeachOrder *) unit->monthorders; + std::shared_ptr order = std::dynamic_pointer_cast(unit->monthorders); reg->deduplicate_unit_list(order->targets, unit->faction->num); for (auto unitid = order->targets.begin(); unitid != order->targets.end(); ) { Unit *target = reg->get_unit_id(*unitid, unit->faction->num); @@ -471,7 +456,8 @@ void Game::Do1TeachOrder(ARegion * reg,Unit * unit) unitid = order->targets.erase(unitid); continue; } - int sk = ((StudyOrder *) target->monthorders)->skill; + std::shared_ptr o = std::dynamic_pointer_cast(target->monthorders); + int sk = o->skill; if (unit->GetRealSkill(sk) <= target->GetRealSkill(sk)) { unit->error(string("TEACH: ") + target->name->const_str() + " is not studying a skill you can teach."); unitid = order->targets.erase(unitid); @@ -500,7 +486,7 @@ void Game::Do1TeachOrder(ARegion * reg,Unit * unit) days -= tempdays; students -= umen; - StudyOrder * o = (StudyOrder *) u->monthorders; + std::shared_ptr o = std::dynamic_pointer_cast(u->monthorders); o->days += tempdays; if (o->days > 30 * umen) { days += o->days - 30 * umen; @@ -520,8 +506,7 @@ void Game::Run1BuildOrder(ARegion *r, Object *obj, Unit *u) if (!Globals->BUILD_NO_TRADE && !ActivityCheck(r, u->faction, FactionActivity::TRADE)) { u->error("BUILD: Faction can't produce in that many regions."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return; } @@ -533,43 +518,38 @@ void Game::Run1BuildOrder(ARegion *r, Object *obj, Unit *u) } if (!buildobj || buildobj->type == O_DUMMY) { u->error("BUILD: Nothing to build."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return; } - AString skname = ObjectDefs[buildobj->type].skill; + + int type = buildobj->type; + AString skname = ObjectDefs[type].skill; int sk = LookupSkill(&skname); if (sk == -1) { - u->error("BUILD: Can't build that."); - delete u->monthorders; - u->monthorders = 0; + u->error("BUILD: Can't build " + string(ObjectDefs[type].name) + "."); + u->monthorders = nullptr; return; } int usk = u->GetSkill(sk); if (usk < ObjectDefs[buildobj->type].level) { - u->error("BUILD: Can't build that."); - delete u->monthorders; - u->monthorders = 0; + u->error("BUILD: Can't build " + string(ObjectDefs[type].name) + "."); + u->monthorders = nullptr; return; } int needed = buildobj->incomplete; - int type = buildobj->type; // AS - if (((ObjectDefs[type].flags & ObjectType::NEVERDECAY) || !Globals->DECAY) && - needed < 1) { - u->error("BUILD: Object is finished."); - delete u->monthorders; - u->monthorders = 0; + if (((ObjectDefs[type].flags & ObjectType::NEVERDECAY) || !Globals->DECAY) && needed < 1) { + u->error("BUILD: " + string(ObjectDefs[type].name) + " is finished."); + u->monthorders = nullptr; return; } // AS if (needed <= -(ObjectDefs[type].maxMaintenance)) { - u->error("BUILD: Object does not yet require maintenance."); - delete u->monthorders; - u->monthorders = 0; + u->error("BUILD: " + string(ObjectDefs[type].name) + " does not yet require maintenance."); + u->monthorders = nullptr; return; } @@ -583,8 +563,7 @@ void Game::Run1BuildOrder(ARegion *r, Object *obj, Unit *u) if (itn == 0) { u->error("BUILD: Don't have the required materials."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return; } @@ -648,8 +627,7 @@ void Game::Run1BuildOrder(ARegion *r, Object *obj, Unit *u) } u->Practice(sk); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; } /* Alternate processing for building item-type ship @@ -672,10 +650,9 @@ void Game::RunBuildShipOrder(ARegion * r,Object * obj,Unit * u) // get needed to complete maxbuild = 0; - if ((u->monthorders) && - (u->monthorders->type == O_BUILD)) { - BuildOrder *border = (BuildOrder *) u->monthorders; - maxbuild = border->needtocomplete; + if ((u->monthorders) && (u->monthorders->type == O_BUILD)) { + std::shared_ptr border = std::dynamic_pointer_cast(u->monthorders); + maxbuild = border->needtocomplete; } if (maxbuild < 1) { // Our helpers have already finished the hard work, so @@ -715,8 +692,7 @@ void Game::RunBuildShipOrder(ARegion * r,Object * obj,Unit * u) "%) in " + r->ShortPrint().const_str() + ".", "build", r); } - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; } void Game::AddNewBuildings(ARegion *r) @@ -727,7 +703,7 @@ void Game::AddNewBuildings(ARegion *r) for(auto u: obj->units) { if (u->monthorders) { if (u->monthorders->type == O_BUILD) { - BuildOrder *o = (BuildOrder *)u->monthorders; + std::shared_ptr o = std::dynamic_pointer_cast(u->monthorders); // If BUILD order was marked for creating new building // in parse phase, it is time to create one now. @@ -769,30 +745,26 @@ void Game::RunBuildHelpers(ARegion *r) for(auto u: obj->units) { if (u->monthorders) { if (u->monthorders->type == O_BUILD) { - BuildOrder *o = (BuildOrder *)u->monthorders; + std::shared_ptr o = std::dynamic_pointer_cast(u->monthorders); Object *tarobj = NULL; if (o->target) { Unit *target = r->get_unit_id(*(o->target),u->faction->num); if (!target) { u->error("BUILD: No such unit to help."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; continue; } // Make sure that unit is building if (!target->monthorders || target->monthorders->type != O_BUILD) { u->error("BUILD: Unit isn't building."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; continue; } // Make sure that unit considers you friendly! if (target->faction->get_attitude(u->faction->num) < A_FRIENDLY) { - u->error("BUILD: Unit you are helping rejects " - "your help."); - delete u->monthorders; - u->monthorders = 0; + u->error("BUILD: Unit you are helping rejects your help."); + u->monthorders = nullptr; continue; } if (target->build == 0) { @@ -809,15 +781,14 @@ void Game::RunBuildHelpers(ARegion *r) int skill = LookupSkill(&skname); int level = u->GetSkill(skill); int needed = 0; - if ((target->monthorders) && - (target->monthorders->type == O_BUILD)) { - BuildOrder *border = (BuildOrder *) target->monthorders; - needed = border->needtocomplete; + if ((target->monthorders) && (target->monthorders->type == O_BUILD)) { + std::shared_ptr border = + std::dynamic_pointer_cast(target->monthorders); + needed = border->needtocomplete; } if (needed < 1) { u->error("BUILD: Construction is already complete."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; continue; } int output = ShipConstruction(r, u, target, level, needed, ship); @@ -836,19 +807,19 @@ void Game::RunBuildHelpers(ARegion *r) if (unfinished > 0) { target->items.SetNum(ship, unfinished); - if ((target->monthorders) && - (target->monthorders->type == O_BUILD)) { - BuildOrder *border = (BuildOrder *) target->monthorders; - border->needtocomplete = unfinished; + if ((target->monthorders) && (target->monthorders->type == O_BUILD)) { + std::shared_ptr border = + std::dynamic_pointer_cast(target->monthorders); + border->needtocomplete = unfinished; } } else { // CreateShip(r, target, ship); // don't create the ship yet; leave that for the unit we're helping target->items.SetNum(ship, 1); - if ((target->monthorders) && - (target->monthorders->type == O_BUILD)) { - BuildOrder *border = (BuildOrder *) target->monthorders; - border->needtocomplete = 0; + if ((target->monthorders) && (target->monthorders->type == O_BUILD)) { + std::shared_ptr border = + std::dynamic_pointer_cast(target->monthorders); + border->needtocomplete = 0; } } int percent = 100 * output / ItemDefs[ship].pMonths; @@ -862,13 +833,9 @@ void Game::RunBuildHelpers(ARegion *r) if ((tarobj != NULL) && (u->object != tarobj)) u->MoveUnit(tarobj); } else { - Object *buildobj; if (u->build > 0) { - buildobj = r->GetObject(u->build); - if (buildobj && - buildobj != r->GetDummy() && - buildobj != u->object) - { + Object *buildobj = r->GetObject(u->build); + if (buildobj && buildobj != r->GetDummy() && buildobj != u->object) { u->MoveUnit(buildobj); } } @@ -918,15 +885,13 @@ int Game::ShipConstruction(ARegion *r, Unit *u, Unit *target, int level, int nee { if (!Globals->BUILD_NO_TRADE && !ActivityCheck(r, u->faction, FactionActivity::TRADE)) { u->error("BUILD: Faction can't produce in that many regions."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return 0; } if (level < ItemDefs[ship].pLevel) { u->error("BUILD: Can't build that."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return 0; } @@ -936,13 +901,7 @@ int Game::ShipConstruction(ARegion *r, Unit *u, Unit *target, int level, int nee int number = u->GetMen() * level + u->GetProductionBonus(ship); // find the max we can possibly produce based on man-months of labor - int maxproduced; - if (ItemDefs[ship].flags & ItemType::SKILLOUT) - maxproduced = u->GetMen(); - else - // don't adjust for pMonths - // - pMonths represents total requirement - maxproduced = number; + int maxproduced = (ItemDefs[ship].flags & ItemType::SKILLOUT) ? u->GetMen() : number; // adjust maxproduced for items needed until completion if (needed < maxproduced) maxproduced = needed; @@ -967,8 +926,7 @@ int Game::ShipConstruction(ARegion *r, Unit *u, Unit *target, int level, int nee // no required materials? if (count < 1) { u->error("BUILD: Don't have the required materials."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return 0; } @@ -1007,8 +965,7 @@ int Game::ShipConstruction(ARegion *r, Unit *u, Unit *target, int level, int nee // no required materials? if (maxproduced < 1) { u->error("BUILD: Don't have the required materials."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return 0; } @@ -1028,8 +985,7 @@ int Game::ShipConstruction(ARegion *r, Unit *u, Unit *target, int level, int nee if (ItemDefs[ship].flags & ItemType::SKILLOUT) output *= level; - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return output; } @@ -1048,7 +1004,7 @@ void Game::RunMonthOrders() void Game::RunUnitProduce(ARegion *r, Unit *u) { - ProduceOrder *o = (ProduceOrder *) u->monthorders; + std::shared_ptr o = std::dynamic_pointer_cast(u->monthorders); for (const auto& p : r->products) { // PRODUCE orders for producing goods from the land @@ -1059,33 +1015,29 @@ void Game::RunUnitProduce(ARegion *r, Unit *u) } if (o->item == I_SILVER) { - if (!o->quiet) - u->error("Can't do that in this region."); - delete u->monthorders; - u->monthorders = 0; + if (!o->quiet) u->error("Can't do that in this region."); + u->monthorders = nullptr; return; } if (o->item == -1 || ItemDefs[o->item].flags & ItemType::DISABLED) { - u->error("PRODUCE: Can't produce that."); - delete u->monthorders; - u->monthorders = 0; + string itemname = o->item == -1 ? "that" : ItemString(o->item, 1, ALWAYSPLURAL); + u->error("PRODUCE: Can't produce " + itemname + "."); + u->monthorders =nullptr; return; } int input = ItemDefs[o->item].pInput[0].item; if (input == -1) { - u->error("PRODUCE: Can't produce that."); - delete u->monthorders; - u->monthorders = 0; + u->error("PRODUCE: Can't produce " + string(ItemString(o->item, 1, ALWAYSPLURAL)) + "."); + u->monthorders = nullptr; return; } int level = u->GetSkill(o->skill); if (level < ItemDefs[o->item].pLevel) { - u->error("PRODUCE: Can't produce that."); - delete u->monthorders; - u->monthorders = 0; + u->error("PRODUCE: Can't produce " + string(ItemString(o->item, 1, ALWAYSPLURAL)) + "."); + u->monthorders = nullptr; return; } @@ -1094,8 +1046,7 @@ void Game::RunUnitProduce(ARegion *r, Unit *u) if (!ActivityCheck(r, u->faction, FactionActivity::TRADE)) { u->error("PRODUCE: Faction can't produce in that many regions."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return; } @@ -1183,18 +1134,13 @@ void Game::RunUnitProduce(ARegion *r, Unit *u) u->Practice(o->skill); o->target -= output; if (o->target > 0) { - TurnOrder *tOrder = new TurnOrder; - AString order; + std::shared_ptr tOrder = std::make_shared(); + string order = "PRODUCE " + to_string(o->target) + " " + ItemDefs[o->item].abr; tOrder->repeating = 0; - order = "PRODUCE "; - order += o->target; - order += " "; - order += ItemDefs[o->item].abr; - tOrder->turnOrders.push_back(order.const_str()); - u->turnorders.Insert(tOrder); - } - delete u->monthorders; - u->monthorders = 0; + tOrder->turnOrders.push_back(order); + u->turnorders.push_back(tOrder); + } + u->monthorders = nullptr; } void Game::RunProduceOrders(ARegion * r) @@ -1224,7 +1170,7 @@ int Game::ValidProd(Unit * u,ARegion * r, Production * p) { if (u->monthorders->type != O_PRODUCE) return 0; - ProduceOrder * po = (ProduceOrder *) u->monthorders; + std::shared_ptr po = std::dynamic_pointer_cast(u->monthorders); if (p->itemtype == po->item && p->skill == po->skill) { if (p->skill == -1) { /* Factor for fractional productivity: 10 */ @@ -1234,8 +1180,7 @@ int Game::ValidProd(Unit * u,ARegion * r, Production * p) int level = u->GetSkill(p->skill); if (level < ItemDefs[p->itemtype].pLevel) { u->error("PRODUCE: Unit isn't skilled enough."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return 0; } @@ -1245,8 +1190,7 @@ int Game::ValidProd(Unit * u,ARegion * r, Production * p) // if (p->itemtype != I_SILVER && !ActivityCheck(r, u->faction, FactionActivity::TRADE)) { u->error("PRODUCE: Faction can't produce in that many regions."); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; return 0; } @@ -1295,7 +1239,7 @@ void Game::RunAProduction(ARegion * r, Production * p) if (!u->monthorders || u->monthorders->type != O_PRODUCE) continue; - ProduceOrder * po = (ProduceOrder *) u->monthorders; + std::shared_ptr po = std::dynamic_pointer_cast(u->monthorders); if (po->skill != p->skill || po->item != p->itemtype) continue; @@ -1323,15 +1267,11 @@ void Game::RunAProduction(ARegion * r, Production * p) p->activity += ubucks; po->target -= ubucks; if (po->target > 0) { - TurnOrder *tOrder = new TurnOrder; - AString order; + std::shared_ptr tOrder = std::make_shared(); tOrder->repeating = 0; - order = "PRODUCE "; - order += po->target; - order += " "; - order += ItemDefs[po->item].abr; - tOrder->turnOrders.push_back(order.const_str()); - u->turnorders.Insert(tOrder); + string order = "PRODUCE " + to_string(po->target) + " " + ItemDefs[po->item].abr; + tOrder->turnOrders.push_back(order); + u->turnorders.push_back(tOrder); } /* Show in unit's events section */ @@ -1361,8 +1301,7 @@ void Game::RunAProduction(ARegion * r, Production * p) r->ShortPrint().const_str() + ".", "produce", r); u->Practice(po->skill); } - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; if (questcomplete) { u->event("You have completed a quest! " + quest_rewards, "quest"); } @@ -1378,8 +1317,7 @@ void Game::RunStudyOrders(ARegion * r) if (u->monthorders) { if (u->monthorders->type == O_STUDY) { Do1StudyOrder(u,obj); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; } } } @@ -1393,8 +1331,7 @@ void Game::RunIdleOrders(ARegion *r) for(auto u: obj->units) { if (u->monthorders && u->monthorders->type == O_IDLE) { u->event("Sits idle.", "idle"); - delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; } } } @@ -1402,16 +1339,16 @@ void Game::RunIdleOrders(ARegion *r) void Game::Do1StudyOrder(Unit *u,Object *obj) { - StudyOrder * o = (StudyOrder *) u->monthorders; + std::shared_ptr o = std::dynamic_pointer_cast(u->monthorders); int sk, cost, reset_man, skmax, taughtdays, days; string str; reset_man = -1; sk = o->skill; if (sk == -1 || SkillDefs[sk].flags & SkillType::DISABLED || - (SkillDefs[sk].flags & SkillType::APPRENTICE && - !Globals->APPRENTICES_EXIST)) { - u->error("STUDY: Can't study that."); + (SkillDefs[sk].flags & SkillType::APPRENTICE && !Globals->APPRENTICES_EXIST)) { + string skname = (sk == -1) ? "that" : SkillDefs[sk].name; + u->error("STUDY: Can't study " + skname + "."); return; } @@ -1574,12 +1511,11 @@ void Game::Do1StudyOrder(Unit *u,Object *obj) // study to level order if (o->level != -1) { if (u->GetRealSkill(sk) < o->level) { - TurnOrder *tOrder = new TurnOrder; - AString order; + std::shared_ptr tOrder = std::make_shared(); tOrder->repeating = 0; - order = AString("STUDY ") + SkillDefs[sk].abbr + " " + o->level; - tOrder->turnOrders.push_back(order.const_str()); - u->turnorders.Insert(tOrder); + string order = "STUDY " + string(SkillDefs[sk].abbr) + " " + to_string(o->level); + tOrder->turnOrders.push_back(order); + u->turnorders.push_front(tOrder); } else { string msg = "Completes study to level " + to_string(o->level) + " in " + SkillDefs[sk].name + "."; u->event(msg, "study"); @@ -1595,19 +1531,15 @@ void Game::Do1StudyOrder(Unit *u,Object *obj) void Game::DoMoveEnter(Unit *unit,ARegion *region,Object **obj) { - MoveOrder * o; - if (!unit->monthorders || - ((unit->monthorders->type != O_MOVE) && - (unit->monthorders->type != O_ADVANCE))) + if (!unit->monthorders || ((unit->monthorders->type != O_MOVE) && (unit->monthorders->type != O_ADVANCE))) return; - o = (MoveOrder *) unit->monthorders; - while (o->dirs.Num()) { - MoveDir * x = (MoveDir *) o->dirs.First(); - int i = x->dir; + std::shared_ptr o = std::dynamic_pointer_cast(unit->monthorders); + while (o->dirs.size()) { + MoveDir x = o->dirs[0]; + int i = x.dir; if (i != MOVE_OUT && i < MOVE_ENTER) return; - o->dirs.Remove(x); - delete x; + std::erase(o->dirs, x); if (i >= MOVE_ENTER) { Object * to = region->GetObject(i - MOVE_ENTER); @@ -1627,8 +1559,7 @@ void Game::DoMoveEnter(Unit *unit,ARegion *region,Object **obj) continue; } - if (forbid && region->IsSafeRegion()) - { + if (forbid && region->IsSafeRegion()) { unit->error("ENTER: No battles allowed in safe regions."); continue; } @@ -1639,8 +1570,7 @@ void Game::DoMoveEnter(Unit *unit,ARegion *region,Object **obj) } int done = 0; - while (forbid) - { + while (forbid) { int result = RunBattle(region, unit, forbid, 0, 0); if (result == BATTLE_IMPOSSIBLE) { unit->error(string("ENTER: Unable to attack ") + forbid->name->const_str()); @@ -1661,8 +1591,7 @@ void Game::DoMoveEnter(Unit *unit,ARegion *region,Object **obj) } else { if (i == MOVE_OUT) { if (TerrainDefs[region->type].similar_type == R_OCEAN && - (!unit->CanSwim() || - unit->GetFlag(FLAG_NOCROSS_WATER))) + (!unit->CanSwim() || unit->GetFlag(FLAG_NOCROSS_WATER))) { unit->error("MOVE: Can't leave ship."); continue; @@ -1678,8 +1607,6 @@ void Game::DoMoveEnter(Unit *unit,ARegion *region,Object **obj) Location *Game::DoAMoveOrder(Unit *unit, ARegion *region, Object *obj) { - MoveOrder *o = (MoveOrder *) unit->monthorders; - MoveDir *x; ARegion *newreg; string road, temp; @@ -1688,15 +1615,15 @@ Location *Game::DoAMoveOrder(Unit *unit, ARegion *region, Object *obj) Location *loc; const char *prevented = nullptr; - if (!o->dirs.Num()) { - delete o; - unit->monthorders = 0; + std::shared_ptr o = std::dynamic_pointer_cast(unit->monthorders); + if (!o->dirs.size()) { + unit->monthorders = nullptr; return 0; } - x = (MoveDir *) o->dirs.First(); + MoveDir x = o->dirs[0]; - if (x->dir == MOVE_IN) { + if (x.dir == MOVE_IN) { if (obj->inner == -1) { unit->error("MOVE: Can't move IN there."); goto done_moving; @@ -1761,10 +1688,10 @@ Location *Game::DoAMoveOrder(Unit *unit, ARegion *region, Object *obj) newreg = candidates[index]; } } - } else if (x->dir == MOVE_PAUSE) { + } else if (x.dir == MOVE_PAUSE) { newreg = region; } else { - newreg = region->neighbors[x->dir]; + newreg = region->neighbors[x.dir]; } if (!newreg) { @@ -1794,8 +1721,8 @@ Location *Game::DoAMoveOrder(Unit *unit, ARegion *region, Object *obj) road = ""; startmove = 0; movetype = unit->MoveType(region); - cost = newreg->MoveCost(movetype, region, x->dir, &road); - if (x->dir == MOVE_PAUSE) + cost = newreg->MoveCost(movetype, region, x.dir, &road); + if (x.dir == MOVE_PAUSE) cost = 1; if (region->type == R_NEXUS) { cost = 1; @@ -1825,12 +1752,9 @@ Location *Game::DoAMoveOrder(Unit *unit, ARegion *region, Object *obj) // have stored movement points, then add in those stored // movement points, but make sure that these are only used // towards entering the hex we were trying to enter - if (!unit->moved && - unit->movepoints >= Globals->MAX_SPEED && - unit->movepoints < cost * Globals->MAX_SPEED && - x->dir == unit->savedmovedir) { - while (unit->savedmovement > 0 && - unit->movepoints < cost * Globals->MAX_SPEED) { + if (!unit->moved && (unit->movepoints >= Globals->MAX_SPEED) && + (unit->movepoints < cost * Globals->MAX_SPEED) && x.dir == unit->savedmovedir) { + while ((unit->savedmovement > 0) && (unit->movepoints < cost * Globals->MAX_SPEED)) { unit->movepoints += Globals->MAX_SPEED; unit->savedmovement--; } @@ -1841,19 +1765,16 @@ Location *Game::DoAMoveOrder(Unit *unit, ARegion *region, Object *obj) if (unit->movepoints < cost * Globals->MAX_SPEED) return 0; - if (x->dir == MOVE_PAUSE) { - unit->event("Pauses to admire the scenery in " + string(region->ShortPrint().const_str()) + - ".", "movement"); + if (x.dir == MOVE_PAUSE) { + unit->event("Pauses to admire the scenery in " + string(region->ShortPrint().const_str()) + ".", "movement"); unit->movepoints -= cost * Globals->MAX_SPEED; unit->moved += cost; - o->dirs.Remove(x); - delete x; + std::erase(o->dirs, x); return 0; } if ((TerrainDefs[newreg->type].similar_type == R_OCEAN) && - (!unit->CanSwim() || - unit->GetFlag(FLAG_NOCROSS_WATER))) { + (!unit->CanSwim() || unit->GetFlag(FLAG_NOCROSS_WATER))) { unit->event("Discovers that " + string(newreg->ShortPrint().const_str()) + " is " + TerrainDefs[newreg->type].name + ".", "movement"); goto done_moving; @@ -1932,8 +1853,8 @@ Location *Game::DoAMoveOrder(Unit *unit, ARegion *region, Object *obj) f = (Farsight *)elem; if (f->unit == unit) { // We moved into here this turn - if (x->dir < MOVE_IN) { - f->exits_used[x->dir] = 1; + if (x.dir < MOVE_IN) { + f->exits_used[x.dir] = 1; } } } @@ -1942,16 +1863,15 @@ Location *Game::DoAMoveOrder(Unit *unit, ARegion *region, Object *obj) f->faction = unit->faction; f->level = 0; f->unit = unit; - if (x->dir < MOVE_IN) { - f->exits_used[region->GetRealDirComp(x->dir)] = 1; + if (x.dir < MOVE_IN) { + f->exits_used[region->GetRealDirComp(x.dir)] = 1; } newreg->passers.Add(f); } region = newreg; - o->dirs.Remove(x); - delete x; + std::erase(o->dirs, x); loc = new Location; loc->unit = unit; @@ -1960,7 +1880,6 @@ Location *Game::DoAMoveOrder(Unit *unit, ARegion *region, Object *obj) return loc; done_moving: - delete o; - unit->monthorders = 0; - return 0; + unit->monthorders = nullptr; + return nullptr; } diff --git a/orders.cpp b/orders.cpp index 489275c6..845456b6 100644 --- a/orders.cpp +++ b/orders.cpp @@ -23,6 +23,7 @@ // // END A3HEADER #include "orders.h" +#include "unit.h" char const *od[] = { "#atlantis", @@ -256,6 +257,14 @@ FindOrder::~FindOrder() { } +StealthOrder::StealthOrder() +{ +} + +StealthOrder::~StealthOrder() +{ +} + StealOrder::StealOrder() { type = O_STEAL; diff --git a/orders.h b/orders.h index b9fb9bab..55c8be27 100644 --- a/orders.h +++ b/orders.h @@ -25,39 +25,13 @@ #ifndef ORDERS_CLASS #define ORDERS_CLASS -class Order; -class AttackOrder; -class MoveOrder; -class WithdrawOrder; -class GiveOrder; -class StudyOrder; -class TeachOrder; -class SellOrder; -class BuyOrder; -class ProduceOrder; -class BuildOrder; -class SailOrder; -class FindOrder; -class StealOrder; -class AssassinateOrder; -class CastOrder; -class CastMindOrder; -class CastRegionOrder; -class TeleportOrder; -class ForgetOrder; -class EvictOrder; -class BankOrder; -class IdleOrder; -class TransportOrder; -class AnnihilateOrder; -class SacrificeOrder; - -#include "unit.h" #include "gamedefs.h" #include "astring.h" -#include "alist.h" #include +// Forward declarations +class UnitId; + enum { O_ATLANTIS, O_END, @@ -145,11 +119,12 @@ enum { /* Enter is MOVE_ENTER + num of object */ #define MOVE_ENTER 100 + extern char const ** OrderStrs; int Parse1Order(AString *); -class Order : public AListElem { +class Order { public: Order(); virtual ~Order(); @@ -158,9 +133,13 @@ class Order : public AListElem { int quiet; }; -class MoveDir : public AListElem { - public: - int dir; +class MoveDir { +public: + MoveDir(int d) : dir(d) {} + ~MoveDir() {} + inline int operator==(const MoveDir &d) { return dir == d.dir; } + + int dir; }; class MoveOrder : public Order { @@ -169,7 +148,7 @@ class MoveOrder : public Order { ~MoveOrder(); int advancing; - AList dirs; + std::vector dirs; }; class WithdrawOrder : public Order { @@ -266,7 +245,7 @@ class SailOrder : public Order { SailOrder(); ~SailOrder(); - AList dirs; + std::vector dirs; }; class FindOrder : public Order { @@ -277,16 +256,23 @@ class FindOrder : public Order { int find; }; -class StealOrder : public Order { +class StealthOrder : public Order { + public: + StealthOrder(); + virtual ~StealthOrder(); + + UnitId *target; +}; + +class StealOrder : public StealthOrder { public: StealOrder(); ~StealOrder(); - UnitId *target; int item; }; -class AssassinateOrder : public Order { +class AssassinateOrder : public StealthOrder { public: AssassinateOrder(); ~AssassinateOrder(); @@ -329,7 +315,7 @@ class TurnOrder : public Order { class CastOrder : public Order { public: CastOrder(); - ~CastOrder(); + virtual ~CastOrder(); int spell; int level; @@ -346,7 +332,7 @@ class CastMindOrder : public CastOrder { class CastRegionOrder : public CastOrder { public: CastRegionOrder(); - ~CastRegionOrder(); + virtual ~CastRegionOrder(); int xloc, yloc, zloc; }; @@ -411,7 +397,7 @@ class TransportOrder : public Order { int except; int distance; - enum TransportPhase { + enum class TransportPhase { SHIP_TO_QM, INTER_QM_TRANSPORT, DISTRIBUTE_FROM_QM diff --git a/parseorders.cpp b/parseorders.cpp index dab2fa5c..ee281207 100644 --- a/parseorders.cpp +++ b/parseorders.cpp @@ -24,6 +24,7 @@ // END A3HEADER #include +#include #include "game.h" #include "gameio.h" @@ -406,7 +407,6 @@ void Game::ParseOrders(int faction, istream& f, OrdersCheck *pCheck) break; case O_ENDTURN: if (unit && unit->inTurnBlock) { - if (unit->monthorders) delete unit->monthorders; unit->monthorders = unit->presentMonthOrders; unit->presentMonthOrders = 0; unit->taxing = unit->presentTaxing; @@ -921,9 +921,9 @@ void Game::ProcessForgetOrder(Unit *u, AString *o, OrdersCheck *pCheck) } if (!pCheck) { - ForgetOrder *ord = new ForgetOrder; + std::shared_ptr ord = std::make_shared(); ord->skill = sk; - u->forgetorders.Add(ord); + u->forgetorders.push_back(ord); } } @@ -936,9 +936,8 @@ void Game::ProcessEntertainOrder(Unit *unit, OrdersCheck *pCheck) string err = string("ENTERTAIN: Overwriting previous ") + (unit->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, unit, 0, err); - if (unit->monthorders) delete unit->monthorders; } - ProduceOrder *o = new ProduceOrder; + std::shared_ptr o = std::make_shared(); o->item = I_SILVER; o->skill = S_ENTERTAINMENT; o->target = 0; @@ -1238,10 +1237,9 @@ void Game::ProcessAssassinateOrder(Unit *u, AString *o, OrdersCheck *pCheck) return; } if (!pCheck) { - if (u->stealorders) delete u->stealorders; - AssassinateOrder *ord = new AssassinateOrder; + std::shared_ptr ord = std::make_shared(); ord->target = id; - u->stealorders = ord; + u->stealthorders = ord; } } @@ -1272,11 +1270,10 @@ void Game::ProcessStealOrder(Unit *u, AString *o, OrdersCheck *pCheck) delete id; return; } - StealOrder *ord = new StealOrder; + std::shared_ptr ord = std::make_shared(); ord->target = id; ord->item = i; - if (u->stealorders) delete u->stealorders; - u->stealorders = ord; + u->stealthorders = ord; } } @@ -1362,9 +1359,9 @@ void Game::ProcessFindOrder(Unit *u, AString *o, OrdersCheck *pCheck) return; } if (!pCheck) { - FindOrder *f = new FindOrder; + std::shared_ptr f = std::make_shared(); f->find = n; - u->findorders.Add(f); + u->findorders.push_back(f); } } @@ -1441,8 +1438,7 @@ void Game::ProcessTaxOrder(Unit *u, OrdersCheck *pCheck) return; } if (Globals->TAX_PILLAGE_MONTH_LONG && u->monthorders) { - delete u->monthorders; - u->monthorders = NULL; + u->monthorders = nullptr; string err = string("TAX: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); } @@ -1457,8 +1453,7 @@ void Game::ProcessPillageOrder(Unit *u, OrdersCheck *pCheck) return; } if (Globals->TAX_PILLAGE_MONTH_LONG && u->monthorders) { - delete u->monthorders; - u->monthorders = NULL; + u->monthorders = nullptr; string err = string("PILLAGE: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); } @@ -1512,7 +1507,7 @@ void Game::ProcessEnterOrder(Unit *u, AString *o, OrdersCheck *pCheck) void Game::ProcessBuildOrder(Unit *unit, AString *o, OrdersCheck *pCheck) { AString * token = o->gettoken(); - BuildOrder * order = new BuildOrder; + std::shared_ptr order = std::make_shared(); int maxbuild; // 'incomplete' for ships: @@ -1623,12 +1618,10 @@ void Game::ProcessBuildOrder(Unit *unit, AString *o, OrdersCheck *pCheck) // Now do all of the generic bits... // Check that the unit isn't doing anything else important - if (unit->monthorders || - (Globals->TAX_PILLAGE_MONTH_LONG && - ((unit->taxing == TAX_TAX) || - (unit->taxing == TAX_PILLAGE)))) { - if (unit->monthorders) delete unit->monthorders; - string err = string("BUILD: Overwriting previous ") + (unit->inTurnBlock ? "DELAYED " : "") + "month-long order."; + if (unit->monthorders || (Globals->TAX_PILLAGE_MONTH_LONG && + ((unit->taxing == TAX_TAX) || (unit->taxing == TAX_PILLAGE)))) { + string err = string("BUILD: Overwriting previous ") + + (unit->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, unit, 0, err); } @@ -1642,7 +1635,7 @@ void Game::ProcessAttackOrder(Unit *u, AString *o, OrdersCheck *pCheck) UnitId *id = ParseUnit(o); while (id && id->unitnum != -1) { if (!pCheck) { - if (!u->attackorders) u->attackorders = new AttackOrder; + if (!u->attackorders) u->attackorders = std::make_shared(); u->attackorders->targets.push_back(*id); delete id; } @@ -1677,10 +1670,10 @@ void Game::ProcessSellOrder(Unit *u, AString *o, OrdersCheck *pCheck) delete token; if (!pCheck) { - SellOrder *s = new SellOrder; + std::shared_ptr s = std::make_shared(); s->item = it; s->num = num; - u->sellorders.Add(s); + u->sellorders.push_back(s); } } @@ -1728,10 +1721,10 @@ void Game::ProcessBuyOrder(Unit *u, AString *o, OrdersCheck *pCheck) delete token; if (!pCheck) { - BuyOrder *b = new BuyOrder; + std::shared_ptr b = std::make_shared(); b->item = it; b->num = num; - u->buyorders.Add(b); + u->buyorders.push_back(b); } } @@ -1763,16 +1756,14 @@ void Game::ProcessProduceOrder(Unit *u, AString *o, OrdersCheck *pCheck) return; } - ProduceOrder *p = new ProduceOrder; + std::shared_ptr p = std::make_shared(); p->item = it; AString skname = item_def.pSkill; p->skill = LookupSkill(&skname); p->target = target; if (u->monthorders || - (Globals->TAX_PILLAGE_MONTH_LONG && - ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { - if (u->monthorders) delete u->monthorders; + (Globals->TAX_PILLAGE_MONTH_LONG && ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { string err = string("PRODUCE: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); } @@ -1782,16 +1773,13 @@ void Game::ProcessProduceOrder(Unit *u, AString *o, OrdersCheck *pCheck) void Game::ProcessWorkOrder(Unit *u, int quiet, OrdersCheck *pCheck) { - ProduceOrder *order = new ProduceOrder; + std::shared_ptr order = std::make_shared(); order->skill = -1; order->item = I_SILVER; order->target = 0; if (quiet) order->quiet = 1; - if (u->monthorders || - (Globals->TAX_PILLAGE_MONTH_LONG && - ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { - if (u->monthorders) delete u->monthorders; + if (u->monthorders || (Globals->TAX_PILLAGE_MONTH_LONG && ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { string err = string("WORK: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); } @@ -1801,12 +1789,12 @@ void Game::ProcessWorkOrder(Unit *u, int quiet, OrdersCheck *pCheck) void Game::ProcessTeachOrder(Unit *u, AString *o, OrdersCheck *pCheck) { - TeachOrder *order = 0; + std::shared_ptr order = nullptr; if (u->monthorders && u->monthorders->type == O_TEACH) { - order = (TeachOrder *) u->monthorders; + order = std::dynamic_pointer_cast(u->monthorders); } else { - order = new TeachOrder; + order = std::make_shared(); } int students = 0; @@ -1826,9 +1814,7 @@ void Game::ProcessTeachOrder(Unit *u, AString *o, OrdersCheck *pCheck) } if ((u->monthorders && u->monthorders->type != O_TEACH) || - (Globals->TAX_PILLAGE_MONTH_LONG && - ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { - if (u->monthorders) delete u->monthorders; + (Globals->TAX_PILLAGE_MONTH_LONG && ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { string err = string("TEACH: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); } @@ -1846,7 +1832,7 @@ void Game::ProcessStudyOrder(Unit *u, AString *o, OrdersCheck *pCheck) int sk = ParseSkill(token); delete token; - StudyOrder *order = new StudyOrder; + std::shared_ptr order = std::make_shared(); order->skill = sk; order->days = 0; // parse study level: @@ -1858,9 +1844,7 @@ void Game::ProcessStudyOrder(Unit *u, AString *o, OrdersCheck *pCheck) order->level = -1; if (u->monthorders || - (Globals->TAX_PILLAGE_MONTH_LONG && - ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { - if (u->monthorders) delete u->monthorders; + (Globals->TAX_PILLAGE_MONTH_LONG && ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { string err = string("STUDY: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); } @@ -1972,10 +1956,10 @@ void Game::ProcessWithdrawOrder(Unit *unit, AString *o, OrdersCheck *pCheck) } if (!pCheck) { - WithdrawOrder *order = new WithdrawOrder; + std::shared_ptr order = std::make_shared(); order->item = item; order->amount = amt; - unit->withdraworders.Add(order); + unit->withdraworders.push_back(order); } return; } @@ -1985,7 +1969,8 @@ AString *Game::ProcessTurnOrder(Unit *unit, istream& f, OrdersCheck *pCheck, int int turnDepth = 1; int turnLast = 1; int formDepth = 0; - TurnOrder *tOrder = new TurnOrder; + + std::shared_ptr tOrder = std::make_shared(); tOrder->repeating = repeat; AString order, *token; @@ -1998,7 +1983,7 @@ AString *Game::ProcessTurnOrder(Unit *unit, istream& f, OrdersCheck *pCheck, int order = AString("#end"); } - AString saveorder = order; + std::string saveorder = order.const_str(); // In order to allow @endturn to work the same as endturn we need to check for and eat the possible @ std::ignore = order.getat(); // we don't care about whether it was set or not, so just ignore the return value token = order.gettoken(); @@ -2012,7 +1997,7 @@ AString *Game::ProcessTurnOrder(Unit *unit, istream& f, OrdersCheck *pCheck, int break; } turnDepth++; - tOrder->turnOrders.push_back(saveorder.const_str()); + tOrder->turnOrders.push_back(saveorder); turnLast = 1; break; case O_FORM: @@ -2022,7 +2007,7 @@ AString *Game::ProcessTurnOrder(Unit *unit, istream& f, OrdersCheck *pCheck, int } turnLast = 0; formDepth++; - tOrder->turnOrders.push_back(saveorder.const_str()); + tOrder->turnOrders.push_back(saveorder); break; case O_ENDFORM: if (turnLast) { @@ -2032,13 +2017,13 @@ AString *Game::ProcessTurnOrder(Unit *unit, istream& f, OrdersCheck *pCheck, int } else { parse_error(pCheck, unit, 0, "TURN: without ENDTURN."); if (!--turnDepth) { - unit->turnorders.Add(tOrder); + unit->turnorders.push_back(tOrder); return new AString(saveorder); } } } formDepth--; - tOrder->turnOrders.push_back(saveorder.const_str()); + tOrder->turnOrders.push_back(saveorder); turnLast = 1; break; case O_UNIT: @@ -2050,7 +2035,7 @@ AString *Game::ProcessTurnOrder(Unit *unit, istream& f, OrdersCheck *pCheck, int parse_error(pCheck, unit, 0, "FORM: without END."); } parse_error(pCheck, unit, 0, "TURN: without ENDTURN."); - unit->turnorders.Add(tOrder); + unit->turnorders.push_back(tOrder); return new AString(saveorder); break; case O_ENDTURN: @@ -2058,21 +2043,21 @@ AString *Game::ProcessTurnOrder(Unit *unit, istream& f, OrdersCheck *pCheck, int parse_error(pCheck, unit, 0, "ENDTURN: without TURN."); } else { if (--turnDepth) - tOrder->turnOrders.push_back(saveorder.const_str()); + tOrder->turnOrders.push_back(saveorder); turnLast = 0; } break; default: - tOrder->turnOrders.push_back(saveorder.const_str()); + tOrder->turnOrders.push_back(saveorder); break; } if (!pCheck && unit->former && unit->former->format) - unit->former->oldorders.push_back(saveorder.const_str()); + unit->former->oldorders.push_back(saveorder); delete token; } } - unit->turnorders.Add(tOrder); + unit->turnorders.push_back(tOrder); return NULL; } @@ -2148,13 +2133,13 @@ void Game::ProcessExchangeOrder(Unit *unit, AString *o, OrdersCheck *pCheck) } if (!pCheck) { - ExchangeOrder *order = new ExchangeOrder; + std::shared_ptr order = std::make_shared(); order->giveItem = itemGive; order->giveAmount = amtGive; order->expectAmount = amtExpected; order->expectItem = itemExpected; order->target = t; - unit->exchangeorders.Add(order); + unit->exchangeorders.push_back(order); } } @@ -2315,14 +2300,14 @@ void Game::ProcessGiveOrder(int order, Unit *unit, AString *o, OrdersCheck *pChe } if (!pCheck) { - GiveOrder *go = new GiveOrder; + std::shared_ptr go = std::make_shared(); go->type = order; go->item = item; go->target = t; go->amount = amt; go->except = excpt; go->unfinished = unfinished; - unit->giveorders.Add(go); + unit->giveorders.push_back(go); } return; } @@ -2772,22 +2757,19 @@ void Game::ProcessAddressOrder(Unit *u, AString *o, OrdersCheck *pCheck) void Game::ProcessAdvanceOrder(Unit *u, AString *o, OrdersCheck *pCheck) { - MoveOrder *m = 0; - if ((u->monthorders && u->monthorders->type != O_ADVANCE) || - (Globals->TAX_PILLAGE_MONTH_LONG && - ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { + (Globals->TAX_PILLAGE_MONTH_LONG && ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { string err = string("ADVANCE: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); - if (u->monthorders) delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; } if (Globals->TAX_PILLAGE_MONTH_LONG) u->taxing = TAX_NONE; if (!u->monthorders) { - u->monthorders = new MoveOrder; + u->monthorders = std::make_shared(); u->monthorders->type = O_ADVANCE; } - m = (MoveOrder *) u->monthorders; + + std::shared_ptr m = std::dynamic_pointer_cast(u->monthorders); m->advancing = 1; for (;;) { @@ -2797,9 +2779,8 @@ void Game::ProcessAdvanceOrder(Unit *u, AString *o, OrdersCheck *pCheck) delete t; if (d!=-1) { if (!pCheck) { - MoveDir *x = new MoveDir; - x->dir = d; - m->dirs.Add(x); + MoveDir x(d); + m->dirs.push_back(x); } } else { parse_error(pCheck, u, 0, "ADVANCE: Warning, bad direction."); @@ -2810,21 +2791,18 @@ void Game::ProcessAdvanceOrder(Unit *u, AString *o, OrdersCheck *pCheck) void Game::ProcessMoveOrder(Unit *u, AString *o, OrdersCheck *pCheck) { - MoveOrder *m = 0; - if ((u->monthorders && u->monthorders->type != O_MOVE) || - (Globals->TAX_PILLAGE_MONTH_LONG && - ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { + (Globals->TAX_PILLAGE_MONTH_LONG && ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { string err = string("MOVE: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); - if (u->monthorders) delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; } if (Globals->TAX_PILLAGE_MONTH_LONG) u->taxing = TAX_NONE; if (!u->monthorders) { - u->monthorders = new MoveOrder; + u->monthorders = std::make_shared(); } - m = (MoveOrder *) u->monthorders; + + std::shared_ptr m = std::dynamic_pointer_cast(u->monthorders); m->advancing = 0; for (;;) { @@ -2834,9 +2812,8 @@ void Game::ProcessMoveOrder(Unit *u, AString *o, OrdersCheck *pCheck) delete t; if (d!=-1) { if (!pCheck) { - MoveDir *x = new MoveDir; - x->dir = d; - m->dirs.Add(x); + MoveDir x(d); + m->dirs.push_back(x); } } else { parse_error(pCheck, u, 0, "MOVE: Warning, bad direction."); @@ -2847,21 +2824,18 @@ void Game::ProcessMoveOrder(Unit *u, AString *o, OrdersCheck *pCheck) void Game::ProcessSailOrder(Unit *u, AString *o, OrdersCheck *pCheck) { - SailOrder *m = 0; - if ((u->monthorders && u->monthorders->type != O_SAIL) || - (Globals->TAX_PILLAGE_MONTH_LONG && - ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { + (Globals->TAX_PILLAGE_MONTH_LONG && ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { string err = string("SAIL: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); - if (u->monthorders) delete u->monthorders; - u->monthorders = 0; + u->monthorders = nullptr; } if (Globals->TAX_PILLAGE_MONTH_LONG) u->taxing = TAX_NONE; if (!u->monthorders) { - u->monthorders = new SailOrder; + u->monthorders = std::make_shared(); } - m = (SailOrder *) u->monthorders; + + std::shared_ptr m = std::dynamic_pointer_cast(u->monthorders); for (;;) { AString *t = o->gettoken(); @@ -2874,9 +2848,8 @@ void Game::ProcessSailOrder(Unit *u, AString *o, OrdersCheck *pCheck) } else { if (d < NDIRS || d == MOVE_PAUSE) { if (!pCheck) { - MoveDir *x = new MoveDir; - x->dir = d; - m->dirs.Add(x); + MoveDir x(d); + m->dirs.push_back(x); } } else { parse_error(pCheck, u, 0, "SAIL: Warning, bad direction."); @@ -2891,7 +2864,7 @@ void Game::ProcessEvictOrder(Unit *u, AString *o, OrdersCheck *pCheck) UnitId *id = ParseUnit(o); while (id && id->unitnum != -1) { if (!pCheck) { - if (!u->evictorders) u->evictorders = new EvictOrder; + if (!u->evictorders) u->evictorders = std::make_shared(); u->evictorders->targets.push_back(*id); delete id; } @@ -2901,15 +2874,13 @@ void Game::ProcessEvictOrder(Unit *u, AString *o, OrdersCheck *pCheck) void Game::ProcessIdleOrder(Unit *u, AString *o, OrdersCheck *pCheck) { - if (u->monthorders || (Globals->TAX_PILLAGE_MONTH_LONG && - ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { - if (u->monthorders) delete u->monthorders; + if (u->monthorders || + (Globals->TAX_PILLAGE_MONTH_LONG && ((u->taxing == TAX_TAX) || (u->taxing == TAX_PILLAGE)))) { string err = string("IDLE: Overwriting previous ") + (u->inTurnBlock ? "DELAYED " : "") + "month-long order."; parse_error(pCheck, u, 0, err); } if (Globals->TAX_PILLAGE_MONTH_LONG) u->taxing = TAX_NONE; - IdleOrder *i = new IdleOrder; - u->monthorders = i; + u->monthorders = std::make_shared(); } void Game::ProcessTransportOrder(Unit *u, AString *o, OrdersCheck *pCheck) @@ -2967,14 +2938,14 @@ void Game::ProcessTransportOrder(Unit *u, AString *o, OrdersCheck *pCheck) } if (!pCheck) { - TransportOrder *order = new TransportOrder; + std::shared_ptr order = std::make_shared(); // At this point we don't know that transport phase for the order but // we will set that later. order->item = item; order->target = tar; order->amount = amt; order->except = except; - u->transportorders.Add(order); + u->transportorders.push_back(order); } return; } @@ -3017,11 +2988,10 @@ void Game::ProcessJoinOrder(Unit *u, AString *o, OrdersCheck *pCheck) delete token; } if (!pCheck) { - JoinOrder *ord = new JoinOrder; + std::shared_ptr ord = std::make_shared(); ord->target = id; ord->overload = overload; ord->merge = merge; - if (u->joinorders) delete u->joinorders; u->joinorders = ord; } } @@ -3071,11 +3041,9 @@ void Game::ProcessSacrificeOrder(Unit *unit, AString *o, OrdersCheck *pCheck) return; } if (!pCheck) { - SacrificeOrder *order = new SacrificeOrder; - order->item = item; - order->amount = amt; - if (unit->sacrificeorders) delete unit->sacrificeorders; - unit->sacrificeorders = order; + unit->sacrificeorders = std::make_shared(); + unit->sacrificeorders->item = item; + unit->sacrificeorders->amount = amt; } return; } @@ -3134,11 +3102,9 @@ void Game::ProcessAnnihilateOrder(Unit *unit, AString *o, OrdersCheck *pCheck) } if (!pCheck) { - AnnihilateOrder *order = new AnnihilateOrder; - order->xloc = x; - order->yloc = y; - order->zloc = z; - if (unit->annihilateorders) delete unit->annihilateorders; - unit->annihilateorders = order; + unit->annihilateorders = std::make_shared(); + unit->annihilateorders->xloc = x; + unit->annihilateorders->yloc = y; + unit->annihilateorders->zloc = z; } } diff --git a/runorders.cpp b/runorders.cpp index c0ca0c9c..ce39a161 100644 --- a/runorders.cpp +++ b/runorders.cpp @@ -26,6 +26,8 @@ #include "game.h" #include "gamedata.h" #include "quests.h" +#include +#include using namespace std; @@ -148,8 +150,7 @@ void Game::RunCastOrders() for(auto u: o->units) { if (u->castorders) { RunACastOrder(r, o, u); - delete u->castorders; - u->castorders = 0; + u->castorders = nullptr; } } } @@ -203,30 +204,27 @@ void Game::RunStealOrders() forlist(&r->objects) { Object *o = (Object *) elem; for(auto u: o->units) { - if (u->stealorders) { - if (u->stealorders->type == O_STEAL) { + if (u->stealthorders) { + if (u->stealthorders->type == O_STEAL) { Do1Steal(r, o, u); - } else if (u->stealorders->type == O_ASSASSINATE) { + } else if (u->stealthorders->type == O_ASSASSINATE) { Do1Assassinate(r, o, u); } - delete u->stealorders; - u->stealorders = 0; + u->stealthorders = nullptr; } } } } } -AList *Game::CanSeeSteal(ARegion *r, Unit *u) +std::vector>Game::CanSeeSteal(ARegion *r, Unit *u) { - AList *retval = new AList; + std::vector>retval; forlist(&factions) { Faction *f = (Faction *) elem; if (r->Present(f)) { if (f->CanSee(r, u, Globals->SKILL_PRACTICE_AMOUNT > 0)) { - FactionPtr *p = new FactionPtr; - p->ptr = f; - retval->Add(p); + retval.push_back(std::shared_ptr(f)); } } } @@ -235,7 +233,7 @@ AList *Game::CanSeeSteal(ARegion *r, Unit *u) void Game::Do1Assassinate(ARegion *r, Object *o, Unit *u) { - AssassinateOrder *so = (AssassinateOrder *) u->stealorders; + std::shared_ptr so = std::dynamic_pointer_cast(u->stealthorders); Unit *tar = r->get_unit_id(*(so->target), u->faction->num); if (!tar) { @@ -264,16 +262,14 @@ void Game::Do1Assassinate(ARegion *r, Object *o, Unit *u) return; } - // Make sure we dispose of the allocated AList properly until we get rid of ALists entirely - std::unique_ptr seers(CanSeeSteal(r, u)); + std::vector> seers(CanSeeSteal(r, u)); int succ = 1; - forlist(seers) { - Faction *f = ((FactionPtr *) elem)->ptr; - if (f == tar->faction) { + for(auto f: seers) { + if (f->num == tar->faction->num) { succ = 0; break; } - if (f->get_attitude(tar->faction->num) == A_ALLY) { + if ((f->get_attitude(tar->faction->num)) == A_ALLY) { succ = 0; break; } @@ -285,8 +281,7 @@ void Game::Do1Assassinate(ARegion *r, Object *o, Unit *u) if (!succ) { string temp = string(u->name->const_str()) + " is caught attempting to assassinate " + tar->name->const_str() + " in " + r->name->const_str() + "."; - forlist(seers) { - Faction *f = ((FactionPtr *) elem)->ptr; + for(auto f: seers) { f->event(temp, "combat"); } // One learns from one's mistakes. Surviving them is another matter! @@ -312,7 +307,7 @@ void Game::Do1Assassinate(ARegion *r, Object *o, Unit *u) void Game::Do1Steal(ARegion *r, Object *o, Unit *u) { - StealOrder *so = (StealOrder *) u->stealorders; + std::shared_ptr so = std::dynamic_pointer_cast(u->stealthorders); Unit *tar = r->get_unit_id(*so->target, u->faction->num); if (!tar) { @@ -338,12 +333,10 @@ void Game::Do1Steal(ARegion *r, Object *o, Unit *u) return; } - // Make sure we dispose of the allocated AList properly until we get rid of alists entirely. - std::unique_ptr seers(CanSeeSteal(r, u)); + std::vector> seers(CanSeeSteal(r, u)); int succ = 1; - forlist(seers) { - Faction *f = ((FactionPtr *) elem)->ptr; - if (f == tar->faction) { + for(auto f: seers) { + if (f->num == tar->faction->num) { succ = 0; break; } @@ -360,8 +353,7 @@ void Game::Do1Steal(ARegion *r, Object *o, Unit *u) if (!succ) { string temp = string(u->name->const_str()) + " is caught attempting to steal from " + tar->name->const_str() + " in " + r->name->const_str() + "."; - forlist(seers) { - Faction *f = ((FactionPtr *) elem)->ptr; + for(auto f: seers) { f->event(temp, "theft"); } // One learns from one's mistakes. Surviving them is another matter! @@ -395,13 +387,10 @@ void Game::Do1Steal(ARegion *r, Object *o, Unit *u) u->items.SetNum(so->item, u->items.GetNum(so->item) + amt); tar->items.SetNum(so->item, tar->items.GetNum(so->item) - amt); - { - string temp = string(u->name->const_str()) + " steals " + - ItemString(so->item, amt) + " from "+ tar->name->const_str() + "."; - forlist(seers) { - Faction *f = ((FactionPtr *) elem)->ptr; - f->event(temp, "theft"); - } + string temp = string(u->name->const_str()) + " steals " + + ItemString(so->item, amt) + " from "+ tar->name->const_str() + "."; + for(auto f: seers) { + f->event(temp, "theft"); } tar->event("Has " + ItemString(so->item, amt) + " stolen.", "theft"); @@ -458,12 +447,11 @@ void Game::RunForgetOrders() forlist(&r->objects) { Object *o = (Object *) elem; for(auto u: o->units) { - forlist(&u->forgetorders) { - ForgetOrder *fo = (ForgetOrder *) elem; + for(auto fo: u->forgetorders) { u->ForgetSkill(fo->skill); u->event("Forgets " + string(SkillStrs(fo->skill).const_str()) + ".", "forget"); } - u->forgetorders.DeleteAll(); + u->forgetorders.clear(); } } } @@ -616,8 +604,7 @@ void Game::RunFindUnit(Unit *u) { int all = 0; Faction *fac; - forlist(&u->findorders) { - FindOrder *f = (FindOrder *) elem; + for(auto f: u->findorders) { if (f->find == 0) all = 1; if (!all) { fac = GetFaction(&factions, f->find); @@ -639,7 +626,7 @@ void Game::RunFindUnit(Unit *u) } } } - u->findorders.DeleteAll(); + u->findorders.clear(); } void Game::RunTaxOrders() @@ -849,7 +836,7 @@ void Game::RunPromoteOrders() if (u && u->promote) { Do1PromoteOrder(o, u); delete u->promote; - u->promote = 0; + u->promote = nullptr; } } } @@ -864,8 +851,7 @@ void Game::RunPromoteOrders() u = o->GetOwner(); if (u && u->evictorders) { Do1EvictOrder(o, u); - delete u->evictorders; - u->evictorders = 0; + u->evictorders = nullptr; } } } @@ -893,12 +879,10 @@ void Game::RunPromoteOrders() if (u->evictorders) { if (o->type != O_DUMMY) { u->error("EVICT: Must be owner"); - delete u->evictorders; - u->evictorders = 0; + u->evictorders = nullptr; } else { u->error("EVICT: Can only evict inside structures."); - delete u->evictorders; - u->evictorders = 0; + u->evictorders = nullptr; } } } @@ -927,16 +911,14 @@ void Game::Do1PromoteOrder(Object *obj, Unit *u) void Game::Do1EvictOrder(Object *obj, Unit *u) { - EvictOrder *ord = u->evictorders; - if (obj->region->type == R_NEXUS) { u->error("Evict: Evict does not work in the Nexus."); return; } - obj->region->deduplicate_unit_list(ord->targets, u->faction->num); + obj->region->deduplicate_unit_list(u->evictorders->targets, u->faction->num); - for(auto id: ord->targets) { + for(auto id: u->evictorders->targets) { Unit *tar = obj->get_unit_id(&id, u->faction->num); if (!tar) continue; if (obj->IsFleet() && @@ -950,7 +932,7 @@ void Game::Do1EvictOrder(Object *obj, Unit *u) tar->event("Evicted from " + string(obj->name->const_str()) + " by " + u->name->const_str(), "evict"); u->event("Evicted " + string(tar->name->const_str()) + " from " + obj->name->const_str(), "evict"); } - ord->targets.clear(); + u->evictorders->targets.clear(); } /* RunEnterOrders is performed in TWO phases: one in the @@ -1010,13 +992,11 @@ void Game::Do1EnterOrder(ARegion *r, Object *in, Unit *u) void Game::Do1JoinOrder(ARegion *r, Object *in, Unit *u) { - JoinOrder *jo; Unit *tar; Object *to, *from; Item *item; - jo = (JoinOrder *) u->joinorders; - tar = r->get_unit_id(*jo->target, u->faction->num); + tar = r->get_unit_id(*u->joinorders->target, u->faction->num); if (!tar) { u->error("JOIN: No such unit."); @@ -1034,9 +1014,8 @@ void Game::Do1JoinOrder(ARegion *r, Object *in, Unit *u) return; } - if (jo->merge) { - if (!u->object->IsFleet() || - u->object->GetOwner()->num != u->num) { + if (u->joinorders->merge) { + if (!u->object->IsFleet() || u->object->GetOwner()->num != u->num) { u->error("JOIN MERGE: Not fleet owner."); return; } @@ -1064,8 +1043,7 @@ void Game::Do1JoinOrder(ARegion *r, Object *in, Unit *u) go.target = &id; go.type = O_GIVE; go.merge = 1; - DoGiveOrder(r, u, &go); - go.target = NULL; + DoGiveOrder(r, u, std::make_shared(go)); } for(auto pass: u->object->units) { pass->MoveUnit(to); @@ -1089,9 +1067,7 @@ void Game::Do1JoinOrder(ARegion *r, Object *in, Unit *u) u->error("JOIN: Is refused entry."); return; } - if (to->IsFleet() && - !jo->overload && - to->FleetCapacity() < to->FleetLoad() + u->Weight()) { + if (to->IsFleet() && !u->joinorders->overload && to->FleetCapacity() < to->FleetLoad() + u->Weight()) { u->event("JOIN: Fleet would be overloaded.", "join"); return; } @@ -1396,9 +1372,8 @@ void Game::DoAttackOrders() } } else { if (u->attackorders && u->IsAlive()) { - AttackOrder *ord = u->attackorders; - r->deduplicate_unit_list(ord->targets, u->faction->num); - for (auto id: ord->targets) { + r->deduplicate_unit_list(u->attackorders->targets, u->faction->num); + for (auto id: u->attackorders->targets) { Unit *t = r->get_unit_id(id, u->faction->num); if (u->canattack && u->IsAlive()) { if (t) { @@ -1408,7 +1383,6 @@ void Game::DoAttackOrders() } } } - delete ord; u->attackorders = 0; } } @@ -1458,10 +1432,13 @@ void Game::RunSellOrders() forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - forlist((&u->sellorders)) { - u->error("SELL: Can't sell that."); - } - u->sellorders.DeleteAll(); + std::for_each( + u->sellorders.begin(), u->sellorders.end(), + [&u](std::shared_ptr o) { + u->error("SELL: Can't sell " + ItemString(o->item, o->num, FULLNUM) + "."); + } + ); + u->sellorders.clear(); } } } @@ -1473,8 +1450,7 @@ int Game::GetSellAmount(ARegion *r, Market *m) forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - forlist ((&u->sellorders)) { - SellOrder *o = (SellOrder *) elem; + for(auto o: u->sellorders) { if (o->item == m->item) { if (o->num == -1) { o->num = u->items.CanSell(o->item); @@ -1503,8 +1479,8 @@ void Game::DoSell(ARegion *r, Market *m) forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - forlist((&u->sellorders)) { - SellOrder *o = (SellOrder *) elem; + for(auto oit = u->sellorders.begin(); oit != u->sellorders.end(); ++oit) { + std::shared_ptr o = *oit; if (o->item == m->item) { int temp = 0; if (o->num > u->GetSharedNum(o->item)) { @@ -1512,8 +1488,7 @@ void Game::DoSell(ARegion *r, Market *m) u->error("SELL: Unit attempted to sell more than it had."); } if (attempted) { - temp = (m->amount *o->num + getrandom(attempted)) - / attempted; + temp = (m->amount *o->num + getrandom(attempted)) / attempted; if (temp<0) temp = 0; } attempted -= o->num; @@ -1521,9 +1496,10 @@ void Game::DoSell(ARegion *r, Market *m) m->activity += temp; u->ConsumeShared(o->item, temp); u->SetMoney(u->GetMoney() + temp * m->price); - u->sellorders.Remove(o); + oit = u->sellorders.erase(oit); + // walk ack one step so that the for loop will put us at the right place after the delete + --oit; u->event("Sells " + ItemString(o->item, temp) + " at $" + to_string(m->price) + " each.", "sell"); - delete o; } } } @@ -1541,10 +1517,13 @@ void Game::RunBuyOrders() forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - forlist((&u->buyorders)) { - u->error("BUY: Can't buy that."); - } - u->buyorders.DeleteAll(); + std::for_each( + u->buyorders.begin(), u->buyorders.end(), + [&u](std::shared_ptr o) { + u->error("BUY: Can't buy " + ItemString(o->item, o->num, FULLNUM) + "."); + } + ); + u->buyorders.clear(); } } } @@ -1556,8 +1535,8 @@ int Game::GetBuyAmount(ARegion *r, Market *m) forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - forlist ((&u->buyorders)) { - BuyOrder *o = (BuyOrder *) elem; + for(auto oit = u->buyorders.begin(); oit != u->buyorders.end(); ++oit) { + std::shared_ptr o = *oit; if (o->item == m->item) { if (ItemDefs[o->item].type & IT_MAN) { if (u->type == U_MAGE) { @@ -1603,8 +1582,9 @@ int Game::GetBuyAmount(ARegion *r, Market *m) num += o->num; } if (o->num < 1 && o->num != -1) { - u->buyorders.Remove(o); - delete o; + oit = u->buyorders.erase(oit); + // back up the iterator so that the for loop will put us at the right place after the delete + --oit; } } } @@ -1625,8 +1605,8 @@ void Game::DoBuy(ARegion *r, Market *m) forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - forlist((&u->buyorders)) { - BuyOrder *o = (BuyOrder *) elem; + for(auto oit = u->buyorders.begin(); oit != u->buyorders.end(); ++oit) { + std::shared_ptr o = *oit; if (o->item == m->item) { int temp = 0; if (m->amount == -1) { @@ -1634,8 +1614,7 @@ void Game::DoBuy(ARegion *r, Market *m) temp = o->num; } else { if (attempted) { - temp = (m->amount * o->num + - getrandom(attempted)) / attempted; + temp = (m->amount * o->num + getrandom(attempted)) / attempted; if (temp < 0) temp = 0; } attempted -= o->num; @@ -1668,9 +1647,10 @@ void Game::DoBuy(ARegion *r, Market *m) u->items.SetNum(o->item, u->items.GetNum(o->item) + temp); u->faction->DiscoverItem(o->item, 0, 1); u->ConsumeSharedMoney(temp * m->price); - u->buyorders.Remove(o); + oit = u->buyorders.erase(oit); + // back up the iterator so that the for loop will put us at the right place after the delete + --oit; u->event("Buys " + ItemString(o->item, temp) + " at $" + to_string(m->price) + " each.", "buy"); - delete o; } } } @@ -2102,17 +2082,16 @@ void Game::DoWithdrawOrders() forlist((&r->objects)) { Object *obj = (Object *)elem; for(auto u: obj->units) { - forlist((&u->withdraworders)) { - WithdrawOrder *o = (WithdrawOrder *)elem; + for(auto o: u->withdraworders) { if (DoWithdrawOrder(r, u, o)) break; } - u->withdraworders.DeleteAll(); + u->withdraworders.clear(); } } } } -int Game::DoWithdrawOrder(ARegion *r, Unit *u, WithdrawOrder *o) +int Game::DoWithdrawOrder(ARegion *r, Unit *u, std::shared_ptr o) { int itm = o->item; int amt = o->amount; @@ -2154,8 +2133,7 @@ void Game::DoGiveOrders() forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - forlist((&u->giveorders)) { - GiveOrder *o = (GiveOrder *)elem; + for(auto o: u->giveorders) { if (o->item < 0) { if (o->amount == -1) { /* do 'give X unit' command */ @@ -2187,8 +2165,7 @@ void Game::DoGiveOrders() go.item = item->type; go.target = o->target; go.type = o->type; - DoGiveOrder(r, u, &go); - go.target = NULL; + DoGiveOrder(r, u, std::make_shared(go)); } } forlist((&s->items)) { @@ -2206,18 +2183,13 @@ void Game::DoGiveOrders() if (o->item == -NITEMS) { go.unfinished = 1; } - if (go.unfinished) { - go.amount = 1; - } else { - go.amount = 0; - } + go.amount = (go.unfinished ? 1 : 0); } else if (o->unfinished) { go.amount = 0; } if (go.amount) { - DoGiveOrder(r, u, &go); + DoGiveOrder(r, u, std::make_shared(go)); } - go.target = NULL; } } } else { @@ -2230,7 +2202,7 @@ void Game::DoGiveOrders() break; } } - u->giveorders.DeleteAll(); + u->giveorders.clear(); } } } @@ -2243,47 +2215,44 @@ void Game::DoExchangeOrders() forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - forlist((&u->exchangeorders)) { - Order *o = (Order *) elem; - DoExchangeOrder(r, u, (ExchangeOrder *) o); + // Since the exchange command will remove the exchange order, we need to copy the list + std::vector> exchangeorders = u->exchangeorders; + for(auto o: exchangeorders) { + DoExchangeOrder(r, u, o); } + u->exchangeorders.clear(); } } } } -void Game::DoExchangeOrder(ARegion *r, Unit *u, ExchangeOrder *o) +void Game::DoExchangeOrder(ARegion *r, Unit *u, std::shared_ptr o) { // Check if the destination unit exists Unit *t = r->get_unit_id(*o->target, u->faction->num); if (!t) { u->error("EXCHANGE: Nonexistant target (" + o->target->Print() + ")."); - u->exchangeorders.Remove(o); return; } // Check each Item can be given if (ItemDefs[o->giveItem].flags & ItemType::CANTGIVE) { u->error(string("EXCHANGE: Can't trade ") + ItemDefs[o->giveItem].names + "."); - u->exchangeorders.Remove(o); return; } if (ItemDefs[o->expectItem].flags & ItemType::CANTGIVE) { u->error(string("EXCHANGE: Can't trade ") + ItemDefs[o->expectItem].names + "."); - u->exchangeorders.Remove(o); return; } if (ItemDefs[o->giveItem].type & IT_MAN) { u->error("EXCHANGE: Exchange aborted. Men may not be traded."); - u->exchangeorders.Remove(o); return; } if (ItemDefs[o->expectItem].type & IT_MAN) { u->error("EXCHANGE: Exchange aborted. Men may not be traded."); - u->exchangeorders.Remove(o); return; } @@ -2298,14 +2267,12 @@ void Game::DoExchangeOrder(ARegion *r, Unit *u, ExchangeOrder *o) t->error(string("EXCHANGE: Not giving enough. Expecting ") + ItemString(o->expectItem, o->expectAmount) + "."); u->error(string("EXCHANGE: Exchange aborted. Not enough recieved. Expecting ") + ItemString(o->expectItem, o->expectAmount) + "."); - o->exchangeStatus = 0; return; } int exchangeOrderFound = 0; // Check if other unit has a reciprocal exchange order - forlist ((&t->exchangeorders)) { - ExchangeOrder *tOrder = (ExchangeOrder *) elem; + for(auto tOrder: t->exchangeorders) { Unit *ptrUnitTemp = r->get_unit_id(*tOrder->target, t->faction->num); if (ptrUnitTemp == u) { if (tOrder->expectItem == o->giveItem) { @@ -2329,48 +2296,33 @@ void Game::DoExchangeOrder(ARegion *r, Unit *u, ExchangeOrder *o) } else if (tOrder->giveAmount == o->expectAmount) o->exchangeStatus = 1; - if ((o->exchangeStatus == 1) && - (tOrder->exchangeStatus == 1)) { + if ((o->exchangeStatus == 1) && (tOrder->exchangeStatus == 1)) { u->event("Exchanges " + ItemString(o->giveItem, o->giveAmount) + " with " + t->name->const_str() + " for " + ItemString(tOrder->giveItem, tOrder->giveAmount) + ".", "exchange"); t->event("Exchanges " + ItemString(tOrder->giveItem, tOrder->giveAmount) + " with " + u->name->const_str() + " for " + ItemString(o->giveItem, o->giveAmount) + ".", "exchange"); u->ConsumeShared(o->giveItem, o->giveAmount); - t->items.SetNum(o->giveItem, - t->items.GetNum(o->giveItem) + o->giveAmount); + t->items.SetNum(o->giveItem, t->items.GetNum(o->giveItem) + o->giveAmount); t->ConsumeShared(tOrder->giveItem, tOrder->giveAmount); - u->items.SetNum(tOrder->giveItem, - u->items.GetNum(tOrder->giveItem) + - tOrder->giveAmount); + u->items.SetNum(tOrder->giveItem, u->items.GetNum(tOrder->giveItem) + tOrder->giveAmount); u->faction->DiscoverItem(tOrder->giveItem, 0, 1); t->faction->DiscoverItem(o->giveItem, 0, 1); - u->exchangeorders.Remove(o); - t->exchangeorders.Remove(tOrder); + std::erase(t->exchangeorders, tOrder); // safe because we immediately return. return; - } else if ((o->exchangeStatus >= 0) && - (tOrder->exchangeStatus >= 0)) { - u->exchangeorders.Remove(o); - t->exchangeorders.Remove(tOrder); } } } } } if (!exchangeOrderFound) { - if (!u->CanSee(r, t)) { - u->error("EXCHANGE: Nonexistant target (" + o->target->Print() + ")."); - u->exchangeorders.Remove(o); - return; - } else { - u->error("EXCHANGE: target unit did not issue a matching exchange order."); - u->exchangeorders.Remove(o); - return; - } + // since we already checked ability to see above, we can only get here if the target unit didn't issue + // a matching exchange order. + u->error("EXCHANGE: target unit did not issue a matching exchange order."); } } -int Game::DoGiveOrder(ARegion *r, Unit *u, GiveOrder *o) +int Game::DoGiveOrder(ARegion *r, Unit *u, std::shared_ptr o) { int hasitem, ship, num, shipcount, amt, newfleet, cur; int notallied, newlvl, oldlvl; @@ -2789,11 +2741,12 @@ int Game::DoGiveOrder(ARegion *r, Unit *u, GiveOrder *o) u->faction = t->faction; u->event("Is given to your faction.", event_type); - if (notallied && u->monthorders && u->monthorders->type == O_MOVE && - ((MoveOrder *) u->monthorders)->advancing) { - u->error("Unit cannot advance after being given."); - delete u->monthorders; - u->monthorders = 0; + if (notallied && u->monthorders && u->monthorders->type == O_MOVE) { + std::shared_ptr mo = std::dynamic_pointer_cast(u->monthorders); + if (mo->advancing) { + u->error("Unit cannot advance after being given."); + u->monthorders = nullptr; + } } /* Check if any new skill reports have to be shown */ @@ -2973,9 +2926,8 @@ void Game::CheckTransportOrders() forlist((&r->objects)) { Object *obj = (Object *)elem; for(auto u: obj->units) { - forlist ((&u->transportorders)) { + for(auto o: u->transportorders) { // make sure target exists - TransportOrder *o = (TransportOrder *)elem; if (!o->target || o->target->unitnum == -1) { u->error("TRANSPORT: Target does not exist."); o->type = NORDERS; @@ -3021,9 +2973,9 @@ void Game::CheckTransportOrders() bool sender_is_valid_qm = sender_has_qm_skill && sender_owns_qm_building; bool target_is_valid_qm = target_has_qm_skill && target_owns_qm_building; if (sender_is_valid_qm) { - o->phase = target_is_valid_qm ? - TransportOrder::INTER_QM_TRANSPORT : // both sender and target are valid QM - TransportOrder::DISTRIBUTE_FROM_QM; // sender is a valid QM, target isn't + o->phase = target_is_valid_qm + ? TransportOrder::TransportPhase::INTER_QM_TRANSPORT // sender and target are valid QM + : TransportOrder::TransportPhase::DISTRIBUTE_FROM_QM; // sender is valid QM, target isn't } else { // sender isn't a valid QM if (!target_is_valid_qm) { // Non-qms or invalid qms can only send to valid QMs // Give a specific error message depending on why they aren't considered a quartermaster @@ -3038,11 +2990,11 @@ void Game::CheckTransportOrders() continue; } // the target is a valid QM so the send is legal - o->phase = TransportOrder::SHIP_TO_QM; + o->phase = TransportOrder::TransportPhase::SHIP_TO_QM; } int maxdist = Globals->LOCAL_TRANSPORT; - if (o->phase == TransportOrder::INTER_QM_TRANSPORT) { + if (o->phase == TransportOrder::TransportPhase::INTER_QM_TRANSPORT) { maxdist = Globals->NONLOCAL_TRANSPORT; // 0 max distance represents unlimited range if (maxdist > 0 && Globals->TRANSPORT & GameDefs::QM_AFFECT_DIST) { @@ -3123,13 +3075,13 @@ void Game::RunTransportOrders() { } // Send all items in to QMs from non-QMs - RunTransportPhase(TransportOrder::SHIP_TO_QM); + RunTransportPhase(TransportOrder::TransportPhase::SHIP_TO_QM); // Ship items between QMs - RunTransportPhase(TransportOrder::INTER_QM_TRANSPORT); + RunTransportPhase(TransportOrder::TransportPhase::INTER_QM_TRANSPORT); // Move items from tempororary transport storage to the QM for distribution CollectInterQMTransportItems(); // Send all items out from QMs to non-QMs - RunTransportPhase(TransportOrder::DISTRIBUTE_FROM_QM); + RunTransportPhase(TransportOrder::TransportPhase::DISTRIBUTE_FROM_QM); // erase all transport orders forlist_reuse((®ions)) { @@ -3137,7 +3089,7 @@ void Game::RunTransportOrders() { forlist((&r->objects)) { Object *obj = (Object *)elem; for(auto u: obj->units) { - u->transportorders.DeleteAll(); + u->transportorders.clear(); } } } @@ -3151,8 +3103,7 @@ void Game::RunTransportPhase(TransportOrder::TransportPhase phase) { forlist((&r->objects)) { Object *obj = (Object *)elem; for(auto u: obj->units) { - forlist ((&u->transportorders)) { - TransportOrder *t = (TransportOrder *)elem; + for (auto t: u->transportorders) { if (t->type != O_TRANSPORT) continue; if (t->phase != phase) continue; @@ -3217,7 +3168,7 @@ void Game::RunTransportPhase(TransportOrder::TransportPhase phase) { u->name->const_str() + ".", "transport"); } - if (phase == TransportOrder::INTER_QM_TRANSPORT) { + if (phase == TransportOrder::TransportPhase::INTER_QM_TRANSPORT) { tar->unit->transport_items.SetNum(t->item, amt); } else { tar->unit->items.SetNum(t->item, tar->unit->items.GetNum(t->item) + amt); @@ -3225,7 +3176,6 @@ void Game::RunTransportPhase(TransportOrder::TransportPhase phase) { tar->unit->faction->DiscoverItem(t->item, 0, 1); u->Practice(S_QUARTERMASTER); - } } } @@ -3242,8 +3192,7 @@ void Game::RunSacrificeOrders() { forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - SacrificeOrder *o = u->sacrificeorders; - if (o == nullptr) continue; + if (u->sacrificeorders == nullptr) continue; bool succeeded = false; @@ -3253,7 +3202,7 @@ void Game::RunSacrificeOrders() { Object *sacrifice_object = (Object *) elem; ObjectType sacrifice_type = ObjectDefs[sacrifice_object->type]; if (!(sacrifice_type.flags & ObjectType::SACRIFICE)) continue; - if (sacrifice_type.sacrifice_item != o->item) continue; + if (sacrifice_type.sacrifice_item != u->sacrificeorders->item) continue; if (sacrifice_object->incomplete >= 0) continue; // Make sure any sacrifice rewards are valid -- there must be at least one of an item or replaced @@ -3273,19 +3222,20 @@ void Game::RunSacrificeOrders() { // Ok this sacrifice will be valid succeeded = true; - int current = u->items.GetNum(o->item); - if (current < o->amount) { - u->error("SACRIFICE: You can only sacrifice up to " + ItemString(o->item, current) + "."); - o->amount = current; + int current = u->items.GetNum(u->sacrificeorders->item); + if (current < u->sacrificeorders->amount) { + u->error("SACRIFICE: You can only sacrifice up to " + + ItemString(u->sacrificeorders->item, current) + "."); + u->sacrificeorders->amount = current; } int required = -sacrifice_object->incomplete; - int used = min(required, o->amount); + int used = min(required, u->sacrificeorders->amount); // Okay we have a valid sacrifice. Do it. sacrifice_object->incomplete += used; - u->items.SetNum(o->item, current - used); - u->event("Sacrifices " + ItemString(o->item, used) + ".", "sacrifice"); + u->items.SetNum(u->sacrificeorders->item, current - used); + u->event("Sacrifices " + ItemString(u->sacrificeorders->item, used) + ".", "sacrifice"); // sacrifice objects store the remaining needed sacrifices as negative numbers in incomplete if (sacrifice_object->incomplete >= 0) { // was the reward an item @@ -3325,7 +3275,8 @@ void Game::RunSacrificeOrders() { // If we didn't succeed, log the error if (!succeeded) { - u->error("SACRIFICE: Unable to sacrifice " + ItemString(o->item, o->amount)); + u->error("SACRIFICE: Unable to sacrifice " + + ItemString(u->sacrificeorders->item, u->sacrificeorders->amount)); } } } @@ -3412,8 +3363,7 @@ void Game::RunAnnihilateOrders() { forlist((&r->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - AnnihilateOrder *o = u->annihilateorders; - if (o == nullptr) continue; + if (u->annihilateorders == nullptr) continue; // Check if the unit has access to the annihilate skill if (u->GetSkill(S_ANNIHILATION) <= 0) { @@ -3422,7 +3372,9 @@ void Game::RunAnnihilateOrders() { } // Ok we have a unit doing a valid annihilate order. - ARegion *target = regions.GetRegion(o->xloc, o->yloc, o->zloc); + ARegion *target = regions.GetRegion( + u->annihilateorders->xloc, u->annihilateorders->yloc, u->annihilateorders->zloc + ); if (target == nullptr) { u->error("ANNIHILATE: Target region does not exist."); continue; diff --git a/spells.cpp b/spells.cpp index 369088df..d5ee945a 100644 --- a/spells.cpp +++ b/spells.cpp @@ -166,7 +166,7 @@ void Game::ProcessMindReading(Unit *u,AString *o, OrdersCheck *pCheck ) return; } - CastMindOrder *order = new CastMindOrder; + std::shared_ptr order = std::make_shared(); order->id = id; order->spell = S_MIND_READING; order->level = 1; @@ -185,7 +185,7 @@ void Game::ProcessBirdLore(Unit *u,AString *o, OrdersCheck *pCheck ) } if (*token == "eagle") { - CastIntOrder *order = new CastIntOrder; + std::shared_ptr order = std::make_shared(); order->spell = S_BIRD_LORE; order->level = 3; u->ClearCastOrders(); @@ -209,7 +209,7 @@ void Game::ProcessBirdLore(Unit *u,AString *o, OrdersCheck *pCheck ) return; } - CastIntOrder *order = new CastIntOrder; + std::shared_ptr order = std::make_shared(); order->spell = S_BIRD_LORE; order->level = 1; order->target = dir; @@ -233,13 +233,11 @@ void Game::ProcessInvisibility(Unit *u,AString *o, OrdersCheck *pCheck ) } delete token; - CastUnitsOrder *order; - if (u->castorders && u->castorders->type == O_CAST && - ((CastOrder *) u->castorders)->spell == S_INVISIBILITY && - ((CastOrder *) u->castorders)->level == 1) { - order = (CastUnitsOrder *) u->castorders; + std::shared_ptr order = std::make_shared(); + if (u->castorders && (u->castorders->type == O_CAST) && + (u->castorders->spell == S_INVISIBILITY) && u->castorders->level == 1) { + order = std::dynamic_pointer_cast(u->castorders); } else { - order = new CastUnitsOrder; order->spell = S_INVISIBILITY; order->level = 1; u->ClearCastOrders(); @@ -256,7 +254,7 @@ void Game::ProcessInvisibility(Unit *u,AString *o, OrdersCheck *pCheck ) void Game::ProcessPhanDemons(Unit *u,AString *o, OrdersCheck *pCheck ) { - CastIntOrder *order = new CastIntOrder; + std::shared_ptr order = std::make_shared(); order->spell = S_CREATE_PHANTASMAL_DEMONS; order->level = 0; order->target = 1; @@ -265,7 +263,6 @@ void Game::ProcessPhanDemons(Unit *u,AString *o, OrdersCheck *pCheck ) if (!token) { u->error("CAST: Illusion to summon must be given."); - delete order; return; } @@ -285,7 +282,6 @@ void Game::ProcessPhanDemons(Unit *u,AString *o, OrdersCheck *pCheck ) if (!order->level) { u->error("CAST: Can't summon that illusion."); - delete order; return; } @@ -304,7 +300,7 @@ void Game::ProcessPhanDemons(Unit *u,AString *o, OrdersCheck *pCheck ) void Game::ProcessPhanUndead(Unit *u,AString *o, OrdersCheck *pCheck) { - CastIntOrder *order = new CastIntOrder; + std::shared_ptr order = std::make_shared(); order->spell = S_CREATE_PHANTASMAL_UNDEAD; order->level = 0; order->target = 1; @@ -313,7 +309,6 @@ void Game::ProcessPhanUndead(Unit *u,AString *o, OrdersCheck *pCheck) if (!token) { u->error("CAST: Must specify which illusion to summon."); - delete order; return; } @@ -333,7 +328,6 @@ void Game::ProcessPhanUndead(Unit *u,AString *o, OrdersCheck *pCheck) if (!order->level) { u->error("CAST: Must specify which illusion to summon."); - delete order; return; } @@ -352,7 +346,7 @@ void Game::ProcessPhanUndead(Unit *u,AString *o, OrdersCheck *pCheck) void Game::ProcessPhanBeasts(Unit *u,AString *o, OrdersCheck *pCheck ) { - CastIntOrder *order = new CastIntOrder; + std::shared_ptr order = std::make_shared(); order->spell = S_CREATE_PHANTASMAL_BEASTS; order->level = 0; order->target = 1; @@ -361,7 +355,6 @@ void Game::ProcessPhanBeasts(Unit *u,AString *o, OrdersCheck *pCheck ) if (!token) { u->error("CAST: Must specify which illusion to summon."); - delete order; return; } @@ -377,7 +370,6 @@ void Game::ProcessPhanBeasts(Unit *u,AString *o, OrdersCheck *pCheck ) delete token; if (!order->level) { - delete order; u->error("CAST: Must specify which illusion to summon."); return; } @@ -392,17 +384,16 @@ void Game::ProcessPhanBeasts(Unit *u,AString *o, OrdersCheck *pCheck ) u->castorders = order; } -void Game::ProcessGenericSpell(Unit *u,int spell, OrdersCheck *pCheck ) +void Game::ProcessGenericSpell(Unit *u,int spell, OrdersCheck *pCheck) { - CastOrder *orders = new CastOrder; - orders->spell = spell; - orders->level = 1; + std::shared_ptr order = std::make_shared(); + order->spell = spell; + order->level = 1; u->ClearCastOrders(); - u->castorders = orders; + u->castorders = order; } -void Game::ProcessRegionSpell(Unit *u, AString *o, int spell, - OrdersCheck *pCheck) +void Game::ProcessRegionSpell(Unit *u, AString *o, int spell, OrdersCheck *pCheck) { AString *token = o->gettoken(); int x = -1; @@ -434,9 +425,8 @@ void Game::ProcessRegionSpell(Unit *u, AString *o, int spell, if (token) { z = token->value(); delete token; - if (z < 0 || (z >= Globals->UNDERWORLD_LEVELS + - Globals->UNDERDEEP_LEVELS + - Globals->ABYSS_LEVEL + 2)) { + if (z < 0 || + (z >= Globals->UNDERWORLD_LEVELS + Globals->UNDERDEEP_LEVELS + Globals->ABYSS_LEVEL + 2)) { u->error("CAST: Invalid Z coordinate specified."); return; } @@ -450,23 +440,22 @@ void Game::ProcessRegionSpell(Unit *u, AString *o, int spell, if (y == -1) y = u->object->region->yloc; if (z == -1) z = u->object->region->zloc; - CastRegionOrder *order; - if (spell == S_TELEPORTATION) - order = new TeleportOrder; - else - order = new CastRegionOrder; + std::shared_ptr order; + u->ClearCastOrders(); + if (spell == S_TELEPORTATION) { + std::shared_ptr tOrder = std::make_shared(); + u->teleportorders = tOrder; + order = tOrder; + } else { + order = std::make_shared(); + u->castorders = order; + } + order->spell = spell; order->level = 1; order->xloc = x; order->yloc = y; order->zloc = z; - - u->ClearCastOrders(); - /* Teleports happen late in the turn! */ - if (spell == S_TELEPORTATION) - u->teleportorders = (TeleportOrder *) order; - else - u->castorders = order; } void Game::ProcessCastPortalLore(Unit *u,AString *o, OrdersCheck *pCheck ) @@ -491,12 +480,11 @@ void Game::ProcessCastPortalLore(Unit *u,AString *o, OrdersCheck *pCheck ) return; } - TeleportOrder *order; - + std::shared_ptr order; if (u->teleportorders && u->teleportorders->spell == S_PORTAL_LORE) { order = u->teleportorders; } else { - order = new TeleportOrder; + order = std::make_shared(); u->ClearCastOrders(); u->teleportorders = order; } @@ -522,6 +510,7 @@ void Game::ProcessCastGateLore(Unit *u,AString *o, OrdersCheck *pCheck ) return; } + std::shared_ptr order = std::make_shared(); if ((*token) == "gate") { delete token; token = o->gettoken(); @@ -531,13 +520,9 @@ void Game::ProcessCastGateLore(Unit *u,AString *o, OrdersCheck *pCheck ) return; } - TeleportOrder *order; - - if (u->teleportorders && u->teleportorders->spell == S_GATE_LORE && - u->teleportorders->gate == token->value()) { + if (u->teleportorders && u->teleportorders->spell == S_GATE_LORE && u->teleportorders->gate == token->value()) { order = u->teleportorders; } else { - order = new TeleportOrder; u->ClearCastOrders(); u->teleportorders = order; } @@ -566,14 +551,9 @@ void Game::ProcessCastGateLore(Unit *u,AString *o, OrdersCheck *pCheck ) } if ((*token) == "random") { - TeleportOrder *order; - - if (u->teleportorders && - u->teleportorders->spell == S_GATE_LORE && - u->teleportorders->gate == -1 ) { + if (u->teleportorders && u->teleportorders->spell == S_GATE_LORE && u->teleportorders->gate == -1 ) { order = u->teleportorders; } else { - order = new TeleportOrder; u->ClearCastOrders(); u->teleportorders = order; } @@ -611,7 +591,7 @@ void Game::ProcessCastGateLore(Unit *u,AString *o, OrdersCheck *pCheck ) if ((*token) == "detect") { delete token; u->ClearCastOrders(); - CastOrder *to = new CastOrder; + std::shared_ptr to = std::make_shared(); to->spell = S_GATE_LORE; to->level = 2; u->castorders = to; @@ -624,10 +604,9 @@ void Game::ProcessCastGateLore(Unit *u,AString *o, OrdersCheck *pCheck ) void Game::ProcessTransmutation(Unit *u, AString *o, OrdersCheck *pCheck) { - CastTransmuteOrder *order; AString *token; - order = new CastTransmuteOrder; + std::shared_ptr order = std::make_shared(); order->spell = S_TRANSMUTATION; order->level = 0; order->item = -1; @@ -636,7 +615,6 @@ void Game::ProcessTransmutation(Unit *u, AString *o, OrdersCheck *pCheck) token = o->gettoken(); if (!token) { u->error("CAST: You must specify what you wish to create."); - delete order; return; } if (token->value() > 0) { @@ -649,7 +627,6 @@ void Game::ProcessTransmutation(Unit *u, AString *o, OrdersCheck *pCheck) delete token; if (order->item == -1) { u->error("CAST: You must specify what you wish to create."); - delete order; return; } @@ -675,7 +652,6 @@ void Game::ProcessTransmutation(Unit *u, AString *o, OrdersCheck *pCheck) break; default: u->error("CAST: Can't create that by transmutation."); - delete order; return; } @@ -931,7 +907,7 @@ int Game::GetRegionInRange(ARegion *r, ARegion *tar, Unit *u, int spell) int Game::RunMindReading(ARegion *r,Unit *u) { - CastMindOrder *order = (CastMindOrder *) u->castorders; + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); int level = u->GetSkill(S_MIND_READING); Unit *tar = r->get_unit_id(*order->id,u->faction->num); @@ -1301,7 +1277,7 @@ int Game::RunDragonLore(ARegion *r, Unit *u) int Game::RunBirdLore(ARegion *r,Unit *u) { - CastIntOrder *order = (CastIntOrder *) u->castorders; + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); int type = regions.GetRegionArray(r->zloc)->levelType; if (type != ARegionArray::LEVEL_SURFACE) { @@ -1355,13 +1331,6 @@ int Game::RunBirdLore(ARegion *r,Unit *u) int Game::RunWolfLore(ARegion *r,Unit *u) { - // if (TerrainDefs[r->type].similar_type != R_MOUNTAIN && - // TerrainDefs[r->type].similar_type != R_FOREST) { - // u->error("CAST: Can only summon wolves in mountain and " - // "forest regions."); - // return 0; - // } - int level = u->GetSkill(S_WOLF_LORE); int max = level * level * 4; @@ -1381,7 +1350,7 @@ int Game::RunWolfLore(ARegion *r,Unit *u) int Game::RunInvisibility(ARegion *r,Unit *u) { - CastUnitsOrder *order = (CastUnitsOrder *) u->castorders; + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); int max = u->GetSkill(S_INVISIBILITY); max = max * max; @@ -1417,7 +1386,7 @@ int Game::RunInvisibility(ARegion *r,Unit *u) int Game::RunPhanDemons(ARegion *r,Unit *u) { - CastIntOrder *order = (CastIntOrder *) u->castorders; + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); int level = u->GetSkill(S_CREATE_PHANTASMAL_DEMONS); int create,max; @@ -1451,7 +1420,7 @@ int Game::RunPhanDemons(ARegion *r,Unit *u) int Game::RunPhanUndead(ARegion *r,Unit *u) { - CastIntOrder *order = (CastIntOrder *) u->castorders; + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); int level = u->GetSkill(S_CREATE_PHANTASMAL_UNDEAD); int create,max; @@ -1485,7 +1454,7 @@ int Game::RunPhanUndead(ARegion *r,Unit *u) int Game::RunPhanBeasts(ARegion *r,Unit *u) { - CastIntOrder *order = (CastIntOrder *) u->castorders; + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); int level = u->GetSkill(S_CREATE_PHANTASMAL_BEASTS); int create,max; @@ -1558,8 +1527,7 @@ int Game::RunClearSkies(ARegion *r, Unit *u) string temp = "Casts Clear Skies"; int val; - CastRegionOrder *order = (CastRegionOrder *)u->castorders; - + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); RangeType *range = FindRange(SkillDefs[S_CLEAR_SKIES].range); if (range != NULL) { tar = regions.GetRegion(order->xloc, order->yloc, order->zloc); @@ -1579,8 +1547,7 @@ int Game::RunWeatherLore(ARegion *r, Unit *u) ARegion *tar; int val, i; - CastRegionOrder *order = (CastRegionOrder *)u->castorders; - + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); tar = regions.GetRegion(order->xloc, order->yloc, order->zloc); val = GetRegionInRange(r, tar, u, S_WEATHER_LORE); if (!val) return 0; @@ -1612,8 +1579,7 @@ int Game::RunFarsight(ARegion *r,Unit *u) ARegion *tar; int val; - CastRegionOrder *order = (CastRegionOrder *)u->castorders; - + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); tar = regions.GetRegion(order->xloc, order->yloc, order->zloc); val = GetRegionInRange(r, tar, u, S_FARSIGHT); if (!val) return 0; @@ -1666,8 +1632,7 @@ int Game::RunTeleport(ARegion *r,Object *o,Unit *u) ARegion *tar; int val; - CastRegionOrder *order = (CastRegionOrder *)u->teleportorders; - + std::shared_ptr order = u->teleportorders; tar = regions.GetRegion(order->xloc, order->yloc, order->zloc); val = GetRegionInRange(r, tar, u, S_TELEPORTATION); if (!val) return 0; @@ -1717,8 +1682,7 @@ int Game::RunGateJump(ARegion *r,Object *o,Unit *u) return 0; } - TeleportOrder *order = u->teleportorders; - + std::shared_ptr order = u->teleportorders; if ((order->gate > 0 && level < 2) || (order->gate == -2 && level < 2)) { u->error("CAST: Unit Doesn't know Gate Lore at that level."); @@ -1875,8 +1839,7 @@ int Game::RunGateJump(ARegion *r,Object *o,Unit *u) int Game::RunPortalLore(ARegion *r,Object *o,Unit *u) { int level = u->GetSkill(S_PORTAL_LORE); - TeleportOrder *order = u->teleportorders; - + std::shared_ptr order = u->teleportorders; if (!level) { u->error("CAST: Doesn't know Portal Lore."); return 0; @@ -1967,10 +1930,9 @@ int Game::RunPortalLore(ARegion *r,Object *o,Unit *u) int Game::RunTransmutation(ARegion *r, Unit *u) { - CastTransmuteOrder *order; int level, num, source; - order = (CastTransmuteOrder *) u->castorders; + std::shared_ptr order = std::dynamic_pointer_cast(u->castorders); level = u->GetSkill(S_TRANSMUTATION); if (!level) { u->error("CAST: Unit doesn't have that skill."); @@ -2133,8 +2095,7 @@ void Game::RunTeleportOrders() } if (val) u->Practice(u->teleportorders->spell); - delete u->teleportorders; - u->teleportorders = 0; + u->teleportorders = nullptr; break; } } diff --git a/unit.cpp b/unit.cpp index d6413999..662fd865 100644 --- a/unit.cpp +++ b/unit.cpp @@ -73,19 +73,19 @@ Unit::Unit() } readyItem = -1; object = 0; - attackorders = NULL; - evictorders = NULL; - stealorders = NULL; - monthorders = NULL; - castorders = NULL; + attackorders = nullptr; + evictorders = nullptr; + stealthorders = nullptr; + monthorders = nullptr; + castorders = nullptr; sacrificeorders = nullptr; annihilateorders = nullptr; - teleportorders = NULL; - joinorders = NULL; + teleportorders = nullptr; + joinorders = nullptr; inTurnBlock = 0; presentTaxing = 0; - presentMonthOrders = NULL; - former = NULL; + presentMonthOrders = nullptr; + former = nullptr; format = 0; free = 0; practiced = 0; @@ -119,19 +119,19 @@ Unit::Unit(int seq, Faction *f, int a) } readyItem = -1; object = 0; - attackorders = NULL; - evictorders = NULL; - stealorders = NULL; - monthorders = NULL; - castorders = NULL; - teleportorders = NULL; - joinorders = NULL; + attackorders = nullptr; + evictorders = nullptr; + stealthorders = nullptr; + monthorders = nullptr; + castorders = nullptr; + teleportorders = nullptr; + joinorders = nullptr; sacrificeorders = nullptr; annihilateorders = nullptr; inTurnBlock = 0; presentTaxing = 0; - presentMonthOrders = NULL; - former = NULL; + presentMonthOrders = nullptr; + former = nullptr; format = 0; free = 0; practiced = 0; @@ -146,10 +146,6 @@ Unit::Unit(int seq, Faction *f, int a) Unit::~Unit() { - if (monthorders) delete monthorders; - if (presentMonthOrders) delete presentMonthOrders; - if (attackorders) delete attackorders; - if (stealorders) delete stealorders; if (name) delete name; if (describe) delete describe; } @@ -377,7 +373,7 @@ int Unit::CanGetSpoil(Item *i) return 0; load = items.Weight(); - + if (flags & FLAG_FLYSPOILS) { capacity = ItemDefs[i->type].fly; if (FlyingCapacity() + capacity < load + weight) @@ -481,10 +477,8 @@ json Unit::write_json_orders() // and then re-added to the end of the list if it was a repeating turn order. wrapping here uses the same stack as // above in the same way. bool wrap_turn_block = has_continuing_month_order; - if (turnorders.First()) { - TurnOrder *tOrder; - forlist(&turnorders) { - tOrder = (TurnOrder *)elem; + if (turnorders.size()) { + for(auto tOrder: turnorders) { if (wrap_turn_block) { container.push_back( { { "order", (tOrder->repeating ? "@TURN" : "TURN") } } ); parent_stack.push(container); @@ -521,7 +515,7 @@ json Unit::write_json_orders() wrap_turn_block = true; // All future turn blocks get wrapped. } // Now, move the container back to the end of the list if it was a repeating turn order and it got unwrapped - tOrder = (TurnOrder *) turnorders.First(); + std::shared_ptr tOrder = turnorders.front(); if (tOrder->repeating && !has_continuing_month_order) { container.push_back( { { "order", "@TURN" } } ); parent_stack.push(container); @@ -657,7 +651,7 @@ void Unit::build_json_report(json& j, int obs, int truesight, int detfac, int au } } } - + if ((type == U_MAGE || type == U_GUARDMAGE) && combat != -1) { j["combat_spell"] = { { "name", SkillDefs[combat].name }, { "tag", SkillDefs[combat].abbr } }; } @@ -692,7 +686,7 @@ void Unit::build_json_report(json& j, int obs, int truesight, int detfac, int au // For the JSON report, the best location for order information is on the unit itself. j["orders"] = write_json_orders(); - + } j["items"] = json::array(); @@ -782,35 +776,25 @@ void Unit::ClearOrders() enter = 0; build = 0; destroy = 0; - if (attackorders) delete attackorders; - attackorders = 0; - if (evictorders) delete evictorders; - evictorders = 0; - if (stealorders) delete stealorders; - stealorders = 0; - promote = 0; + attackorders = nullptr; + evictorders = nullptr; + stealthorders = nullptr; + promote = nullptr; taxing = TAX_NONE; - advancefrom = 0; - if (monthorders) delete monthorders; - monthorders = 0; + advancefrom = nullptr; + monthorders = nullptr; inTurnBlock = 0; presentTaxing = 0; - if (presentMonthOrders) delete presentMonthOrders; - presentMonthOrders = 0; - if (castorders) delete castorders; - castorders = 0; - if (teleportorders) delete teleportorders; - teleportorders = 0; - if (sacrificeorders) delete sacrificeorders; - sacrificeorders = 0; + presentMonthOrders = nullptr; + castorders = nullptr; + teleportorders = nullptr; + sacrificeorders = nullptr; } void Unit::ClearCastOrders() { - if (castorders) delete castorders; - castorders = 0; - if (teleportorders) delete teleportorders; - teleportorders = 0; + castorders = nullptr; + teleportorders = nullptr; } void Unit::DefaultOrders(Object *obj) @@ -921,16 +905,15 @@ void Unit::DefaultOrders(Object *obj) int dir = directions[dirIndex]; if (dir >= 0) { - MoveOrder *o = new MoveOrder; + std::shared_ptr o = std::make_shared(); o->advancing = 0; if (getrandom(100) < aggression) { o->advancing = 1; } - MoveDir *d = new MoveDir; - d->dir = dir; - o->dirs.Add(d); + MoveDir d(dir); + o->dirs.push_back(d); monthorders = o; } } @@ -952,7 +935,7 @@ void Unit::DefaultOrders(Object *obj) Globals->TAX_PILLAGE_MONTH_LONG && Taxers(1)) { taxing = TAX_AUTO; } else { - ProduceOrder *order = new ProduceOrder; + std::shared_ptr order = std::make_shared(); order->skill = -1; order->item = I_SILVER; order->target = 0; @@ -1104,7 +1087,7 @@ int Unit::GetSharedNum(int item) forlist((&object->region->objects)) { Object *obj = (Object *) elem; for(auto u: obj->units) { - if ((u->num == num) || + if ((u->num == num) || (u->faction == faction && u->GetFlag(FLAG_SHARING))) count += u->items.GetNum(item); } @@ -1332,7 +1315,7 @@ int Unit::GetAvailSkill(int sk) grant = ItemDefs[i->type].minGrant; if (grant > ItemDefs[i->type].maxGrant) grant = ItemDefs[i->type].maxGrant; - + if (grant > retval) retval = grant; } @@ -1401,7 +1384,7 @@ int Unit::CanStudy(int sk) if (!Globals->MAGE_NONLEADERS || !(SkillDefs[sk].flags & SkillType::MAGIC)) return 0; } - + int curlev = GetRealSkill(sk); if (SkillDefs[sk].flags & SkillType::DISABLED) return 0; @@ -1953,7 +1936,7 @@ static int ContributesToMovement(int movetype, int item) return ItemDefs[item].swim; break; } - + return 0; } @@ -2121,7 +2104,7 @@ int Unit::Taxers(int numtaxers) int basetax = 0; int weapontax = 0; int armortax = 0; - + // check out items int numMelee= 0; int numUsableMelee = 0; @@ -2211,7 +2194,7 @@ int Unit::Taxers(int numtaxers) else creatures += pItem->num; } - + if (ItemDefs[pItem->type].type & IT_ARMOR) { numArmor += pItem->num; } @@ -2230,7 +2213,7 @@ int Unit::Taxers(int numtaxers) GetSkill(S_STEALTH))) { basetax = totalMen; taxers = totalMen; - + // Weapon tax bonus if ((Globals->WHO_CAN_TAX & GameDefs::TAX_ANYONE) || ((Globals->WHO_CAN_TAX & GameDefs::TAX_COMBAT_SKILL) && @@ -2244,7 +2227,7 @@ int Unit::Taxers(int numtaxers) } weapontax += numMelee; } - + if (((Globals->WHO_CAN_TAX & GameDefs::TAX_BOW_SKILL) && (GetSkill(S_CROSSBOW) || GetSkill(S_LONGBOW)))) { weapontax += numUsableBows; @@ -2253,7 +2236,7 @@ int Unit::Taxers(int numtaxers) GetSkill(S_RIDING)) { if (weapontax < numUsableMounts) weapontax = numUsableMounts; } - + } else { if (Globals->WHO_CAN_TAX & GameDefs::TAX_USABLE_WEAPON) { @@ -2314,7 +2297,7 @@ int Unit::Taxers(int numtaxers) weapontax += numUsableBattle; taxers += numUsableBattle; } - + } // Ok, all the items categories done - check for mages taxing @@ -2366,13 +2349,13 @@ int Unit::Taxers(int numtaxers) } } } - + armortax = numArmor; - + // Check for overabundance if (weapontax > totalMen) weapontax = totalMen; if (armortax > weapontax) armortax = weapontax; - + // Adjust basetax in case of weapon taxation if (basetax < weapontax) basetax = weapontax; @@ -2389,7 +2372,7 @@ int Unit::Taxers(int numtaxers) basetax += illusions; taxers += illusions; } - + if (numtaxers) return(taxers); int taxes = Globals->TAX_BASE_INCOME * basetax @@ -2592,7 +2575,7 @@ void Unit::DiscardUnfinishedShips() { items.SetNum(i,0); } } - if (discard > 0) event("discards all unfinished ships.", "discard"); + if (discard > 0) event("discards all unfinished ships.", "discard"); } void Unit::event(const string& message, const string& category, ARegion *r) @@ -2700,7 +2683,7 @@ int Unit::GetAttribute(char const *attrib) } else base = monbase; // monster units have no men - } + } return base; } diff --git a/unit.h b/unit.h index 6ac89dae..fe645e30 100644 --- a/unit.h +++ b/unit.h @@ -269,30 +269,29 @@ class Unit int enter; int build; UnitId *promote; - AList findorders; - AList giveorders; - AList withdraworders; - AList bankorders; - AList buyorders; - AList sellorders; - AList forgetorders; - CastOrder *castorders; - TeleportOrder *teleportorders; - Order *stealorders; - Order *monthorders; - AttackOrder *attackorders; - EvictOrder *evictorders; - SacrificeOrder *sacrificeorders; - AnnihilateOrder *annihilateorders; + std::vector> findorders; + std::vector> giveorders; + std::vector> withdraworders; + std::vector> buyorders; + std::vector> sellorders; + std::vector> forgetorders; + std::shared_ptr castorders; + std::shared_ptr teleportorders; + std::shared_ptrstealthorders; + std::shared_ptr monthorders; + std::shared_ptr attackorders; + std::shared_ptr evictorders; + std::shared_ptr sacrificeorders; + std::shared_ptr annihilateorders; ARegion *advancefrom; - AList exchangeorders; - AList turnorders; + std::vector> exchangeorders; + std::list> turnorders; int inTurnBlock; - Order *presentMonthOrders; + std::shared_ptr presentMonthOrders; int presentTaxing; - AList transportorders; - Order *joinorders; + std::vector> transportorders; + std::shared_ptr joinorders; Unit *former; int format; diff --git a/unittest/quartermaster_test.cpp b/unittest/quartermaster_test.cpp index 859ec5f1..365d148c 100644 --- a/unittest/quartermaster_test.cpp +++ b/unittest/quartermaster_test.cpp @@ -48,13 +48,13 @@ ut::suite<"Quartermaster"> quartermaster_suite = [] helper.parse_orders(faction->num, ss); helper.check_transport_orders(); - helper.transport_phase(TransportOrder::SHIP_TO_QM); + helper.transport_phase(TransportOrder::TransportPhase::SHIP_TO_QM); expect(unit1->items.GetNum(I_STONE) == 50_i); expect(qm1->items.GetNum(I_STONE) == 50_i); expect(qm2->items.GetNum(I_STONE) == 0_i); expect(unit2->items.GetNum(I_STONE) == 0_i); - helper.transport_phase(TransportOrder::INTER_QM_TRANSPORT); + helper.transport_phase(TransportOrder::TransportPhase::INTER_QM_TRANSPORT); expect(unit1->items.GetNum(I_STONE) == 50_i); expect(qm1->items.GetNum(I_STONE) == 0_i); expect(qm2->transport_items.GetNum(I_STONE) == 50_i); @@ -68,7 +68,7 @@ ut::suite<"Quartermaster"> quartermaster_suite = [] expect(qm2->items.GetNum(I_STONE) == 50_i); expect(unit2->items.GetNum(I_STONE) == 0_i); - helper.transport_phase(TransportOrder::DISTRIBUTE_FROM_QM); + helper.transport_phase(TransportOrder::TransportPhase::DISTRIBUTE_FROM_QM); expect(unit1->items.GetNum(I_STONE) == 50_i); expect(qm1->items.GetNum(I_STONE) == 0_i); expect(qm2->items.GetNum(I_STONE) == 0_i); @@ -116,14 +116,14 @@ ut::suite<"Quartermaster"> quartermaster_suite = [] helper.parse_orders(faction->num, ss); helper.check_transport_orders(); - helper.transport_phase(TransportOrder::SHIP_TO_QM); + helper.transport_phase(TransportOrder::TransportPhase::SHIP_TO_QM); expect(unit1->items.GetNum(I_STONE) == 50_i); expect(qm1->items.GetNum(I_STONE) == 50_i); expect(qm2->items.GetNum(I_STONE) == 0_i); expect(qm3->items.GetNum(I_STONE) == 0_i); expect(unit2->items.GetNum(I_STONE) == 0_i); - helper.transport_phase(TransportOrder::INTER_QM_TRANSPORT); + helper.transport_phase(TransportOrder::TransportPhase::INTER_QM_TRANSPORT); expect(unit1->items.GetNum(I_STONE) == 50_i); expect(qm1->items.GetNum(I_STONE) == 0_i); expect(qm2->transport_items.GetNum(I_STONE) == 50_i); @@ -142,7 +142,7 @@ ut::suite<"Quartermaster"> quartermaster_suite = [] expect(qm3->items.GetNum(I_STONE) == 0_i); expect(unit2->items.GetNum(I_STONE) == 0_i); - helper.transport_phase(TransportOrder::DISTRIBUTE_FROM_QM); + helper.transport_phase(TransportOrder::TransportPhase::DISTRIBUTE_FROM_QM); expect(unit1->items.GetNum(I_STONE) == 50_i); expect(qm1->items.GetNum(I_STONE) == 0_i); expect(qm2->items.GetNum(I_STONE) == 50_i);