1 #include "stdafx.h"
2 #include "campaign.h"
3 #include "view_id.h"
4 #include "model.h"
5 #include "progress_meter.h"
6 #include "campaign_type.h"
7 #include "player_role.h"
8 #include "villain_type.h"
9 
10 SERIALIZATION_CONSTRUCTOR_IMPL(Campaign);
11 
SERIALIZE_DEF(Campaign,sites,playerPos,worldName,defeated,influencePos,influenceSize,playerRole,type) const12 SERIALIZE_DEF(Campaign, sites, playerPos, worldName, defeated, influencePos, influenceSize, playerRole, type)
13 
14 const Table<Campaign::SiteInfo>& Campaign::getSites() const {
15   return sites;
16 }
17 
canEmbark(Vec2 pos) const18 bool Campaign::canEmbark(Vec2 pos) const {
19   if (type == CampaignType::CAMPAIGN)
20     return false;
21   switch (playerRole) {
22     case PlayerRole::ADVENTURER: return !!sites[pos].dweller;
23     case PlayerRole::KEEPER: return !sites[pos].dweller && !sites[pos].blocked;
24   }
25 }
26 
getType() const27 CampaignType Campaign::getType() const {
28   return type;
29 }
30 
canTravelTo(Vec2 pos) const31 bool Campaign::canTravelTo(Vec2 pos) const {
32   return (isInInfluence(pos) || playerPos == pos) && !sites[pos].isEmpty();
33 }
34 
getPlayerPos() const35 optional<Vec2> Campaign::getPlayerPos() const {
36   return playerPos;
37 }
38 
Campaign(Table<SiteInfo> s,CampaignType t,PlayerRole r,const string & w)39 Campaign::Campaign(Table<SiteInfo> s, CampaignType t, PlayerRole r, const string& w)
40     : sites(s), worldName(w), defeated(sites.getBounds(), false), playerRole(r), type(t) {
41 }
42 
getWorldName() const43 const string& Campaign::getWorldName() const {
44   return worldName;
45 }
46 
clearSite(Vec2 v)47 void Campaign::clearSite(Vec2 v) {
48   sites[v] = SiteInfo{};
49   sites[v].viewId = {ViewId::GRASS};
50 }
51 
isDefeated(Vec2 pos) const52 bool Campaign::isDefeated(Vec2 pos) const {
53   return defeated[pos];
54 }
55 
setDefeated(Vec2 pos)56 void Campaign::setDefeated(Vec2 pos) {
57   defeated[pos] = true;
58   refreshInfluencePos();
59 }
60 
isEnemy() const61 bool Campaign::VillainInfo::isEnemy() const {
62   return type != VillainType::ALLY;
63 }
64 
getDescription() const65 string Campaign::VillainInfo::getDescription() const {
66   switch (type) {
67     case VillainType::ALLY: return "ally";
68     case VillainType::MAIN: return "main villain";
69     case VillainType::LESSER: return "lesser villain";
70     case VillainType::PLAYER: return "player";
71     case VillainType::NONE:
72       FATAL << "Tried to present villain of type NONE in campaign";
73       return "player";
74   }
75 }
76 
getVillain() const77 optional<Campaign::VillainInfo> Campaign::SiteInfo::getVillain() const {
78   if (dweller)
79     return dweller->getValueMaybe<VillainInfo>();
80   return none;
81 }
82 
getKeeper() const83 optional<Campaign::KeeperInfo> Campaign::SiteInfo::getKeeper() const {
84   if (dweller)
85     return dweller->getValueMaybe<KeeperInfo>();
86   return none;
87 }
88 
getRetired() const89 optional<Campaign::RetiredInfo> Campaign::SiteInfo::getRetired() const {
90   if (dweller)
91     return dweller->getValueMaybe<RetiredInfo>();
92   return none;
93 }
94 
isEmpty() const95 bool Campaign::SiteInfo::isEmpty() const {
96   return !dweller;
97 }
98 
getDwellerDescription() const99 optional<string> Campaign::SiteInfo::getDwellerDescription() const {
100   if (dweller)
101     return dweller->match(
102         [](const VillainInfo& info) { return info.name + " (" + info.getDescription() + ")"; },
103         [](const RetiredInfo& info) { return info.gameInfo.getName() + " (main villain)" ;},
104         [](const KeeperInfo&)->string { return "This is your home site"; });
105   else
106     return none;
107 }
108 
getVillainType() const109 optional<VillainType> Campaign::SiteInfo::getVillainType() const {
110   if (dweller)
111     return dweller->match(
112         [](const VillainInfo& info) { return info.type; },
113         [](const RetiredInfo&) { return VillainType::MAIN; },
114         [](const KeeperInfo&) { return VillainType::PLAYER; });
115   else
116     return none;
117 }
118 
getDwellerViewId() const119 optional<ViewId> Campaign::SiteInfo::getDwellerViewId() const {
120   if (dweller)
121     return dweller->match(
122         [](const VillainInfo& info) { return info.viewId; },
123         [](const RetiredInfo& info) { return info.gameInfo.getViewId(); },
124         [](const KeeperInfo& info) { return info.viewId; });
125   else
126     return none;
127 }
128 
isEnemy() const129 bool Campaign::SiteInfo::isEnemy() const {
130   return getRetired() || (getVillain() && getVillain()->isEnemy());
131 }
132 
setBlocked()133 void Campaign::SiteInfo::setBlocked() {
134   blocked = true;
135   viewId.push_back(Random.choose(ViewId::MAP_MOUNTAIN1, ViewId::MAP_MOUNTAIN2, ViewId::MAP_MOUNTAIN3,
136         ViewId::CANIF_TREE, ViewId::DECID_TREE));
137 }
138 
isInInfluence(Vec2 pos) const139 bool Campaign::isInInfluence(Vec2 pos) const {
140   return influencePos.count(pos);
141 }
142 
refreshInfluencePos()143 void Campaign::refreshInfluencePos() {
144   influencePos.clear();
145   if (!playerPos)
146     return;
147   for (double r = 1; r <= max(sites.getWidth(), sites.getHeight()); r += 0.1) {
148     for (Vec2 v : sites.getBounds())
149       if ((sites[v].getVillain() || sites[v].getRetired()) && v.distD(*playerPos) <= r)
150         influencePos.insert(v);
151     int numEnemies = 0;
152     for (Vec2 v : influencePos)
153       if (sites[v].isEnemy() && !defeated[v])
154         ++numEnemies;
155     if (numEnemies >= influenceSize)
156       break;
157   }
158 }
159 
getNumNonEmpty() const160 int Campaign::getNumNonEmpty() const {
161   int ret = 0;
162   for (Vec2 v : sites.getBounds())
163     if (!sites[v].isEmpty())
164       ++ret;
165   return ret;
166 }
167 
getParameters() const168 map<string, string> Campaign::getParameters() const {
169   int numMain = 0;
170   int numLesser = 0;
171   int numAlly = 0;
172   int numRetired = 0;
173   for (Vec2 v : sites.getBounds())
174     if (sites[v].getRetired())
175       ++numRetired;
176     else if (auto villain = sites[v].getVillain())
177       switch (villain->type) {
178         case VillainType::ALLY: ++numAlly; break;
179         case VillainType::MAIN: ++numMain; break;
180         case VillainType::LESSER: ++numLesser; break;
181         default: break;
182       }
183   return {
184     {"main", toString(numMain)},
185     {"lesser", toString(numLesser)},
186     {"allies", toString(numAlly)},
187     {"retired", toString(numRetired)},
188     {"player_role", EnumInfo<PlayerRole>::getString(playerRole)},
189     {"game_type", EnumInfo<CampaignType>::getString(type)},
190   };
191 }
192 
getPlayerRole() const193 PlayerRole Campaign::getPlayerRole() const {
194   return playerRole;
195 }
196