1 /* Copyright (C) 2013-2014 Michal Brzozowski (rusolis@poczta.fm)
2 
3    This file is part of KeeperRL.
4 
5    KeeperRL is free software; you can redistribute it and/or modify it under the terms of the
6    GNU General Public License as published by the Free Software Foundation; either version 2
7    of the License, or (at your option) any later version.
8 
9    KeeperRL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10    even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License along with this program.
14    If not, see http://www.gnu.org/licenses/ . */
15 #pragma once
16 
17 #include "move_info.h"
18 #include "task_callback.h"
19 #include "resource_id.h"
20 #include "event_listener.h"
21 #include "entity_map.h"
22 #include "minion_trait.h"
23 #include "spawn_type.h"
24 
25 class CollectiveAttack;
26 class Creature;
27 class CollectiveControl;
28 class Tribe;
29 class TribeId;
30 class Level;
31 class Trigger;
32 struct AttractionInfo;
33 class MinionEquipment;
34 class TaskMap;
35 class KnownTiles;
36 class CollectiveTeams;
37 class ConstructionMap;
38 class Technology;
39 class CollectiveConfig;
40 class CostInfo;
41 struct TriggerInfo;
42 class Territory;
43 struct CollectiveName;
44 class Workshops;
45 class TileEfficiency;
46 class Zones;
47 struct ItemFetchInfo;
48 class CollectiveWarnings;
49 class Immigration;
50 
51 class Collective : public TaskCallback, public UniqueEntity<Collective>, public EventListener<Collective> {
52   public:
53   static PCollective create(WLevel, TribeId, const optional<CollectiveName>&, bool discoverable);
54   void init(CollectiveConfig&&, Immigration&&);
55   void acquireInitialTech();
56   void addCreature(WCreature, EnumSet<MinionTrait>);
57   void addCreature(PCreature, Position, EnumSet<MinionTrait>);
58   MoveInfo getMove(WCreature);
59   void setControl(PCollectiveControl);
60   void tick();
61   void update(bool currentlyActive);
62   TribeId getTribeId() const;
63   Tribe* getTribe() const;
64   WLevel getLevel() const;
65   WModel getModel() const;
66   WGame getGame() const;
67   void addNewCreatureMessage(const vector<WCreature>&);
68   void setTask(WCreature, PTask);
69   bool hasTask(WConstCreature) const;
70   void cancelTask(WConstCreature);
71   void banishCreature(WCreature);
72   bool wasBanished(WConstCreature) const;
73   void setVillainType(VillainType);
74   bool isDiscoverable() const;
75   void setEnemyId(EnemyId);
76   VillainType getVillainType() const;
77   optional<EnemyId> getEnemyId() const;
78   WCollectiveControl getControl() const;
79   double getLocalTime() const;
80   double getGlobalTime() const;
81 
82   typedef CollectiveResourceId ResourceId;
83 
84   SERIALIZATION_DECL(Collective)
85 
86   const vector<WCreature>& getCreatures() const;
87   bool isConquered() const;
88 
89   const vector<WCreature>& getCreatures(SpawnType) const;
90   const vector<WCreature>& getCreatures(MinionTrait) const;
91   vector<WCreature> getCreaturesAnyOf(EnumSet<MinionTrait>) const;
92   bool hasTrait(WConstCreature, MinionTrait) const;
93   bool hasAnyTrait(WConstCreature, EnumSet<MinionTrait>) const;
94   void setTrait(WCreature c, MinionTrait);
95   void removeTrait(WCreature c, MinionTrait);
96 
97   bool canPillage() const;
98   bool hasTradeItems() const;
99   vector<WItem> getTradeItems() const;
100   PItem buyItem(WItem);
101   vector<TriggerInfo> getTriggers(WConstCollective against) const;
102 
103   double getEfficiency(WConstCreature) const;
104   WConstCreature getLeader() const;
105   WCreature getLeader();
106   bool hasLeader() const;
107   void clearLeader();
108 
109   const Territory& getTerritory() const;
110   Territory& getTerritory();
111   bool canClaimSquare(Position pos) const;
112   void claimSquare(Position);
113   const KnownTiles& getKnownTiles() const;
114   const TileEfficiency& getTileEfficiency() const;
115   void retire();
116   CollectiveWarnings& getWarnings();
117   const CollectiveConfig& getConfig() const;
118 
119   bool usesEquipment(WConstCreature) const;
120 
121   virtual ~Collective();
122 
123   int numResource(ResourceId) const;
124   int numResourcePlusDebt(ResourceId) const;
125   bool hasResource(const CostInfo&) const;
126   void takeResource(const CostInfo&);
127   void returnResource(const CostInfo&);
128 
129   const ConstructionMap& getConstructions() const;
130 
131   void setMinionTask(WConstCreature c, MinionTask task);
132   optional<MinionTask> getMinionTask(WConstCreature) const;
133   bool isMinionTaskPossible(WCreature c, MinionTask task);
134 
135   vector<WItem> getAllItems(bool includeMinions = true) const;
136   vector<WItem> getAllItems(ItemPredicate predicate, bool includeMinions = true) const;
137   vector<WItem> getAllItems(ItemIndex, bool includeMinions = true) const;
138 
139   vector<pair<WItem, Position>> getTrapItems(TrapType, const vector<Position>&) const;
140 
141   void addTrap(Position, TrapType);
142   void removeTrap(Position);
143   bool canAddFurniture(Position, FurnitureType) const;
144   void addFurniture(Position, FurnitureType, const CostInfo&, bool noCredit);
145   void removeFurniture(Position, FurnitureLayer);
146   void destroySquare(Position, FurnitureLayer);
147   bool isPlannedTorch(Position) const;
148   bool canPlaceTorch(Position) const;
149   void removeTorch(Position);
150   void addTorch(Position);
151   Zones& getZones();
152   const Zones& getZones() const;
153   void cancelMarkedTask(Position);
154   void orderDestruction(Position pos, const DestroyAction&);
155   double getDangerLevel() const;
156   bool isMarked(Position) const;
157   HighlightType getMarkHighlight(Position) const;
158   void setPriorityTasks(Position);
159   bool hasPriorityTasks(Position) const;
160 
161   bool hasTech(TechId id) const;
162   void acquireTech(Technology*);
163   vector<Technology*> getTechnologies() const;
164   bool addKnownTile(Position);
165 
166   const EntitySet<Creature>& getKills() const;
167   int getPoints() const;
168 
169   MinionEquipment& getMinionEquipment();
170   const MinionEquipment& getMinionEquipment() const;
171   optional<FurnitureType> getMissingTrainingFurniture(WConstCreature, ExperienceType) const;
172 
173   Workshops& getWorkshops();
174   const Workshops& getWorkshops() const;
175 
176   Immigration& getImmigration();
177   const Immigration& getImmigration() const;
178 
179   int getPopulationSize() const;
180   int getMaxPopulation() const;
181 
182   void orderConsumption(WCreature consumer, WCreature who);
183   vector<WCreature> getConsumptionTargets(WCreature consumer) const;
184   void addAttack(const CollectiveAttack&);
185   void onRansomPaid();
186   void onExternalEnemyKilled(const string& name);
187 
188   CollectiveTeams& getTeams();
189   const CollectiveTeams& getTeams() const;
190   void freeTeamMembers(TeamId);
191 
192   const optional<CollectiveName>& getName() const;
193   const TaskMap& getTaskMap() const;
194   TaskMap& getTaskMap();
195   void updateResourceProduction();
196   bool isItemMarked(WConstItem) const;
197   int getNumItems(ItemIndex, bool includeMinions = true) const;
198   optional<set<Position>> getStorageFor(WConstItem) const;
199 
200   void addKnownVillain(WConstCollective);
201   bool isKnownVillain(WConstCollective) const;
202   void addKnownVillainLocation(WConstCollective);
203   bool isKnownVillainLocation(WConstCollective) const;
204 
205   void onEvent(const GameEvent&);
206   void onPositionDiscovered(Position);
207 
208   private:
209   struct Private {};
210 
211   public:
212   Collective(Private, WLevel, TribeId, const optional<CollectiveName>&);
213 
214   protected:
215   // From Task::Callback
216   virtual void onAppliedItem(Position, WItem item) override;
217   virtual void onAppliedItemCancel(Position) override;
218   virtual void onConstructed(Position, FurnitureType) override;
219   virtual void onDestructed(Position, FurnitureType, const DestroyAction&) override;
220   virtual void onAppliedSquare(WCreature, Position) override;
221   virtual void onKillCancelled(WCreature) override;
222   virtual void onCopulated(WCreature who, WCreature with) override;
223   virtual bool isConstructionReachable(Position) override;
224 
225   private:
226   void addCreatureInTerritory(PCreature, EnumSet<MinionTrait>);
227   void removeCreature(WCreature);
228   void onMinionKilled(WCreature victim, WCreature killer);
229   void onKilledSomeone(WCreature victim, WCreature killer);
230 
231   void fetchItems(Position, const ItemFetchInfo&);
232 
233   void addMoraleForKill(WConstCreature killer, WConstCreature victim);
234   void decreaseMoraleForKill(WConstCreature killer, WConstCreature victim);
235   void decreaseMoraleForBanishing(WConstCreature);
236 
237   bool isItemNeeded(WConstItem) const;
238   void addProducesMessage(WConstCreature, const vector<PItem>&);
239   int getDebt(ResourceId id) const;
240 
241   HeapAllocated<MinionEquipment> SERIAL(minionEquipment);
242   EnumMap<ResourceId, int> SERIAL(credit);
243   HeapAllocated<TaskMap> SERIAL(taskMap);
244   vector<TechId> SERIAL(technologies);
245   void markItem(WConstItem, WConstTask);
246   void unmarkItem(UniqueEntity<Item>::Id);
247 
248   HeapAllocated<KnownTiles> SERIAL(knownTiles);
249 
250   struct CurrentTaskInfo {
251     MinionTask SERIAL(task);
252     // If none then it's a one-time task. Upon allocating the task, the variable is set to a negative value,
253     // so the job immediately times out after finishing the task.
254     optional<double> SERIAL(finishTime);
255 
256     SERIALIZE_ALL(task, finishTime)
257   };
258 
259   EntityMap<Creature, CurrentTaskInfo> SERIAL(currentTasks);
260   optional<Position> getTileToExplore(WConstCreature, MinionTask) const;
261   WTask getStandardTask(WCreature c);
262   PTask getEquipmentTask(WCreature c);
263   void considerHealingTask(WCreature c);
264   bool isTaskGood(WConstCreature, MinionTask, bool ignoreTaskLock = false) const;
265   void setRandomTask(WConstCreature);
266 
267   void handleSurprise(Position);
268   int getTaskDuration(WConstCreature, MinionTask) const;
269   void decayMorale();
270   vector<WCreature> SERIAL(creatures);
271   WCreature SERIAL(leader) = nullptr;
272   EnumMap<MinionTrait, vector<WCreature>> SERIAL(byTrait);
273   EnumMap<SpawnType, vector<WCreature>> SERIAL(bySpawnType);
274   PCollectiveControl SERIAL(control);
275   HeapAllocated<TribeId> SERIAL(tribe);
276   WLevel SERIAL(level) = nullptr;
277   HeapAllocated<Territory> SERIAL(territory);
278   struct AlarmInfo {
279     double SERIAL(finishTime);
280     Position SERIAL(position);
281     SERIALIZE_ALL(finishTime, position)
282   };
283   optional<AlarmInfo> SERIAL(alarmInfo);
284   HeapAllocated<ConstructionMap> SERIAL(constructions);
285   EntityMap<Item, WConstTask> SERIAL(markedItems);
286   EntitySet<Creature> SERIAL(surrendering);
287   void updateConstructions();
288   void handleTrapPlacementAndProduction();
289   void scheduleAutoProduction(function<bool (WConstItem)> itemPredicate, int count);
290   void delayDangerousTasks(const vector<Position>& enemyPos, double delayTime);
291   bool isDelayed(Position);
292   unordered_map<Position, double, CustomHash<Position>> SERIAL(delayedPos);
293   vector<Position> getEnemyPositions() const;
294   double manaRemainder = 0;
295   double getKillManaScore(WConstCreature) const;
296   void addMana(double);
297   EntitySet<Creature> SERIAL(kills);
298   int SERIAL(points) = 0;
299   HeapAllocated<CollectiveTeams> SERIAL(teams);
300   HeapAllocated<optional<CollectiveName>> SERIAL(name);
301   HeapAllocated<CollectiveConfig> SERIAL(config);
302   EntitySet<Creature> SERIAL(banished);
303   VillainType SERIAL(villainType);
304   optional<EnemyId> SERIAL(enemyId);
305   unique_ptr<Workshops> SERIAL(workshops);
306   HeapAllocated<Zones> SERIAL(zones);
307   HeapAllocated<TileEfficiency> SERIAL(tileEfficiency);
308   HeapAllocated<CollectiveWarnings> SERIAL(warnings);
309   PImmigration SERIAL(immigration);
310   mutable optional<double> dangerLevelCache;
311   EntitySet<Collective> SERIAL(knownVillains);
312   EntitySet<Collective> SERIAL(knownVillainLocations);
313   set<EnemyId> SERIAL(conqueredVillains);
314   void setDiscoverable();
315   bool SERIAL(discoverable) = false;
316 };
317