1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

- Refactoring for checking victory/loss conditions (use enum class instead of magic numbers)

- Improved showing player lost message for one special case
This commit is contained in:
beegee1 2013-11-17 17:57:04 +00:00
parent 2b6cdd5f41
commit 3e4407593f
12 changed files with 1008 additions and 910 deletions

View File

@ -192,14 +192,14 @@ void VCAI::showShipyardDialog(const IShipyard *obj)
NET_EVENT_HANDLER;
}
void VCAI::gameOver(PlayerColor player, bool victory)
void VCAI::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult)
{
LOG_TRACE_PARAMS(logAi, "victory '%i'", victory);
LOG_TRACE_PARAMS(logAi, "victoryLossCheckResult '%s'", victoryLossCheckResult);
NET_EVENT_HANDLER;
logAi->debugStream() << boost::format("Player %d: I heard that player %d %s.") % playerID % player.getNum() % (victory ? "won" : "lost");
logAi->debugStream() << boost::format("Player %d: I heard that player %d %s.") % playerID % player.getNum() % (victoryLossCheckResult.victory() ? "won" : "lost");
if(player == playerID)
{
if(victory)
if(victoryLossCheckResult.victory())
{
logAi->debugStream() << "VCAI: I won! Incredible!";
logAi->debugStream() << "Turn nr " << myCb->getDate();
@ -959,13 +959,13 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, BuildingID building, unsi
TResources currentRes = cb->getResourceAmount();
TResources income = estimateIncome();
//TODO: calculate if we have enough resources to build it in maxDays
for(const auto & buildID : toBuild)
{
const CBuilding *b = t->town->buildings.at(buildID);
EBuildingState::EBuildingState canBuild = cb->canBuildStructure(t, buildID);
if(canBuild == EBuildingState::ALLOWED)
for(const auto & buildID : toBuild)
{
const CBuilding *b = t->town->buildings.at(buildID);
EBuildingState::EBuildingState canBuild = cb->canBuildStructure(t, buildID);
if(canBuild == EBuildingState::ALLOWED)
{
if(!containsSavedRes(b->resources))
{
@ -974,13 +974,13 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, BuildingID building, unsi
return true;
}
continue;
}
else if(canBuild == EBuildingState::NO_RESOURCES)
{
TResources cost = t->town->buildings.at(buildID)->resources;
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
{
int diff = currentRes[i] - cost[i] + income[i];
}
else if(canBuild == EBuildingState::NO_RESOURCES)
{
TResources cost = t->town->buildings.at(buildID)->resources;
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
{
int diff = currentRes[i] - cost[i] + income[i];
if(diff < 0)
saving[i] = 1;
}

View File

@ -188,7 +188,7 @@ public:
virtual void playerBlocked(int reason, bool start) override;
virtual void showPuzzleMap() override;
virtual void showShipyardDialog(const IShipyard *obj) override;
virtual void gameOver(PlayerColor player, bool victory) override;
virtual void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
virtual void artifactPut(const ArtifactLocation &al) override;
virtual void artifactRemoved(const ArtifactLocation &al) override;
virtual void stacksErased(const StackLocation &location) override;

View File

@ -2069,13 +2069,13 @@ void CPlayerInterface::finishMovement( const TryMoveHero &details, const int3 &h
std::stable_sort(CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.end(), ocmptwo_cgin);
}
void CPlayerInterface::gameOver(PlayerColor player, bool victory )
void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult )
{
EVENT_HANDLER_CALLED_BY_CLIENT;
if(player == playerID)
{
if(!victory)
if(victoryLossCheckResult.loss())
showInfoDialog(CGI->generaltexth->allTexts[95]);
// else
// showInfoDialog("Placeholder message: you won!");
@ -2108,9 +2108,18 @@ void CPlayerInterface::gameOver(PlayerColor player, bool victory )
else
{
if(!victory && cb->getPlayerStatus(playerID) == EPlayerStatus::INGAME) //enemy has lost
if(victoryLossCheckResult.loss() && cb->getPlayerStatus(playerID) == EPlayerStatus::INGAME) //enemy has lost
{
std::string txt = CGI->generaltexth->allTexts[5]; //%s has been vanquished!
std::string txt;
if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER)
{
txt = CGI->generaltexth->allTexts[8]; // %s's heroes have abandoned him, and he is banished from this land.
}
else
{
txt = CGI->generaltexth->allTexts[5]; // %s has been vanquished!
}
boost::algorithm::replace_first(txt, "%s", CGI->generaltexth->capColors[player.getNum()]);
showInfoDialog(txt,std::vector<CComponent*>(1, new CComponent(CComponent::flag, player.getNum(), 0)));
}

View File

@ -184,7 +184,7 @@ public:
void centerView (int3 pos, int focusTime) override;
void objectPropertyChanged(const SetObjectProperty * sop) override;
void objectRemoved(const CGObjectInstance *obj) override;
void gameOver(PlayerColor player, bool victory) override;
void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface
void showComp(const Component &comp, std::string message) override; //display component in the advmapint infobox
void saveGame(COSer<CSaveFile> &h, const int version) override; //saving

View File

@ -292,7 +292,7 @@ void ChangeObjPos::applyCl( CClient *cl )
void PlayerEndsGame::applyCl( CClient *cl )
{
CALL_IN_ALL_INTERFACES(gameOver, player, victory);
CALL_IN_ALL_INTERFACES(gameOver, player, victoryLossCheckResult);
}
void RemoveBonus::applyCl( CClient *cl )
@ -409,30 +409,30 @@ void NewStructures::applyCl( CClient *cl )
{
CGTownInstance *town = GS(cl)->getTown(tid);
for(const auto & id : bid)
{
if(id == BuildingID::CAPITOL) //fort or capitol
{
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->capitols.at(town->subID).get());
}
if(id == BuildingID::FORT)
{
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->gobjs.at(Obj::TOWN).at(town->subID).get());
}
if(vstd::contains(cl->playerint,town->tempOwner))
cl->playerint[town->tempOwner]->buildChanged(town,id,1);
{
if(id == BuildingID::CAPITOL) //fort or capitol
{
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->capitols.at(town->subID).get());
}
if(id == BuildingID::FORT)
{
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->gobjs.at(Obj::TOWN).at(town->subID).get());
}
if(vstd::contains(cl->playerint,town->tempOwner))
cl->playerint[town->tempOwner]->buildChanged(town,id,1);
}
}
void RazeStructures::applyCl (CClient *cl)
{
CGTownInstance *town = GS(cl)->getTown(tid);
for(const auto & id : bid)
{
if (id == BuildingID::CAPITOL) //fort or capitol
{
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->gobjs.at(Obj::TOWN).at(town->subID).get());
}
if(vstd::contains (cl->playerint,town->tempOwner))
cl->playerint[town->tempOwner]->buildChanged (town,id,2);
{
if (id == BuildingID::CAPITOL) //fort or capitol
{
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->gobjs.at(Obj::TOWN).at(town->subID).get());
}
if(vstd::contains (cl->playerint,town->tempOwner))
cl->playerint[town->tempOwner]->buildChanged (town,id,2);
}
}
@ -532,13 +532,13 @@ void InfoWindow::applyCl( CClient *cl )
comps.push_back(&elem);
}
std::string str;
text.toString(str);
if(vstd::contains(cl->playerint,player))
cl->playerint.at(player)->showInfoDialog(str,comps,(soundBase::soundID)soundID);
else
logNetwork->warnStream() << "We received InfoWindow for not our player...";
}
text.toString(str);
if(vstd::contains(cl->playerint,player))
cl->playerint.at(player)->showInfoDialog(str,comps,(soundBase::soundID)soundID);
else
logNetwork->warnStream() << "We received InfoWindow for not our player...";
}
void SetObjectProperty::applyCl( CClient *cl )
{
@ -575,26 +575,26 @@ void CommanderLevelUp::applyCl( CClient *cl )
void BlockingDialog::applyCl( CClient *cl )
{
std::string str;
text.toString(str);
if(vstd::contains(cl->playerint,player))
cl->playerint.at(player)->showBlockingDialog(str,components,queryID,(soundBase::soundID)soundID,selection(),cancel());
else
logNetwork->warnStream() << "We received YesNoDialog for not our player...";
}
text.toString(str);
if(vstd::contains(cl->playerint,player))
cl->playerint.at(player)->showBlockingDialog(str,components,queryID,(soundBase::soundID)soundID,selection(),cancel());
else
logNetwork->warnStream() << "We received YesNoDialog for not our player...";
}
void GarrisonDialog::applyCl(CClient *cl)
{
const CGHeroInstance *h = cl->getHero(hid);
const CArmedInstance *obj = static_cast<const CArmedInstance*>(cl->getObj(objid));
if(!vstd::contains(cl->playerint,h->getOwner()))
return;
cl->playerint.at(h->getOwner())->showGarrisonDialog(obj,h,removableUnits,queryID);
}
void ExchangeDialog::applyCl(CClient *cl)
if(!vstd::contains(cl->playerint,h->getOwner()))
return;
cl->playerint.at(h->getOwner())->showGarrisonDialog(obj,h,removableUnits,queryID);
}
void ExchangeDialog::applyCl(CClient *cl)
{
assert(heroes[0] && heroes[1]);
INTERFACE_CALL_IF_PRESENT(heroes[0]->tempOwner, heroExchangeStarted, heroes[0]->id, heroes[1]->id, queryID);
@ -945,13 +945,13 @@ void SetAvailableArtifacts::applyCl(CClient *cl)
INTERFACE_CALL_IF_PRESENT(cl->getTile(bm->visitablePos())->visitableObjects.back()->tempOwner, availableArtifactsChanged, bm);
}
}
void TradeComponents::applyCl(CClient *cl)
{///Shop handler
switch (CGI->mh->map->objects.at(objectid)->ID)
{
case Obj::BLACK_MARKET:
break;
void TradeComponents::applyCl(CClient *cl)
{///Shop handler
switch (CGI->mh->map->objects.at(objectid)->ID)
{
case Obj::BLACK_MARKET:
break;
case Obj::TAVERN:
break;
case Obj::DEN_OF_THIEVES:

View File

@ -2032,23 +2032,29 @@ bool CGameState::checkForVisitableDir( const int3 & src, const TerrainTile *pom,
return true;
}
EVictoryLossCheckResult CGameState::checkForVictoryAndLoss(PlayerColor player) const
{
auto result = checkForVictory(player);
if (result == EVictoryLossCheckResult::NO_VICTORY_OR_LOSS) result = checkForLoss(player);
return result;
}
int CGameState::victoryCheck( PlayerColor player ) const
EVictoryLossCheckResult CGameState::checkForVictory( PlayerColor player ) const
{
const PlayerState *p = CGameInfoCallback::getPlayer(player);
if(map->victoryCondition.condition == EVictoryConditionType::WINSTANDARD || map->victoryCondition.allowNormalVictory
|| (!p->human && !map->victoryCondition.appliesToAI)) //if the special victory condition applies only to human, AI has the standard)
{
if(player == checkForStandardWin())
return -1;
return EVictoryLossCheckResult::VICTORY_STANDARD;
}
if (p->enteredWinningCheatCode)
{ //cheater or tester, but has entered the code...
if(map->victoryCondition.condition == EVictoryConditionType::WINSTANDARD)
return -1;
return EVictoryLossCheckResult::VICTORY_STANDARD;
else
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
if(p->human || map->victoryCondition.appliesToAI)
@ -2059,7 +2065,7 @@ int CGameState::victoryCheck( PlayerColor player ) const
//check if any hero has winning artifact
for(auto & elem : p->heroes)
if(elem->hasArt(map->victoryCondition.objectId))
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
@ -2081,13 +2087,13 @@ int CGameState::victoryCheck( PlayerColor player ) const
}
if(total >= map->victoryCondition.count)
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
break;
case EVictoryConditionType::GATHERRESOURCE:
if(p->resources[map->victoryCondition.objectId] >= map->victoryCondition.count)
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
@ -2095,7 +2101,7 @@ int CGameState::victoryCheck( PlayerColor player ) const
{
const CGTownInstance *t = static_cast<const CGTownInstance *>(map->victoryCondition.obj);
if(t->tempOwner == player && t->fortLevel()-1 >= map->victoryCondition.objectId && t->hallLevel()-1 >= map->victoryCondition.count)
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
break;
@ -2104,22 +2110,22 @@ int CGameState::victoryCheck( PlayerColor player ) const
if((t == map->victoryCondition.obj || !map->victoryCondition.obj)
&& t->tempOwner == player
&& t->hasBuilt(BuildingID::GRAIL))
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
case EVictoryConditionType::BEATHERO:
if(map->victoryCondition.obj->tempOwner >= PlayerColor::PLAYER_LIMIT) //target hero not present on map
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
case EVictoryConditionType::CAPTURECITY:
{
if(map->victoryCondition.obj->tempOwner == player)
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
break;
case EVictoryConditionType::BEATMONSTER:
if(!getObj(map->victoryCondition.obj->id)) //target monster not present on map
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
case EVictoryConditionType::TAKEDWELLINGS:
for(auto & elem : map->objects)
@ -2131,11 +2137,11 @@ int CGameState::victoryCheck( PlayerColor player ) const
case Obj::CREATURE_GENERATOR1: case Obj::CREATURE_GENERATOR2:
case Obj::CREATURE_GENERATOR3: case Obj::CREATURE_GENERATOR4:
case Obj::RANDOM_DWELLING: case Obj::RANDOM_DWELLING_LVL: case Obj::RANDOM_DWELLING_FACTION:
return 0; //found not flagged dwelling - player not won
return EVictoryLossCheckResult::NO_VICTORY_OR_LOSS; //found not flagged dwelling - player not won
}
}
}
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
case EVictoryConditionType::TAKEMINES:
for(auto & elem : map->objects)
{
@ -2144,25 +2150,25 @@ int CGameState::victoryCheck( PlayerColor player ) const
switch(elem->ID)
{
case Obj::MINE: case Obj::ABANDONED_MINE:
return 0; //found not flagged mine - player not won
return EVictoryLossCheckResult::NO_VICTORY_OR_LOSS; //found not flagged mine - player not won
}
}
}
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
case EVictoryConditionType::TRANSPORTITEM:
{
const CGTownInstance *t = static_cast<const CGTownInstance *>(map->victoryCondition.obj);
if((t->visitingHero && t->visitingHero->hasArt(map->victoryCondition.objectId))
|| (t->garrisonHero && t->garrisonHero->hasArt(map->victoryCondition.objectId)))
{
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
}
break;
}
}
return 0;
return EVictoryLossCheckResult::NO_VICTORY_OR_LOSS;
}
PlayerColor CGameState::checkForStandardWin() const
@ -2395,16 +2401,16 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
#undef FILL_FIELD
}
int CGameState::lossCheck( PlayerColor player ) const
EVictoryLossCheckResult CGameState::checkForLoss( PlayerColor player ) const
{
const PlayerState *p = CGameInfoCallback::getPlayer(player);
//if(map->lossCondition.typeOfLossCon == lossStandard)
if(checkForStandardLoss(player))
return -1;
return EVictoryLossCheckResult::LOSS_STANDARD_HEROES_AND_TOWNS;
if (p->enteredLosingCheatCode)
{
return 1;
return EVictoryLossCheckResult::LOSS_SPECIAL;
}
if(p->human) //special loss condition applies only to human player
@ -2417,20 +2423,20 @@ int CGameState::lossCheck( PlayerColor player ) const
const CGObjectInstance *obj = map->lossCondition.obj;
assert(obj);
if(obj->tempOwner != player)
return 1;
return EVictoryLossCheckResult::LOSS_SPECIAL;
}
break;
case ELossConditionType::TIMEEXPIRES:
if(map->lossCondition.timeLimit < day)
return 1;
return EVictoryLossCheckResult::LOSS_SPECIAL;
break;
}
}
if(!p->towns.size() && p->daysWithoutCastle >= 7)
return 2;
return EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER;
return false;
return EVictoryLossCheckResult::NO_VICTORY_OR_LOSS;
}
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > CGameState::unusedHeroesFromPool()
@ -3283,3 +3289,53 @@ CPathfinder::CPathfinder(CPathsInfo &_out, CGameState *_gs, const CGHeroInstance
useSubterraneanGates = true;
allowEmbarkAndDisembark = true;
}
const EVictoryLossCheckResult EVictoryLossCheckResult::NO_VICTORY_OR_LOSS = EVictoryLossCheckResult(0);
const EVictoryLossCheckResult EVictoryLossCheckResult::VICTORY_STANDARD = EVictoryLossCheckResult(1);
const EVictoryLossCheckResult EVictoryLossCheckResult::VICTORY_SPECIAL = EVictoryLossCheckResult(2);
const EVictoryLossCheckResult EVictoryLossCheckResult::LOSS_STANDARD_HEROES_AND_TOWNS = EVictoryLossCheckResult(3);
const EVictoryLossCheckResult EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER = EVictoryLossCheckResult(4);
const EVictoryLossCheckResult EVictoryLossCheckResult::LOSS_SPECIAL = EVictoryLossCheckResult(5);
EVictoryLossCheckResult::EVictoryLossCheckResult() : intValue(0)
{
}
EVictoryLossCheckResult::EVictoryLossCheckResult(si32 intValue) : intValue(intValue)
{
}
bool EVictoryLossCheckResult::operator==(EVictoryLossCheckResult const & other) const
{
return intValue == other.intValue;
}
bool EVictoryLossCheckResult::operator!=(EVictoryLossCheckResult const & other) const
{
return intValue != other.intValue;
}
bool EVictoryLossCheckResult::victory() const
{
return *this == VICTORY_STANDARD || *this == VICTORY_SPECIAL;
}
bool EVictoryLossCheckResult::loss() const
{
return !victory();
}
std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult)
{
if(victoryLossCheckResult == EVictoryLossCheckResult::NO_VICTORY_OR_LOSS) os << "No victory or loss";
else if(victoryLossCheckResult == EVictoryLossCheckResult::VICTORY_STANDARD) os << "Victory standard";
else if(victoryLossCheckResult == EVictoryLossCheckResult::VICTORY_SPECIAL) os << "Victory special";
else if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_STANDARD_HEROES_AND_TOWNS) os << "Loss standard heroes and towns";
else if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER) os << "Loss standard towns and time over";
else if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_SPECIAL) os << "Loss special";
else os << "Unknown type";
return os;
}

