File: RAI.h

package info (click to toggle)
spring 103.0%2Bdfsg2-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 43,720 kB
  • ctags: 63,685
  • sloc: cpp: 368,283; ansic: 33,988; python: 12,417; java: 12,203; awk: 5,879; sh: 1,846; xml: 655; perl: 405; php: 211; objc: 194; makefile: 77; sed: 2
file content (195 lines) | stat: -rw-r--r-- 8,866 bytes parent folder | download | duplicates (4)
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
// _____________________________________________________
//
// RAI - Skirmish AI for Spring
// Author: Reth / Michael Vadovszki
// _____________________________________________________

#ifndef RAI_IGLOBALAI_H
#define RAI_IGLOBALAI_H

#if _MSC_VER > 1000
#pragma once
#endif

struct UnitInfo;
struct EnemyInfo;
class cRAI;

#include "LegacyCpp/IGlobalAI.h"
using std::map;
#include "BasicArray.h"
#include "UnitDefHandler.h"
#include "BuilderPlacement.h"
#include "Builder.h"
#include "UnitManager.h"
#include "SWeaponManager.h"
#include "PowerManager.h"
#include "CombatManager.h"
using std::set;

const char AI_NAME[]="RAI v0.601";
const bool RAIDEBUGGING = false;

// These are for anything that can occur in Update() but not on a regular basis
struct UpdateEvent
{
	int type;	// (1=unit-time-out,2=unit-monitoring,3=initialize), also used as a ranking of importance
	int frame;	// when the event will trigger
	int index;
	int unitID;
	UnitInfo* unitI;
	float3* lastPosition; // only used by unit-monitoring
};

struct UnitInfo
{
	UnitInfo(sRAIUnitDef* rUnitDef);

	const UnitDef* ud;		// Always valid
	sRAIUnitDef* udr;		// Always valid
	sRAIUnitDefBL* udrBL;	// Valid if AIDisabled=false
	TerrainMapArea* area;	// Not always valid, but definitely = 0 if a unit flies
	sBuildQuarry* BuildQ;	// Valid if building something, otherwise = 0
	UnitInfoPower* CloakUI; // I can not rely on cb->IsUnitCloaked(unit), since I need to keep track of power variables.
	UnitInfoPower* OnOffUI; // I can not rely on cb->IsUnitActivated(unit), same reason
	sSWeaponUnitInfo* SWeaponUI; // Valid if the unit has a stock weapon, otherwise = 0
	sRAIGroup* group;
	EnemyInfo* E;	// valid if 'enemyID' & 'Group' are set, otherwise this must be updated before used
	sWeaponEfficiency* enemyEff;
	UpdateEvent* UE;
	bool AIDisabled;
	bool humanCommand;	// Set true if a unit receives an order through HandleEvent(), set false on UnitIdle()
	bool unitBeingBuilt;// Work Around: for cb->UnitBeingBuilt(), which will not work if UnitDestroyed() fails to trigger immediately after a unit's death   Spring-Version(v0.74b3)
	bool inCombat;
	int lastUnitIdleFrame;		// Guard: Prevent UnitIdle from executing too many times in rapid succession
	int lastUnitDamagedFrame;	// Guard: Prevent UnitDamaged from executing too many times in rapid succession

	// Buildings Only
	ResourceSiteExt* RS;			// Extractor/Geo, otherwise = 0
	map<int,UnitInfo*> UGuards;		// Hubs/Nanos guarding this unit
	map<int,UnitInfo*> UGuarding;	// Hubs/Nanos only, Units being guarded
//	map<int,UnitInfo*> UAssist;		// Hubs/Nanos only, Units it will assist with building
	map<int,UnitInfo*> URepair;		// Hubs/Nanos only, Units that are in need of repairs
	map<int,UnitInfo*> UDefences;	// Defences build near this unit
	map<int,UnitInfo*> UDefending;	// Defences Only, buildings near this unit
//	map<int,ResourceSiteExt*> Resources;	// Hubs only, the only resources this unit can build at

	// old
//	int commandTimeOut;			// Work Around: for the currently broken command.timeout   Spring-Version(v0.72b1)
	int enemyID;
};

struct EnemyInfo
{
	EnemyInfo();

	bool inLOS;
	bool inRadar;
	int baseThreatFrame;// last frame it attacked one of our immobile units
	int baseThreatID;	// what unit of ours did it last attack
	const UnitDef* ud;	// valid if the enemy was in LOS at least once, otherwise = 0
	sRAIUnitDef* udr;	// same as above
	ResourceSiteExt* RS;	// Enemy Extractor/Geo, otherwise = 0
	set<sRAIGroup*> attackGroups;

	float3 position;	// last known position, used if not in LOS or Radar
	bool posLocked;		// This unit does not move and its 'position' was saved while in LOS
};

using namespace std;

#include "GTerrainMap.h"
#include "GResourceMap.h"

