Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
CampaignPlanStrategic.cpp
Go to the documentation of this file.
1 /* Project Starshatter 4.5
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: Stars.exe
6  FILE: CampaignPlanStrategic.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  CampaignPlanStrategic prioritizes targets and defensible
13  allied forces as the first step in force tasking.
14 */
15 
16 #include "MemDebug.h"
17 #include "CampaignPlanStrategic.h"
18 #include "Campaign.h"
19 #include "Combatant.h"
20 #include "CombatGroup.h"
21 #include "CombatUnit.h"
22 #include "CombatZone.h"
23 #include "Random.h"
24 
25 // +--------------------------------------------------------------------+
26 
27 void
29 {
30  if (campaign && campaign->IsActive()) {
31  if (Campaign::Stardate() - exec_time < 300)
32  return;
33 
35  while (++zone)
36  zone->Clear();
37 
39  while (++iter) {
40  Combatant* c = iter.value();
41  CombatGroup* force = c->GetForce();
42 
43  force->CalcValue();
44 
45  PlaceGroup(force);
46  ScoreCombatant(c);
47  ScoreNeeds(c);
48 
49  force->ClearUnlockedZones();
50  AssignZones(c);
51  ResolveZoneMovement(force);
52  }
53 
55  }
56 }
57 
58 // +--------------------------------------------------------------------+
59 
60 void
62 {
63  if (!g)
64  return;
65 
66  Text rgn = g->GetRegion();
67  CombatZone* zone = campaign->GetZone(rgn);
68 
69  // if we couldn't find anything suitable,
70  // just pick a zone at random:
71  if (!zone && g->IsMovable()) {
72  int nzones = campaign->GetZones().size();
73  int n = RandomIndex() % nzones;
74  zone = campaign->GetZones().at(n);
75 
76  Text assigned_rgn;
77  if (!campaign->GetZone(rgn)) {
78  assigned_rgn = *zone->GetRegions().at(0);
79  g->AssignRegion(assigned_rgn);
80  }
81  }
82 
83  if (zone && !zone->HasGroup(g))
84  zone->AddGroup(g);
85 
87  while (++iter)
88  PlaceGroup(iter.value());
89 }
90 
91 // +--------------------------------------------------------------------+
92 
93 void
95 {
96  // prep lists:
97  c->GetDefendList().clear();
98  c->GetTargetList().clear();
99 
100  ScoreDefensible(c);
101 
103  while (++iter) {
104  if (iter->GetIFF() > 0 && iter->GetIFF() != c->GetIFF())
105  ScoreTargets(c, iter.value());
106  }
107 
108  // sort lists:
109  c->GetDefendList().sort();
110  c->GetTargetList().sort();
111 }
112 
113 // +--------------------------------------------------------------------+
114 
115 void
117 {
118  if (c->GetForce())
119  ScoreDefend(c, c->GetForce());
120 }
121 
122 void
124 {
125  if (!g || g->IsReserve())
126  return;
127 
128  if (g->IsDefensible()) {
129  g->SetPlanValue(g->Value());
130  c->GetDefendList().append(g);
131 
132  CombatZone* zone = campaign->GetZone(g->GetRegion());
133  ZoneForce* force = 0;
134 
135  if (zone)
136  force = zone->FindForce(c->GetIFF());
137 
138  if (force)
139  force->GetDefendList().append(g);
140  }
141 
143  while (++iter) {
144  ScoreDefend(c, iter.value());
145  }
146 }
147 
148 // +--------------------------------------------------------------------+
149 
150 void
152 {
153  if (t->GetForce())
154  ScoreTarget(c, t->GetForce());
155 }
156 
157 void
159 {
160  if (!g || g->IntelLevel() <= Intel::SECRET)
161  return;
162 
163  if (g->IsTargetable()) {
164  g->SetPlanValue(g->Value() * c->GetTargetStratFactor(g->Type()));
165  c->GetTargetList().append(g);
166 
167  CombatZone* zone = campaign->GetZone(g->GetRegion());
168  ZoneForce* force = 0;
169 
170  if (zone)
171  force = zone->FindForce(c->GetIFF());
172 
173  if (force)
174  force->GetTargetList().append(g);
175  }
176 
178  while (++iter) {
179  ScoreTarget(c, iter.value());
180  }
181 }
182 
183 // +--------------------------------------------------------------------+
184 
185 void
187 {
189  while (++zone) {
190  ZoneForce* force = zone->FindForce(c->GetIFF());
191 
192  // clear needs:
199 
200  // what defensive assets are needed in this zone?
201  ListIter<CombatGroup> def = force->GetDefendList();
202  while (++def) {
203  int defender_type = *CombatGroup::PreferredDefender(def->Type());
204  force->AddNeed(defender_type, def->Value());
205  }
206 
207  // what offensive assets are needed in this zone?
208  ListIter<CombatGroup> tgt = force->GetTargetList();
209  while (++tgt) {
210  int attacker_type = *CombatGroup::PreferredAttacker(tgt->Type());
211  force->AddNeed(attacker_type, tgt->Value());
212  }
213  }
214 }
215 
216 // +--------------------------------------------------------------------+
217 
218 void
220 {
221  if (!g || g->IsReserve())
222  return;
223 
224  if (g->IsAssignable())
225  groups.append(g);
226 
228  while (++iter)
229  BuildGroupList(iter.value(), groups);
230 }
231 
232 // +--------------------------------------------------------------------+
233 
234 void
236 {
237  // find the list of assignable groups, in priority order:
238  List<CombatGroup> groups;
239  BuildGroupList(c->GetForce(), groups);
240  groups.sort();
241 
242  // for each group, assign a zone:
243  ListIter<CombatGroup> g_iter = groups;
244 
245  // first pass: fighter and attack squadrons assigned to star bases
246  while (++g_iter) {
247  CombatGroup* g = g_iter.value();
248  int gtype = g->Type();
249 
250  if (gtype == CombatGroup::ATTACK_SQUADRON ||
253  CombatGroup* parent = g->GetParent();
254 
255  if (parent && parent->Type() == CombatGroup::WING)
256  parent = parent->GetParent();
257 
258  if (!parent || parent->Type() == CombatGroup::CARRIER_GROUP)
259  continue;
260 
261  // these groups are attached to fixed resources,
262  // so they must be assigned to the parent's zone:
263  CombatZone* parent_zone = campaign->GetZone(parent->GetRegion());
264 
265  if (parent_zone) {
266  ZoneForce* parent_force = parent_zone->FindForce(g->GetIFF());
267 
268  if (parent_force) {
269  g->SetAssignedZone(parent_zone);
270  parent_force->AddNeed(g->Type(), -(g->Value()));
271  }
272  }
273  }
274  }
275 
276  // second pass: carrier groups
277  g_iter.reset();
278  while (++g_iter) {
279  CombatGroup* g = g_iter.value();
280  int gtype = g->Type();
281 
282  if (gtype == CombatGroup::CARRIER_GROUP) {
283  int current_zone_need = 0;
284  int highest_zone_need = 0;
285  CombatZone* highest_zone = 0;
286  ZoneForce* highest_force = 0;
287  CombatZone* current_zone = 0;
288  ZoneForce* current_force = 0;
289 
290  List<CombatZone> possible_zones;
291 
292  if (g->IsZoneLocked()) {
293  current_zone = g->GetAssignedZone();
294  current_force = current_zone->FindForce(g->GetIFF());
295  }
296 
297  else {
299  while (++z_iter) {
300  CombatZone* zone = z_iter.value();
301  ZoneForce* force = zone->FindForce(g->GetIFF());
302  int need = force->GetNeed(CombatGroup::CARRIER_GROUP) +
306 
307  if (g->IsSystemLocked() && zone->System() != g->GetAssignedSystem())
308  continue;
309 
310  possible_zones.append(zone);
311 
312  if (zone->HasRegion(g->GetRegion())) {
313  current_zone_need = need;
314  current_zone = zone;
315  current_force = force;
316  }
317 
318  if (need > highest_zone_need) {
319  highest_zone_need = need;
320  highest_zone = zone;
321  highest_force = force;
322  }
323  }
324  }
325 
326  CombatZone* assigned_zone = current_zone;
327  ZoneForce* assigned_force = current_force;
328 
329  if (highest_zone_need > current_zone_need) {
330  assigned_zone = highest_zone;
331  assigned_force = highest_force;
332  }
333 
334  // if we couldn't find anything suitable,
335  // just pick a zone at random:
336  if (!assigned_zone) {
337  if (possible_zones.isEmpty())
338  possible_zones.append(campaign->GetZones());
339 
340  int nzones = possible_zones.size();
341  int n = RandomIndex() % nzones;
342 
343  assigned_zone = possible_zones.at(n);
344  assigned_force = assigned_zone->FindForce(g->GetIFF());
345  }
346 
347  if (assigned_force && assigned_zone) {
348  Text assigned_rgn;
349  if (!campaign->GetZone(g->GetRegion())) {
350  assigned_rgn = *assigned_zone->GetRegions().at(0);
351  g->AssignRegion(assigned_rgn);
352  }
353 
354  g->SetAssignedZone(assigned_zone);
355  assigned_force->AddNeed(g->Type(), -(g->Value()));
356 
357  // also assign the carrier's wing and squadrons to the same zone:
358  ListIter<CombatGroup> squadron = g->GetComponents();
359  while (++squadron) {
360  squadron->SetAssignedZone(assigned_zone);
361  assigned_force->AddNeed(squadron->Type(), -(squadron->Value()));
362 
363  if (squadron->Type() == CombatGroup::WING) {
364  ListIter<CombatGroup> s = squadron->GetComponents();
365  while (++s) {
366  s->SetAssignedZone(assigned_zone);
367  assigned_force->AddNeed(s->Type(), -(s->Value()));
368  }
369  }
370  }
371  }
372  }
373  }
374 
375  // third pass: everything else
376  g_iter.reset();
377  while (++g_iter) {
378  CombatGroup* g = g_iter.value();
379  int gtype = g->Type();
380 
382  int current_zone_need = 0;
383  int highest_zone_need = 0;
384  CombatZone* highest_zone = 0;
385  ZoneForce* highest_force = 0;
386  CombatZone* current_zone = 0;
387  ZoneForce* current_force = 0;
388 
389  List<CombatZone> possible_zones;
390 
391  if (g->IsZoneLocked()) {
392  current_zone = g->GetAssignedZone();
393  current_force = current_zone->FindForce(g->GetIFF());
394  }
395 
396  else {
398  while (++z_iter) {
399  CombatZone* zone = z_iter.value();
400  ZoneForce* force = zone->FindForce(g->GetIFF());
401  int need = force->GetNeed(g->Type());
402 
403  if (g->IsSystemLocked() && zone->System() != g->GetAssignedSystem())
404  continue;
405 
406  possible_zones.append(zone);
407 
408  // battle groups can do double-duty:
409  if (gtype == CombatGroup::BATTLE_GROUP)
411 
412  if (zone->HasRegion(g->GetRegion())) {
413  current_zone_need = need;
414  current_zone = zone;
415  current_force = force;
416  }
417 
418  if (need > highest_zone_need) {
419  highest_zone_need = need;
420  highest_zone = zone;
421  highest_force = force;
422  }
423  }
424  }
425 
426  if (highest_zone_need > current_zone_need) {
427  g->SetAssignedZone(highest_zone);
428 
429  if (highest_force)
430  highest_force->AddNeed(g->Type(), -(g->Value()));
431  }
432  else {
433  if (!current_zone) {
434  if (possible_zones.isEmpty())
435  possible_zones.append(campaign->GetZones());
436 
437  int nzones = possible_zones.size();
438  int n = RandomIndex() % nzones;
439 
440  current_zone = possible_zones.at(n);
441  current_force = current_zone->FindForce(g->GetIFF());
442  }
443 
444  g->SetAssignedZone(current_zone);
445 
446  if (current_force)
447  current_force->AddNeed(g->Type(), -(g->Value()));
448 
449  Text assigned_rgn;
450  if (!campaign->GetZone(g->GetRegion())) {
451  assigned_rgn = *current_zone->GetRegions().at(0);
452  g->AssignRegion(assigned_rgn);
453  }
454  }
455  }
456  }
457 }
458 
459 // +--------------------------------------------------------------------+
460 
461 void
463 {
464  CombatZone* zone = g->GetAssignedZone();
465  bool move = false;
466 
467  if (zone && !zone->HasRegion(g->GetRegion())) {
468  move = true;
469  CombatZone* old_zone = g->GetCurrentZone();
470  if (old_zone)
471  old_zone->RemoveGroup(g);
472  zone->AddGroup(g);
473  }
474 
476  while (++comp)
477  ResolveZoneMovement(comp.value());
478 
479  // assign region last, to allow components to
480  // resolve their zones:
481  if (zone && move)
482  g->AssignRegion(*zone->GetRegions().at(0));
483 }