forked from Atlantis-PBEM/Atlantis
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathunit.h
488 lines (381 loc) · 12.4 KB
/
unit.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
#ifndef UNIT_CLASS
#define UNIT_CLASS
// START A3HEADER
//
// This source file is part of the Atlantis PBM game program.
// Copyright (C) 1995-1999 Geoff Dunbar
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program, in the file license.txt. If not, write
// to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
// See the Atlantis Project web page for details:
// http://www.prankster.com/project
//
// END A3HEADER
#include "alist.h"
#include "skills.h"
#include "items.h"
#include "helper.h"
#include "movetype.h"
class Ainfile;
class Aoutfile;
class ARegion;
class Areport;
class AttackOrder;
class CastOrder;
class EvictOrder;
class IEvent;
class JoinOrder;
class JsonReport;
class Object;
class Order;
class TeleportOrder;
class Unit; // defined locally
//----------------------------------------------------------------------------
/// Ways a unit can be on guard
enum
{
GUARD_NONE,
GUARD_GUARD,
GUARD_AVOID,
GUARD_SET,
GUARD_ADVANCE
};
/// Ways a unit can tax/pillage
enum
{
TAX_NONE,
TAX_TAX,
TAX_PILLAGE,
TAX_AUTO
};
/// Ways a unit can reveal itself
enum
{
REVEAL_NONE,
REVEAL_UNIT,
REVEAL_FACTION
};
/// Types of units
enum
{
U_NORMAL,
U_MAGE,
U_GUARD,
U_WMON,
U_GUARDMAGE,
U_APPRENTICE,
NUNITTYPES
};
/// maximum number of ready weapons or armors
enum { MAX_READY = 4 };
/// Unit flags (set of standing orders)
enum
{
FLAG_BEHIND = 0x0001, ///< try to hide behind friendly units
FLAG_NOCROSS_WATER = 0x0002, ///< don't obey orders that lead to crossing water
FLAG_AUTOTAX = 0x0004, ///< try to exhort taxes from the population
FLAG_HOLDING = 0x0008, ///< do not go to aid neighboring hexes in battle
FLAG_NOAID = 0x0010, ///< do not ask for aid in battle
FLAG_INVIS = 0x0020, ///< maintain invisibility?
FLAG_CONSUMING_UNIT = 0x0040, ///< consume food items in inventory
FLAG_CONSUMING_FACTION = 0x0080, ///< consume any food from friendly units
FLAG_NOSPOILS = 0x0100, ///< do not take spoils
FLAG_FLYSPOILS = 0x0200, ///< do not take spoils that would prevent flying
FLAG_WALKSPOILS = 0x0400, ///< do not take spoils that would prevent walking
FLAG_RIDESPOILS = 0x0800, ///< do not take spoils that would prevent riding
FLAG_SHARE = 0x1000 ///< share with friendly units
};
//----------------------------------------------------------------------------
/// Handle on a unit, including new units ('alias')
class UnitId : public AListElem
{
public:
UnitId(bool nobody);
UnitId(int unit_num, int alias = 0, int faction = 0, bool rename = false);
~UnitId();
AString Print(ARegion *region, int fac_num = 0) const;
///@return true if unitnum does not refer to "no one"
bool valid() const { return unitnum != -1; }
///@return Unit indicated by 'alias' and 'f'
Unit* find(AList &l, int f) const;
Unit* find(const std::vector<Unit*> &l, int f) const;
private: // data
int unitnum; ///< 0 -> new unit
int alias; ///< "new alias"
int faction; ///< "faction F new alias"
bool rename; ///< write out with new unit number
};
//----------------------------------------------------------------------------
/// One unit in the game
class Unit : public AListElem
{
public:
/// constructor
Unit(int seq = 0, Faction *f = NULL, int alias = 0);
/// destructor
~Unit();
static
Unit* findByFaction(AList &l, int alias, int faction);
static
Unit* findByFaction(const std::vector<Unit*> &l, int alias, int faction);
static
Unit* findByNum(AList &l, int num);
static
Unit* findByNum(const std::vector<Unit*> &l, int num);
/// set flags to make unit into monsters
void SetMonFlags();
/// Add 'num' of 'mon_id' and set flags for monsters
void MakeWMon(const char *mon_name, int mon_id, int num);
/// write to 'f'
void Writeout(Aoutfile *f);
/// read from 'f'
void Readin(Ainfile *f, AList *facs, ATL_VER v);
/// write appropriate details to 'f'
void WriteReport(JsonReport &of, int obs, int truesight, int detfac, int autosee, ARegion *loc);
///@return string with name, and faction if visible
AString GetName(int obs);
///@return extra string for mages
AString MageReport() const;
///@return string describing ready items
AString ReadyItem() const;
///@return string of all skills that can be studied
AString StudyableSkills();
///@return 1 if 'i' can be added to spoils
int CanGetSpoil(const Item *i);
///@return new string with combat details
AString* BattleReport(int obs);
AString TemplateReport();
/// clear all the values related to monthly orders
void ClearOrders();
/// clear cast order and teleport order
void ClearCastOrders();
/// clear orders and populate with defaults
void DefaultOrders();
/// change name to 's', delete s
void SetName(AString *s);
/// change describe to 's', delete s
void SetDescribe(AString *s);
/// post turn processing
void PostTurn(ARegion *reg);
///@return 1 if unit has leaders, else 0
int IsLeader();
///@return 1 if unit has men who are not leaders
int IsNormal();
///@return item id of first man type
int firstManType();
///@return number of monsters in unit
int GetMons();
///@return number of men in unit
int GetMen() const;
///@return number of items of type 't'
int GetMen(int t) const;
///@return number of soldiers in unit
int GetSoldiers();
/// set the number of men of 'type' to 'num' (assumes reduction)
void SetMen(int type, int num);
///@return 1 if this has some fight in it
int IsAlive();
///@return amount of silver
int GetMoney();
/// set silver to 'n'
void SetMoney(int n);
///@return maintenance cost for this
int MaintCost();
/// apply effects of hunger on this
void Short(int needed, int hunger);
///@return total number of skill levels known
int SkillLevels();
///@return the skill with type 'sk'
Skill* GetSkillObject(int sk);
///@return effective stealth for this
int GetStealth() const;
///@return effective tactics for this
int GetTactics() const;
///@return effective observation for this
int GetObservation() const;
///@return effective entertainment for this
int GetEntertainment() const;
///@return effective riding attack bonus for this
int GetAttackRiding();
///@return effective riding defense bonus for this
int GetDefenseRiding();
///@return bonus to 'sk'
int GetSkillBonus(int sk) const;
///@return bonus when producing 'item'
int GetProductionBonus(int item);
/// wrapper around various get skill level functions
int GetSkill(int sk) const;
/// set skill 'sk' to 'level'
void SetSkill(int sk, int level);
///@return skill level of 'sk'
int GetRealSkill(int sk) const;
/// remove 'sk' from known skills (also reverts type as appopriate)
void ForgetSkill(int sk);
///@return 1 if dependencies for 's' are satisfied, else 0
int CheckDepend(int sk, const SkillDepend &s);
///@return 1 if 'sk' can be studied
int CanStudy(int sk);
///@return the maximum level that can be studied in 'skill' for unit based on all men of type 'race'
int SkillMax(int sk);
/// increase 'sk' by 'days', @return 1 on success, else 0
int Study(int sk, int days);
/// increase 'sk' by the practice amount, @return 1 if done, else 0
int Practise(int sk);
/// adjust skills for maximums
void AdjustSkills();
///@return 1 if can see, 2 if can see faction (forwards to Faction::CanSee())
int CanSee(ARegion *r, Unit *u, int practise = 0);
/// forwards to Faction::CanCatch()
int CanCatch(ARegion *r, Unit *u);
///@return 1 if there are enough amulets of true sight to protect this from the invisibility of 'u'
int AmtsPreventCrime(Unit *u);
/// Get this unit's attitude toward the Unit parameter
int GetAttitude(ARegion *,Unit *);
///@return this highest hostility of all monsters in this
int Hostile();
///@return 1 if this forbids entry of 'u' to 'r'
int Forbids(ARegion *r, Unit *u);
///@return weight of all items
int Weight();
///@return carrying capacity for different movement modes
int FlyingCapacity();
int RidingCapacity();
int SwimmingCapacity();
int WalkingCapacity();
///@return true if can move in mode for given weight (defaults to weight of items)
int CanFly(int weight);
int CanRide(int weight);
int CanWalk(int weight);
int CanFly();
int CanSwim();
int CanReallySwim(int weight = 0);
///set start_move_points corresponding to move_type
AString calcMovePoints();
///@return 1 if there is really some movement (0 for exits)
int CanMoveTo(ARegion *r1, ARegion *r2);
///@return flags & mask
int GetFlag(int mask) const;
///@return true if unit is invisible
bool isInvisible() const;
/// update flags according to 'mask' (clear or set using 'val')
void SetFlag(int mask, int val);
/// copy 'flags', 'guard' and 'reveal' flags from 'u'
void CopyFlags(const Unit *u);
///@return type of item to be used in battle (not a weapon), -1 for none
int GetBattleItem(int index);
///@return type of armor in use (modulo assassination), -1 for none
int GetArmor(int index, int ass);
///@param[out] bonus attack bonus provided
///@return -1 if no mount, else item type
int GetMount(int index, int canFly, int canRide, int &bonus);
///@return skill level and bonuses for weapon at 'index'
int GetWeapon(int index, int riding, int ridingBonus,
int &attackBonus, int &defenseBonus, int &attacks);
/// wrap the base form, and check for riding limitations
int CanUseWeapon(const WeaponType *pWep, int riding);
///@return 0 for weapons that need no skill, -1 if skill is lacking, or the skill level appropriate
///@NOTE: also practises the appropriate skill
int CanUseWeapon(const WeaponType *pWep);
///@return number of "men" who can tax (includes monsters)
int Taxers();
/// move this from current object to 'newobj'
void MoveUnit(Object *newobj);
/// prepend unit name and forward to Faction::Event
void Event(const AString &);
void logEvent(IEvent *e);
/// prepend unit name and forward to Faction::Error
void Error(const AString &);
///@return number of items of type 'itemId' this unit can consume
/// stop after you reach 'hint' items, -1 -> no limit
int canConsume(int itemId, int hint = -1);
void consume(int itemId, int num);
public: // data
Faction *faction;
Faction *formfaction;
Object *object;
AString *name;
AString *describe;
int num;
int type;
int alias;
int gm_alias; // used for gm manual creation of new units
int guard; // Also, avoid- see enum above
int reveal;
int flags;
int taxing;
MoveType move_type = M_NONE; ///< move type available
int start_move_points = 0; ///< starting move points
int movepoints = 0; ///< points used
int canattack;
int nomove;
SkillList skills;
ItemList items;
int combat;
int readyItem;
int readyWeapon[MAX_READY];
int readyArmor[MAX_READY];
AList oldorders;
int needed; // For assessing maintenance
int hunger;
int stomach_space;
int losses;
int free;
int practised; ///< Has this unit practised a skill this turn
// Orders
int destroy;
int enter_ = 0; ///< default to not enter, or leave (-1)
Object *build;
int leftShip;
UnitId *promote;
AList findorders;
AList giveorders;
AList withdraworders;
AList buyorders;
AList sellorders;
AList forgetorders;
CastOrder *castorders;
TeleportOrder *teleportorders;
Order *stealorders;
Order *monthorders;
AttackOrder *attackorders;
EvictOrder *evictorders;
JoinOrder *joinorders = nullptr;
ARegion *advancefrom;
AList exchangeorders;
AList turnorders;
int inTurnBlock;
Order *presentMonthOrders;
int presentTaxing;
Unit *former;
protected:
/// limit the unit to one skill (for non MU)
void limitSkillNoMagic();
void limitSkillMagic(unsigned max_no_magic);
AString SpoilsReport();
void SkillStarvation();
///@return highest move possible
MoveType moveType();
///@return movement points corresponding to MoveType()
int CalcMovePoints(MoveType mt);
};
//----------------------------------------------------------------------------
class UnitPtr : public AListElem
{
public:
Unit *ptr;
};
UnitPtr* GetUnitList(AList *, Unit *);
#endif