// how often lists are updated by frame interval.  NOTE: this is different from in-game graphics frames and will always be trigger 30x per second (assuming the game speed is 1.00)
#define FUPDATE_MINIMAL 90		// 3 seconds, the minimal time for an update.  NOTE: excluding FUPDATE_UNITS, this value needs to be 'a factor' of the other FUPDATE values
#define FUPDATE_UNITS 900		// 60 seconds, unit is checked for idleness - should never happen, but it does.
#define FUPDATE_POWER 450		// 15 seconds, all units are checked for on/off or cloak/uncloak tasks
#define FUPDATE_BUILDLIST 1800	// 600 seconds, redetermines the available build options - half unnecessary since this is also called by events, hence the longer delay
#define EVENT_LIST_SIZE 10000
class cRAI : public IGlobalAI
{
public:
	cRAI();
	virtual ~cRAI();
	void InitAI(IGlobalAICallback* callback, int team);
	void UnitCreated(int unit, int builder);		// called when a new unit is created on an ai team
	void UnitFinished(int unit);					// called when a unit has finished being build
	void UnitDestroyed(int unit,int attacker);		// called when a unit is destroyed
	void EnemyEnterLOS(int enemy);					// called when an enemy unit enters the "line of sight" of you or your ally
	void EnemyLeaveLOS(int enemy);					// called when an enemy unit exits the "line of sight" of you and your ally
	void EnemyEnterRadar(int enemy);				// called when an enemy unit enters the radar of you or your ally
	void EnemyLeaveRadar(int enemy);				// called when an enemy unit exits the radar of you and your ally
	void EnemyDestroyed(int enemy,int attacker);	// called if an enemy inside los or radar dies
	void EnemyRemove(int enemy, EnemyInfo* E);
	void EnemyDamaged(int damaged,int attacker,float damage,float3 dir); // called when an enemy inside los or radar is damaged
	void UnitIdle(int unit);						// called when a unit go idle and is not assigned to any group
	void RecvChatMessage(const char* msg,int player) {};	// called when someone writes a chat msg
	void RecvLuaMessage(const char* inData, const char** outData) {}
	void UnitDamaged(int damaged,int attacker,float damage,float3 dir); // called when one of your units are damaged
	void UnitMoveFailed(int unit);
	int HandleEvent(int msg,const void* data);
	void Update();			// called every frame
	void UpdateEventAdd(const int &eventType, const int &eventFrame, int uID=0, UnitInfo* uI=0);
	void CorrectPosition(float3& position);
	TerrainMapArea* GetCurrentMapArea(sRAIUnitDef* udr, float3& position); // returns MapB index if >=0, -1 = any mb, -2 = error(unit can not exist at this position)
	float3 GetRandomPosition(TerrainMapArea* area);
	bool IsHumanControled(const int& unit,UnitInfo* U); // this function will crash if the 'unit' id is invalid

	// used to check if the UnitDestroyed() event failed to trigger properly for units,  Work Around:  Spring-Version(v0.74b3-0.75b2)
	bool ValidateUnit(const int& unitID); // returns true if the unitID exists in-game, unitID is assumed to have been valid up to this point
	bool ValidateUnitList(map<int,UnitInfo*>* UL); // returns true if at least one unit on the list is valid
	void ValidateAllUnits();

	static bool LocateFile(IAICallback* cb, const string& relFileName, string& absFileName, bool forWriting);
	/// Converts a string to one that can be used in a file name (eg. "Abc.123 $%^*" -> "Abc.123_____")
	static std::string MakeFileSystemCompatible(const std::string& str);

	map<int,UnitInfo> Units;	// Complete record of all owned units, key value = unit id
	map<int,UnitInfo*> UImmobile;
	map<int,UnitInfo*> UMobile;
	map<int,EnemyInfo> Enemies;
	map<int,EnemyInfo*> EThreat;	// These enemies have attacked our immobile units

	cLogFile* l;
	cBuilder* B;
	cCombatManager* CM;
	cRAIUnitDefHandler* UDH;
	cUnitManager* UM;
	GlobalResourceMap* RM; // = static RM
	GlobalTerrainMap* TM; // = static TM

	void DebugDrawLine(float3 StartPos, float distance, int direction, float xposoffset=0, float zposoffset=0, float yposoffset=50, int lifetime=9000, int arrow=0, float width=5.0, int group=1); // direction 0-3, counter-clock wise, 0=right
	void DebugDrawShape(float3 CenterPos, float linelength, float width=5.0, int arrow=0, float yposoffset=50, int lifetime=9000, int sides=4, int group=1); // incomplete, sides is always 4

	typedef pair<int,UnitInfo*> iupPair;	// used to access UImmobile,UMobile, also used by different classes
	typedef pair<int,EnemyInfo*> iepPair;

private:
	std::string GetLogFileSubPath(int teamId) const;
	void RemoveLogFile(string relFileName) const;
	void UpdateEventRemove(UpdateEvent* e);
	void UpdateEventReorderFirst();
	UpdateEvent* eventList[EVENT_LIST_SIZE];
	int eventSize;

	int DebugEnemyEnterLOS;
	int DebugEnemyLeaveLOS;
	int DebugEnemyEnterRadar;
	int DebugEnemyLeaveRadar;
	int DebugEnemyDestroyedLOS;
	int DebugEnemyDestroyedRadar;
	int DebugEnemyEnterLOSError;
	int DebugEnemyLeaveLOSError;
	int DebugEnemyEnterRadarError;
	int DebugEnemyLeaveRadarError;
	int frame;

	typedef pair<int,UnitInfo> iuPair;		// used to access Units
	typedef pair<int,EnemyInfo> iePair;
	void ClearLogFiles();
	IAICallback* cb;
	cSWeaponManager* SWM;
};

#endif