View File

@ -356,27 +356,55 @@ public:
struct BattleInfo;
class DLL_LINKAGE EVictoryLossCheckResult
{
public:
static const EVictoryLossCheckResult NO_VICTORY_OR_LOSS;
static const EVictoryLossCheckResult VICTORY_STANDARD;
static const EVictoryLossCheckResult VICTORY_SPECIAL;
static const EVictoryLossCheckResult LOSS_STANDARD_HEROES_AND_TOWNS;
static const EVictoryLossCheckResult LOSS_STANDARD_TOWNS_AND_TIME_OVER;
static const EVictoryLossCheckResult LOSS_SPECIAL;
EVictoryLossCheckResult();
bool operator==(EVictoryLossCheckResult const & other) const;
bool operator!=(EVictoryLossCheckResult const & other) const;
bool victory() const;
bool loss() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & intValue;
}
private:
EVictoryLossCheckResult(si32 intValue);
si32 intValue;
};
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult);
class DLL_LINKAGE CGameState : public CNonConstInfoCallback
{
public:
ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized)
PlayerColor currentPlayer; //ID of player currently having turn
ConstTransitivePtr<BattleInfo> curB; //current battle
ui32 day; //total number of days in game
ConstTransitivePtr<CMap> map;
std::map<PlayerColor, PlayerState> players;
std::map<TeamID, TeamState> teams;
CBonusSystemNode globalEffects;
struct DLL_LINKAGE HeroesPool
{
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > heroesPool; //[subID] - heroes available to buy; nullptr if not available
std::map<ui32,ui8> pavailable; // [subid] -> which players can recruit hero (binary flags)
CGHeroInstance * pickHeroFor(bool native, PlayerColor player, const CTown *town, std::map<ui32, ConstTransitivePtr<CGHeroInstance> > &available, const CHeroClass *bannedClass = nullptr) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
ConstTransitivePtr<BattleInfo> curB; //current battle
ui32 day; //total number of days in game
ConstTransitivePtr<CMap> map;
std::map<PlayerColor, PlayerState> players;
std::map<TeamID, TeamState> teams;
CBonusSystemNode globalEffects;
struct DLL_LINKAGE HeroesPool
{
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > heroesPool; //[subID] - heroes available to buy; nullptr if not available
std::map<ui32,ui8> pavailable; // [subid] -> which players can recruit hero (binary flags)
CGHeroInstance * pickHeroFor(bool native, PlayerColor player, const CTown *town, std::map<ui32, ConstTransitivePtr<CGHeroInstance> > &available, const CHeroClass *bannedClass = nullptr) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & heroesPool & pavailable;
}
} hpool; //we have here all heroes available on this map that are not hired
@ -404,15 +432,13 @@ public:
void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1); //calculates possible paths for hero, by default uses current hero position and movement left; returns pointer to newly allocated CPath or nullptr if path does not exists
int3 guardingCreaturePosition (int3 pos) const;
std::vector<CGObjectInstance*> guardingCreatures (int3 pos) const;
int victoryCheck(PlayerColor player) const; //checks if given player is winner; -1 if std victory, 1 if special victory, 0 else
int lossCheck(PlayerColor player) const; //checks if given player is loser; -1 if std loss, 1 if special, 0 else
PlayerColor checkForStandardWin() const; //returns color of player that accomplished standard victory conditions or 255 (NEUTRAL) if no winner
bool checkForStandardLoss(PlayerColor player) const; //checks if given player lost the game
void obtainPlayersStats(SThievesGuildInfo & tgi, int level); //fills tgi with info about other players that is available at given level of thieves' guild
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > unusedHeroesFromPool(); //heroes pool without heroes that are available in taverns
BattleInfo * setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town);
void buildBonusSystemTree();
EVictoryLossCheckResult checkForVictoryAndLoss(PlayerColor player) const;
void obtainPlayersStats(SThievesGuildInfo & tgi, int level); //fills tgi with info about other players that is available at given level of thieves' guild
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > unusedHeroesFromPool(); //heroes pool without heroes that are available in taverns
BattleInfo * setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town);
void buildBonusSystemTree();
void attachArmedObjects();
void buildGlobalTeamPlayerTree();
void deserializationFix();
@ -438,6 +464,12 @@ public:
friend class IGameCallback;
friend class CMapHandler;
friend class CGameHandler;
private:
EVictoryLossCheckResult checkForVictory(PlayerColor player) const; //checks if given player is winner
EVictoryLossCheckResult checkForLoss(PlayerColor player) const; //checks if given player is loser
PlayerColor checkForStandardWin() const; //returns color of player that accomplished standard victory conditions or 255 (NEUTRAL) if no winner
bool checkForStandardLoss(PlayerColor player) const; //checks if given player lost the game
};
struct DLL_LINKAGE QuestInfo //universal interface for human and AI

