Galactic Bloodshed
shootblast.cc
Go to the documentation of this file.
1 // Copyright 2014 The Galactic Bloodshed Authors. All rights reserved.
2 // Use of this source code is governed by a license that can be
3 // found in the COPYING file.
4 
5 #include "gb/shootblast.h"
6 
7 #include <cmath>
8 #include <cstdio>
9 #include <cstdlib>
10 #include <cstring>
11 
12 #include "gb/GB_server.h"
13 #include "gb/buffers.h"
14 #include "gb/build.h"
15 #include "gb/defense.h"
16 #include "gb/files_shl.h"
17 #include "gb/fire.h"
18 #include "gb/getplace.h"
19 #include "gb/misc.h"
20 #include "gb/races.h"
21 #include "gb/ships.h"
22 #include "gb/shlmisc.h"
23 #include "gb/tweakables.h"
24 #include "gb/utils/rand.h"
25 #include "gb/vars.h"
26 
27 static int hit_probability;
28 static double penetration_factor;
29 
30 static int do_radiation(Ship *, double, int, int, const char *, char *);
31 static int do_damage(int, Ship *, double, int, int, int, int, double,
32  const char *, char *);
33 
34 static void ship_disposition(Ship *, int *, int *, int *);
35 static int CEW_hit(double, int);
36 static int Num_hits(double, int, int, double, int, int, int, int, int, int, int,
37  int);
38 static int cew_hit_odds(double, int);
39 static void do_critical_hits(int, Ship *, int *, int *, int, char *);
40 static double p_factor(double, double);
41 static void mutate_sector(Sector &);
42 
43 int shoot_ship_to_ship(Ship *from, Ship *to, int strength, int cew, int ignore,
44  char *long_msg, char *short_msg) {
45  int hits;
46  int damage;
47  double dist;
48  double xfrom;
49  double yfrom;
50  double xto;
51  double yto;
52  int focus;
53  int fevade;
54  int fspeed;
55  int fbody;
56  int tevade;
57  int tspeed;
58  int tbody;
59  int caliber;
60  char weapon[32];
61  char damage_msg[1024];
62 
63  hits = 0;
64  if (strength <= 0) return -1;
65 
66  if (!(from->alive || ignore) || !to->alive) return -1;
67  if (from->whatorbits == ScopeLevel::LEVEL_SHIP ||
68  from->whatorbits == ScopeLevel::LEVEL_UNIV)
69  return -1;
70  if (to->whatorbits == ScopeLevel::LEVEL_SHIP ||
71  to->whatorbits == ScopeLevel::LEVEL_UNIV)
72  return -1;
73  if (from->storbits != to->storbits) return -1;
74  if (has_switch(*from) && !from->on) return -1;
75 
76  xfrom = from->xpos;
77  yfrom = from->ypos;
78 
79  xto = to->xpos;
80  yto = to->ypos;
81  /* compute caliber */
82  caliber = current_caliber(from);
83 
84  if (from->type ==
85  ShipType::STYPE_MISSILE) /* missiles hit at point blank range */
86  dist = 0.0;
87  else {
88  dist = sqrt((double)Distsq(xfrom, yfrom, xto, yto));
89  if (from->type == ShipType::STYPE_MINE) { /* compute the effective range */
90  dist *= dist / 200.0; /* mines are very effective inside 200 */
91  }
92  }
93  if ((double)dist > gun_range((Race *)nullptr, from, 0)) return -1;
94  /* attack parameters */
95  ship_disposition(from, &fevade, &fspeed, &fbody);
96  ship_disposition(to, &tevade, &tspeed, &tbody);
97  auto defense = getdefense(*to);
98 
99  if (laser_on(*from) && from->focus)
100  focus = 1;
101  else
102  focus = 0;
103 
104  if (cew)
105  hits = strength * CEW_hit((double)dist, (int)from->cew_range);
106  else
107  hits =
108  Num_hits((double)dist, focus, strength, from->tech, (int)from->damage,
109  fevade, tevade, fspeed, tspeed, tbody, caliber, defense);
110  /* CEW, destruct, lasers */
111  damage = 0;
112  if (from->mode) {
113  damage =
114  do_radiation(to, from->tech, strength, hits, "radiation", damage_msg);
115  sprintf(short_msg, "%s: %s %s %s\n", Dispshiploc(to),
116  ship_to_string(*from).c_str(), to->alive ? "attacked" : "DESTROYED",
117  ship_to_string(*to).c_str());
118  strcpy(long_msg, short_msg);
119  strcat(long_msg, damage_msg);
120  } else {
121  if (cew)
122  sprintf(weapon, "strength CEW");
123  else if (laser_on(*from)) {
124  if (from->focus)
125  sprintf(weapon, "strength focused laser");
126  else
127  sprintf(weapon, "strength laser");
128  } else
129  switch (caliber) {
130  case GTYPE_LIGHT:
131  sprintf(weapon, "light guns");
132  break;
133  case GTYPE_MEDIUM:
134  sprintf(weapon, "medium guns");
135  break;
136  case GTYPE_HEAVY:
137  sprintf(weapon, "heavy guns");
138  break;
139  case GTYPE_NONE:
140  sprintf(weapon, "pea-shooter");
141  return -1;
142  }
143 
144  damage = do_damage((int)from->owner, to, (double)from->tech, strength, hits,
145  defense, caliber, (double)dist, weapon, damage_msg);
146  sprintf(short_msg, "%s: %s %s %s\n", Dispshiploc(to),
147  ship_to_string(*from).c_str(), to->alive ? "attacked" : "DESTROYED",
148  ship_to_string(*to).c_str());
149  strcpy(long_msg, short_msg);
150  strcat(long_msg, damage_msg);
151  }
152  return damage;
153 }
154 
155 #ifdef DEFENSE
156 int shoot_planet_to_ship(racetype *Race, Ship *ship, int strength,
157  char *long_msg, char *short_msg) {
158  int hits;
159  int evade;
160  int speed;
161  int body;
162  int damage;
163  char damage_msg[1024];
164 
165  hits = 0;
166  if (strength <= 0) return -1;
167  if (!ship->alive) return -1;
168 
169  if (ship->whatorbits != ScopeLevel::LEVEL_PLAN) return -1;
170 
171  ship_disposition(ship, &evade, &speed, &body);
172 
173  hits = Num_hits(0.0, 0, strength, Race->tech, 0, evade, 0, speed, 0, body,
174  GTYPE_MEDIUM, 1);
175 
176  damage = do_damage(Race->Playernum, ship, Race->tech, strength, hits, 0,
177  GTYPE_MEDIUM, 0.0, "medium guns", damage_msg);
178  sprintf(short_msg, "%s [%d] %s %s\n", Dispshiploc(ship), Race->Playernum,
179  ship->alive ? "attacked" : "DESTROYED",
180  ship_to_string(*ship).c_str());
181  strcpy(long_msg, short_msg);
182  strcat(long_msg, damage_msg);
183 
184  return damage;
185 }
186 #endif
187 
188 int shoot_ship_to_planet(Ship *ship, Planet *pl, int strength, int x, int y,
189  SectorMap &smap, int ignore, int caliber,
190  char *long_msg, char *short_msg) {
191  int x2;
192  int y2;
193  int numdest;
194  player_t oldowner;
195  population_t kills;
196  int i;
197  int num_sectors;
198  int sum_mob[MAXPLAYERS];
199  double d;
200  double r;
201  double fac;
202 
203  numdest = 0;
204  if (strength <= 0) return -1;
205  if (!(ship->alive || ignore)) return -1;
206  if (has_switch(*ship) && !ship->on) return -1;
207  if (ship->whatorbits != ScopeLevel::LEVEL_PLAN) return -1;
208 
209  if (x < 0 || x > pl->Maxx - 1 || y < 0 || y > pl->Maxy - 1) return -1;
210 
211  r = .4 * strength;
212  if (!caliber) { /* figure out the appropriate gun caliber if not given*/
213  if (ship->fire_laser)
214  caliber = GTYPE_LIGHT;
215  else
216  switch (ship->guns) {
217  case PRIMARY:
218  caliber = ship->primtype;
219  break;
220  case SECONDARY:
221  caliber = ship->sectype;
222  break;
223  default:
224  caliber = GTYPE_LIGHT;
225  }
226  }
227 
228  auto &target = smap.get(x, y);
229  oldowner = target.owner;
230 
231  for (i = 1; i <= Num_races; i++) sum_mob[i - 1] = 0;
232 
233  for (y2 = 0; y2 < pl->Maxy; y2++) {
234  for (x2 = 0; x2 < pl->Maxx; x2++) {
235  int dx;
236  int dy;
237  dx = std::min(abs(x2 - x), abs(x + (pl->Maxx - 1) - x2));
238  dy = abs(y2 - y);
239  d = sqrt((double)(dx * dx + dy * dy));
240  auto &s = smap.get(x2, y2);
241 
242  if (d <= r) {
243  fac = SECTOR_DAMAGE * (double)strength * (double)caliber / (d + 1.);
244 
245  if (s.owner) {
246  if (s.popn) {
247  kills = int_rand(0, ((int)(fac / 10.0) * s.popn)) /
248  (1 + (s.condition == SectorType::SEC_PLATED));
249  if (kills > s.popn)
250  s.popn = 0;
251  else
252  s.popn -= kills;
253  }
254  if (s.troops && (fac > 5.0 * (double)Defensedata[s.condition])) {
255  kills = int_rand(0, ((int)(fac / 20.0) * s.troops)) /
256  (1 + (s.condition == SectorType::SEC_PLATED));
257  if (kills > s.troops)
258  s.troops = 0;
259  else
260  s.troops -= kills;
261  }
262 
263  if (!(s.popn + s.troops)) s.owner = 0;
264  }
265 
266  if (fac >= 5.0 && !int_rand(0, 10)) mutate_sector(s);
267 
268  if (round_rand(fac) > Defensedata[s.condition] * int_rand(0, 10)) {
269  if (s.owner) Nuked[s.owner - 1] = 1;
270  s.popn = 0;
271  s.troops = int_rand(0, (int)s.troops);
272  if (!s.troops) /* troops may survive this */
273  s.owner = 0;
274  s.eff = 0;
275  s.resource = s.resource / ((int)fac + 1);
276  s.mobilization = 0;
277  s.fert = 0; /*all is lost !*/
278  s.crystals = int_rand(0, (int)s.crystals);
279  s.condition = SectorType::SEC_WASTED;
280  numdest++;
281  } else {
282  s.fert = std::max(0, (int)s.fert - (int)fac);
283  s.eff = std::max(0, (int)s.eff - (int)fac);
284  s.mobilization = std::max(0, (int)s.mobilization - (int)fac);
285  s.resource = std::max(0, (int)s.resource - (int)fac);
286  }
287  }
288  if (s.owner) sum_mob[s.owner - 1] += s.mobilization;
289  }
290  }
291  num_sectors = pl->Maxx * pl->Maxy;
292  for (i = 1; i <= Num_races; i++) {
293  pl->info[i - 1].mob_points = sum_mob[i - 1];
294  pl->info[i - 1].comread = sum_mob[i - 1] / num_sectors;
295  pl->info[i - 1].guns = planet_guns(sum_mob[i - 1]);
296  }
297 
298  /* planet toxicity goes up a bit */
299  pl->conditions[TOXIC] += (100 - pl->conditions[TOXIC]) *
300  ((double)numdest / (double)(pl->Maxx * pl->Maxy));
301 
302  sprintf(short_msg, "%s bombards %s [%d]\n", ship_to_string(*ship).c_str(),
303  Dispshiploc(ship), oldowner);
304  strcpy(long_msg, short_msg);
305  sprintf(buf, "\t%d sectors destroyed\n", numdest);
306  strcat(long_msg, buf);
307  return numdest;
308 }
309 
310 static int do_radiation(Ship *ship, double tech, int strength, int hits,
311  const char *weapon, char *msg) {
312  double fac;
313  double r;
314  int i;
315  int arm;
316  int body;
317  int penetrate;
318  int casualties;
319  int casualties1;
320  int dosage;
321 
322  fac =
323  (2. / 3.14159265) * atan((double)(5 * (tech + 1.0) / (ship->tech + 1.0)));
324 
325  arm = std::max(0UL, armor(*ship) - hits / 5);
326  body = shipbody(*ship);
327 
328  penetrate = 0;
329  r = 1.0;
330  for (i = 1; i <= arm; i++) r *= fac;
331 
332  for (i = 1; i <= hits; i++) /* check to see how many hits penetrate */
333  if (double_rand() <= r) penetrate += 1;
334 
335  dosage = round_rand(40. * (double)penetrate / (double)body);
336  dosage = std::min(100, dosage);
337 
338  if (dosage > ship->rad) ship->rad = std::max(ship->rad, dosage);
339  if (success(ship->rad)) ship->active = 0;
340 
341  casualties = 0;
342  casualties1 = 0;
343  sprintf(buf, "\tAttack: %d %s\n\t Hits: %d\n", strength, weapon, hits);
344  strcat(msg, buf);
345  sprintf(buf, "\t Rad: %d%% for a total of %d%%\n", dosage, ship->rad);
346  strcat(msg, buf);
347  if (casualties || casualties1) {
348  sprintf(buf, "\tKilled: %d civ + %d mil\n", casualties, casualties1);
349  strcat(msg, buf);
350  }
351  return dosage;
352 }
353 
354 static int do_damage(int who, Ship *ship, double tech, int strength, int hits,
355  int defense, int caliber, double range, const char *weapon,
356  char *msg) {
357  double body;
358  int i;
359  int arm;
360  int damage;
361  int penetrate;
362  int crithits;
363  int critdam;
364  int casualties;
365  int casualties1;
366  int primgundamage;
367  int secgundamage;
368  double fac;
369  double r;
370  char critmsg[1024];
371 
372  sprintf(buf, "\tAttack: %d %s at a range of %.0f\n", strength, weapon, range);
373  strcpy(msg, buf);
374  sprintf(buf, "\t Hits: %d %d%% probability\n", hits, hit_probability);
375  strcat(msg, buf);
376  /* ship may lose some armor */
377  if (ship->armor)
378  if (success(hits * caliber)) {
379  ship->armor--;
380  sprintf(buf, "\t\tArmor reduced to %d\n", ship->armor);
381  strcat(msg, buf);
382  }
383 
384  fac = p_factor(tech, ship->tech);
385  penetration_factor = fac;
386  arm = std::max(0UL, armor(*ship) + defense - hits / 5);
387  body = sqrt((double)(0.1 * shipbody(*ship)));
388 
389  critdam = 0;
390  crithits = 0;
391  penetrate = 0;
392  r = 1.0;
393  for (i = 1; i <= arm; i++) r *= fac;
394 
395  for (i = 1; i <= hits; i++) /* check to see how many hits penetrate */
396  if (double_rand() <= r) penetrate += 1;
397 
398  damage = round_rand(SHIP_DAMAGE * (double)caliber * (double)penetrate /
399  (double)body);
400 
401  do_critical_hits(penetrate, ship, &crithits, &critdam, caliber, critmsg);
402 
403  if (crithits) damage += critdam;
404 
405  damage = std::min(100, damage);
406  ship->damage = std::min(100, (int)(ship->damage) + damage);
407  do_collateral(ship, damage, &casualties, &casualties1, &primgundamage,
408  &secgundamage);
409  /* set laser strength for ships to maximum safe limit */
410  if (ship->fire_laser) {
411  int safe;
412  safe = (int)((1.0 - .01 * ship->damage) * ship->tech / 4.0);
413  if (ship->fire_laser > safe) ship->fire_laser = safe;
414  }
415 
416  if (penetrate) {
417  sprintf(buf, "\t\t%d penetrations eff armor=%d defense=%d prob=%.3f\n",
418  penetrate, arm, defense, r);
419  strcat(msg, buf);
420  }
421  if (crithits) {
422  sprintf(buf, "\t\t%d CRITICAL hits do %d%% damage\n", crithits, critdam);
423  strcat(msg, buf);
424  strcat(msg, critmsg);
425  }
426  if (damage) {
427  sprintf(buf, "\tDamage: %d%% damage for a total of %d%%\n", damage,
428  ship->damage);
429  strcat(msg, buf);
430  }
431  if (primgundamage || secgundamage) {
432  sprintf(buf, "\t Other: %d primary/%d secondary guns destroyed\n",
433  primgundamage, secgundamage);
434  strcat(msg, buf);
435  }
436  if (casualties || casualties1) {
437  sprintf(buf, "\tKilled: %d civ + %d mil casualties\n", casualties,
438  casualties1);
439  strcat(msg, buf);
440  }
441 
442  if (ship->damage >= 100) kill_ship(who, ship);
443  ship->build_cost = (int)cost(*ship);
444  return damage;
445 }
446 
447 static void ship_disposition(Ship *ship, int *evade, int *speed, int *body) {
448  *evade = 0;
449  *speed = 0;
450  *body = size(*ship);
451  if (ship->active && !ship->docked && (ship->whatdest || ship->navigate.on)) {
452  *evade = ship->protect.evade;
453  *speed = ship->speed;
454  }
455 }
456 
457 static int CEW_hit(double dist, int cew_range) {
458  int prob;
459  int hits;
460 
461  hits = 0;
462  prob = cew_hit_odds(dist, cew_range);
463 
464  if (success(prob)) hits = 1;
465 
466  return hits;
467 }
468 
469 static int Num_hits(double dist, int focus, int guns, double tech, int fdam,
470  int fev, int tev, int fspeed, int tspeed, int body,
471  int caliber, int defense) {
472  int factor;
473  int i;
474  int prob;
475  int hits;
476 
477  prob = hit_odds(dist, &factor, tech, fdam, fev, tev, fspeed, tspeed, body,
478  caliber, defense);
479 
480  hits = 0;
481  if (focus) {
482  if (success(prob * prob / 100)) hits = guns;
483  hit_probability = prob * prob / 100;
484  } else {
485  for (i = 1; i <= guns; i++)
486  if (success(prob)) hits++;
487  hit_probability = prob; /* global variable */
488  }
489 
490  return hits;
491 }
492 
493 int hit_odds(double range, int *factor, double tech, int fdam, int fev, int tev,
494  int fspeed, int tspeed, int body, int caliber, int defense) {
495  int odds;
496  double a;
497  double b;
498  double c;
499 
500  if (caliber == GTYPE_NONE) {
501  *factor = 0;
502  return 0;
503  }
504 
505  a = log10(1.0 + (double)tech) * 80.0 * pow((double)body, 0.33333);
506  b = 72.0 / ((2.0 + (double)tev) * (2.0 + (double)fev) *
507  (18.0 + (double)tspeed + (double)fspeed));
508  c = a * b / (double)caliber;
509  *factor = (int)(c * (1.0 - (double)fdam / 100.)); /* 50% hit range */
510  odds = 0;
511  if (*factor > 0)
512  odds =
513  (int)((double)((*factor) * 100) / ((double)((*factor) + (int)range)));
514  odds = (int)((double)odds * (1.0 - 0.1 * (double)defense));
515  return odds;
516 }
517 
518 static int cew_hit_odds(double range, int cew_range) {
519  int odds;
520  double factor;
521 
522  factor = (range + 1.0) / ((double)cew_range + 1.0); /* maximum chance */
523  odds = (int)(100.0 * exp((double)(-50.0 * (factor - 1.0) * (factor - 1.0))));
524  return odds;
525 }
526 
527 /*
528  * gun range of given ship, given race and ship
529  */
530 double gun_range(Race *r, Ship *s, int mode) {
531  if (mode) return (logscale((int)(r->tech + 1.0)) * SYSTEMSIZE);
532 
533  return (logscale((int)(s->tech + 1.0)) * SYSTEMSIZE);
534 }
535 
536 /*
537  * range of telescopes, ground or space, given race and ship
538  */
539 double tele_range(int type, double tech) {
540  if (type == ShipType::OTYPE_GTELE)
541  return log1p((double)tech) * 400 + SYSTEMSIZE / 8;
542 
543  return log1p((double)tech) * 1500 + SYSTEMSIZE / 3;
544 }
545 
546 int current_caliber(Ship *ship) {
547  if (ship->laser && ship->fire_laser) return GTYPE_LIGHT;
548  if (ship->type == ShipType::STYPE_MINE) return GTYPE_LIGHT;
549  if (ship->type == ShipType::STYPE_MISSILE) return GTYPE_HEAVY;
550  if (ship->guns == PRIMARY) return ship->primtype;
551  if (ship->guns == SECONDARY) return ship->sectype;
552 
553  return GTYPE_NONE;
554 }
555 
556 static void do_critical_hits(int penetrate, Ship *ship, int *crithits,
557  int *critdam, int caliber, char *critmsg) {
558  int eff_size;
559  int i;
560  int dam;
561  *critdam = 0;
562  *crithits = 0;
563  eff_size = std::max(1, shipbody(*ship) / caliber);
564  for (i = 1; i <= penetrate; i++)
565  if (!int_rand(0, eff_size - 1)) {
566  *crithits += 1;
567  dam = int_rand(0, 100);
568  *critdam += dam;
569  }
570  *critdam = std::min(100, *critdam);
571  /* check for special systems damage */
572  strcpy(critmsg, "\t\tSpecial systems damage: ");
573  if (ship->cew && success(*critdam)) {
574  strcat(critmsg, "CEW ");
575  ship->cew = 0;
576  }
577  if (ship->laser && success(*critdam)) {
578  strcat(critmsg, "Laser ");
579  ship->laser = 0;
580  }
581  if (ship->cloak && success(*critdam)) {
582  strcat(critmsg, "Cloak ");
583  ship->cloak = 0;
584  }
585  if (ship->hyper_drive.has && success(*critdam)) {
586  strcat(critmsg, "Hyper-drive ");
587  ship->hyper_drive.has = 0;
588  }
589  if (ship->max_speed && success(*critdam)) {
590  ship->speed = 0;
591  ship->max_speed = int_rand(0, (int)ship->max_speed - 1);
592  sprintf(buf, "Speed=%d ", ship->max_speed);
593  strcat(critmsg, buf);
594  }
595  if (ship->armor && success(*critdam)) {
596  ship->armor = int_rand(0, (int)ship->armor - 1);
597  sprintf(buf, "Armor=%d ", ship->armor);
598  strcat(critmsg, buf);
599  }
600  strcat(critmsg, "\n");
601 }
602 
603 void do_collateral(Ship *ship, int damage, int *casualties, int *casualties1,
604  int *primgundamage, int *secgundamage) {
605  int i;
606  /* compute crew/troop casualties */
607  *casualties = 0;
608  *casualties1 = 0;
609  *primgundamage = 0;
610  *secgundamage = 0;
611 
612  for (i = 1; i <= ship->popn; i++) *casualties += success(damage);
613  ship->popn -= *casualties;
614  for (i = 1; i <= ship->troops; i++) *casualties1 += success(damage);
615  ship->troops -= *casualties1;
616  for (i = 1; i <= ship->primary; i++) *primgundamage += success(damage);
617  ship->primary -= *primgundamage;
618  for (i = 1; i <= ship->secondary; i++) *secgundamage += success(damage);
619  ship->secondary -= *secgundamage;
620  if (!ship->primary) ship->primtype = GTYPE_NONE;
621  if (!ship->secondary) ship->sectype = GTYPE_NONE;
622 }
623 
624 static double p_factor(double attacker, double defender) {
625  return ((2. / 3.141592) *
626  atan(5 * (double)((attacker + 1.0) / (defender + 1.0))));
627 }
628 
629 int planet_guns(int points) {
630  if (points < 0) return 0; /* shouldn't happen */
631  return std::min(20, points / 1000);
632 }
633 
634 static void mutate_sector(Sector &s) {
635  if (int_rand(0, 6) >= Defensedata[s.condition]) s.condition = s.type;
636 }
static void do_critical_hits(int, Ship *, int *, int *, int, char *)
Definition: shootblast.cc:556
static void mutate_sector(Sector &)
Definition: shootblast.cc:634
#define Distsq(x1, y1, x2, y2)
Definition: tweakables.h:218
int current_caliber(Ship *)
Definition: shootblast.cc:546
#define SYSTEMSIZE
Definition: tweakables.h:81
static void ship_disposition(Ship *, int *, int *, int *)
Definition: shootblast.cc:447
static int do_radiation(Ship *, double, int, int, const char *, char *)
Definition: shootblast.cc:310
#define SECONDARY
Definition: ships.h:16
int shoot_ship_to_ship(Ship *, Ship *, int, int, int, char *, char *)
Definition: shootblast.cc:43
int planet_guns(int)
Definition: shootblast.cc:629
#define SECTOR_DAMAGE
Definition: tweakables.h:120
#define SHIP_DAMAGE
Definition: tweakables.h:121
int shoot_ship_to_planet(Ship *, Planet *, int, int, int, SectorMap &, int, int, char *, char *)
Definition: shootblast.cc:188
#define PRIMARY
Definition: ships.h:15
#define TOXIC
Definition: tweakables.h:39
static double penetration_factor
Definition: shootblast.cc:28
#define DEFENSE
Definition: config.h:30
int shoot_planet_to_ship(Race *, Ship *, int, char *, char *)
int hit_odds(double, int *, double, int, int, int, int, int, int, int, int)
Definition: shootblast.cc:493
static int CEW_hit(double, int)
Definition: shootblast.cc:457
static int Num_hits(double, int, int, double, int, int, int, int, int, int, int, int)
Definition: shootblast.cc:469
static int cew_hit_odds(double, int)
Definition: shootblast.cc:518
static int do_damage(int, Ship *, double, int, int, int, int, double, const char *, char *)
Definition: shootblast.cc:354
double gun_range(Race *, Ship *, int)
Definition: shootblast.cc:530
static double p_factor(double, double)
Definition: shootblast.cc:624
double tele_range(int, double)
Definition: shootblast.cc:539
#define MAXPLAYERS
Definition: vars.h:45
void do_collateral(Ship *, int, int *, int *, int *, int *)
Definition: shootblast.cc:603
static int hit_probability
Definition: shootblast.cc:27