View File

@ -45,6 +45,7 @@ struct BattleTriggerEffect;
class CComponent;
struct CObstacleInstance;
struct CPackForServer;
class EVictoryLossCheckResult;
class DLL_LINKAGE IBattleEventsReceiver
{
@ -128,7 +129,7 @@ public:
virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
virtual void objectRemoved(const CGObjectInstance *obj){}; //eg. collected resource, picked artifact, beaten hero
virtual void playerBlocked(int reason, bool start){}; //reason: 0 - upcoming battle
virtual void gameOver(PlayerColor player, bool victory){}; //player lost or won the game
virtual void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) {}; //player lost or won the game
virtual void playerStartsTurn(PlayerColor player){};
virtual void showComp(const Component &comp, std::string message) {}; //display component in the advmapint infobox

View File

@ -481,11 +481,11 @@ struct PlayerEndsGame : public CPackForClient //117
DLL_LINKAGE void applyGs(CGameState *gs);
PlayerColor player;
ui8 victory;
EVictoryLossCheckResult victoryLossCheckResult;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & player & victory;
h & player & victoryLossCheckResult;
}
};

View File

@ -274,7 +274,8 @@ DLL_LINKAGE void ChangeObjPos::applyGs( CGameState *gs )
DLL_LINKAGE void PlayerEndsGame::applyGs( CGameState *gs )
{
PlayerState *p = gs->getPlayer(player);
p->status = victory ? EPlayerStatus::WINNER : EPlayerStatus::LOSER;
if(victoryLossCheckResult.victory()) p->status = EPlayerStatus::WINNER;
else p->status = EPlayerStatus::LOSER;
}
DLL_LINKAGE void RemoveBonus::applyGs( CGameState *gs )

File diff suppressed because it is too large Load Diff

View File

@ -81,8 +81,6 @@ struct CasualtiesAfterBattle
class CGameHandler : public IGameCallback, CBattleInfoCallback
{
private:
void makeStackDoNothing(const CStack * next);
public:
//use enums as parameters, because doMove(sth, true, false, true) is not readable
enum EGuardLook {CHECK_FOR_GUARDS, IGNORE_GUARDS};
@ -110,7 +108,6 @@ public:
void runBattle();
void checkLossVictory(PlayerColor player);
void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all
void getLossVicMessage(PlayerColor player, si8 standard, bool victory, InfoWindow &out) const;
////used only in endBattle - don't touch elsewhere
bool visitObjectAfterVictory;
@ -292,6 +289,10 @@ public:
void spawnWanderingMonsters(CreatureID creatureID);
friend class CVCMIServer;
friend class CScriptCallback;
private:
void makeStackDoNothing(const CStack * next);
void getVictoryLossMessage(PlayerColor player, EVictoryLossCheckResult victoryLossCheckResult, InfoWindow & out) const;
};
void makeStackDoNothing();