Galactic Bloodshed
orbit.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 /* orbit.c -- display orbits of planets (graphic representation) */
6 
7 #include "gb/commands/orbit.h"
8 
9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 
13 #include "gb/GB_server.h"
14 #include "gb/buffers.h"
15 #include "gb/files_shl.h"
16 #include "gb/fire.h"
17 #include "gb/getplace.h"
18 #include "gb/map.h"
19 #include "gb/max.h"
20 #include "gb/races.h"
21 #include "gb/ships.h"
22 #include "gb/tweakables.h"
23 #include "gb/vars.h"
24 
25 static double Lastx, Lasty, Zoom;
26 static const int SCALE = 100;
27 
28 static void DispStar(const GameObj &, const ScopeLevel, startype *, int, Race *,
29  char *);
30 static void DispPlanet(const GameObj &, const ScopeLevel, const Planet &,
31  char *, int, Race *, char *);
32 static void DispShip(const GameObj &, placetype *, Ship *, Race *, char *,
33  const Planet & = Planet());
34 
35 /* OPTIONS
36  * -p : If this option is set, ``orbit'' will not display planet names.
37  *
38  * -S : Do not display star names.
39  *
40  * -s : Do not display ships.
41  *
42  * -(number) : Do not display that #'d ship or planet (in case it obstructs
43  * the view of another object)
44  */
45 void orbit(const command_t &argv, GameObj &g) {
46  int DontDispNum = -1;
47  placetype where;
48  int DontDispPlanets;
49  int DontDispShips;
50  int DontDispStars;
51  char output[100000];
52 
53  DontDispPlanets = DontDispShips = DontDispStars = 0;
54 
55  /* find options, set flags accordingly */
56  for (int flag = 1; flag <= argv.size() - 1; flag++)
57  if (*argv[flag].c_str() == '-') {
58  for (int i = 1; argv[flag][i] != '\0'; i++) switch (argv[flag][i]) {
59  case 's':
60  DontDispShips = 1;
61  break;
62  case 'S':
63  DontDispStars = 1;
64  break;
65  case 'p':
66  DontDispPlanets = 1;
67  break;
68  default:
69  if (sscanf(argv[flag].c_str() + 1, "%d", &DontDispNum) != 1) {
70  sprintf(buf, "Bad number %s.\n", argv[flag].c_str() + 1);
71  notify(g.player, g.governor, buf);
72  DontDispNum = -1;
73  }
74  if (DontDispNum) DontDispNum--; /* make a '1' into a '0' */
75  break;
76  }
77  }
78 
79  if (argv.size() == 1) {
80  where = getplace(g, ":", 0);
81  int i = (g.level == ScopeLevel::LEVEL_UNIV);
82  Lastx = g.lastx[i];
83  Lasty = g.lasty[i];
84  Zoom = g.zoom[i];
85  } else {
86  where = getplace(g, argv[argv.size() - 1], 0);
87  Lastx = Lasty = 0.0;
88  Zoom = 1.1;
89  }
90 
91  if (where.err) {
92  notify(g.player, g.governor, "orbit: error in args.\n");
93  return;
94  }
95 
96  /* orbit type of map */
97  sprintf(output, "#");
98 
99  auto Race = races[g.player - 1];
100 
101  switch (where.level) {
102  case ScopeLevel::LEVEL_UNIV:
103  for (starnum_t i = 0; i < Sdata.numstars; i++)
104  if (DontDispNum != i) {
105  DispStar(g, ScopeLevel::LEVEL_UNIV, Stars[i], DontDispStars, Race,
106  buf);
107  strcat(output, buf);
108  }
109  if (!DontDispShips) {
110  Shiplist shiplist{Sdata.ships};
111  for (auto &s : shiplist) {
112  if (DontDispNum != s.number) {
113  DispShip(g, &where, &s, Race, buf);
114  strcat(output, buf);
115  }
116  }
117  }
118  break;
119  case ScopeLevel::LEVEL_STAR: {
120  DispStar(g, ScopeLevel::LEVEL_STAR, Stars[where.snum], DontDispStars,
121  Race, buf);
122  strcat(output, buf);
123 
124  for (planetnum_t i = 0; i < Stars[where.snum]->numplanets; i++)
125  if (DontDispNum != i) {
126  const auto p = getplanet((int)where.snum, i);
127  DispPlanet(g, ScopeLevel::LEVEL_STAR, p, Stars[where.snum]->pnames[i],
128  DontDispPlanets, Race, buf);
129  strcat(output, buf);
130  }
131  /* check to see if you have ships at orbiting the star, if so you can
132  see enemy ships */
133  bool iq = false;
134  if (g.god)
135  iq = true;
136  else {
137  Shiplist shiplist{Stars[where.snum]->ships};
138  for (auto &s : shiplist) {
139  if (s.owner == g.player && shipsight(s)) {
140  iq = true; /* you are there to sight, need a crew */
141  break;
142  }
143  }
144  }
145  if (!DontDispShips) {
146  Shiplist shiplist{Stars[where.snum]->ships};
147  for (auto &s : shiplist) {
148  if (DontDispNum != s.number &&
149  !(s.owner != g.player && s.type == ShipType::STYPE_MINE)) {
150  if ((s.owner == g.player) || iq) {
151  DispShip(g, &where, &s, Race, buf);
152  strcat(output, buf);
153  }
154  }
155  }
156  }
157  } break;
158  case ScopeLevel::LEVEL_PLAN: {
159  const auto p = getplanet(where.snum, where.pnum);
160  DispPlanet(g, ScopeLevel::LEVEL_PLAN, p,
161  Stars[where.snum]->pnames[where.pnum], DontDispPlanets, Race,
162  buf);
163  strcat(output, buf);
164 
165  /* check to see if you have ships at landed or
166  orbiting the planet, if so you can see orbiting enemy ships */
167  bool iq = false;
168  Shiplist shiplist{p.ships};
169  for (auto &s : shiplist) {
170  if (s.owner == g.player && shipsight(s)) {
171  iq = true; /* you are there to sight, need a crew */
172  break;
173  }
174  }
175  /* end check */
176  if (!DontDispShips) {
177  for (auto &s : shiplist) {
178  if (DontDispNum != s.number) {
179  if (!landed(s)) {
180  if ((s.owner == g.player) || iq) {
181  DispShip(g, &where, &s, Race, buf, p);
182  strcat(output, buf);
183  }
184  }
185  }
186  }
187  }
188  } break;
189  default:
190  g.out << "Bad scope.\n";
191  return;
192  }
193  strcat(output, "\n");
194  notify(g.player, g.governor, output);
195 }
196 
197 // TODO(jeffbailey) Remove DontDispStar parameter as unused, but it really looks
198 // like we should be doing something here.
199 static void DispStar(const GameObj &g, const ScopeLevel level, startype *star,
200  int /* DontDispStars */, Race *r, char *string) {
201  int x = 0; // TODO(jeffbailey): Inititalized x and y to 0.
202  int y = 0;
203  int stand;
204 
205  *string = '\0';
206 
207  if (level == ScopeLevel::LEVEL_UNIV) {
208  x = (int)(SCALE + ((SCALE * (star->xpos - Lastx)) / (UNIVSIZE * Zoom)));
209  y = (int)(SCALE + ((SCALE * (star->ypos - Lasty)) / (UNIVSIZE * Zoom)));
210  } else if (level == ScopeLevel::LEVEL_STAR) {
211  x = (int)(SCALE + (SCALE * (-Lastx)) / (SYSTEMSIZE * Zoom));
212  y = (int)(SCALE + (SCALE * (-Lasty)) / (SYSTEMSIZE * Zoom));
213  }
214  /*if (star->nova_stage)
215  DispArray(x, y, 11,7, Novae[star->nova_stage-1], fac); */
216  if (y >= 0 && x >= 0) {
217  if (r->governor[g.governor].toggle.color) {
218  stand = (isset(star->explored, g.player) ? g.player : 0) + '?';
219  sprintf(temp, "%c %d %d 0 * ", (char)stand, x, y);
220  strcat(string, temp);
221  stand = (isset(star->inhabited, g.player) ? g.player : 0) + '?';
222  sprintf(temp, "%c %s;", (char)stand, star->name);
223  strcat(string, temp);
224  } else {
225  stand = (isset(star->explored, g.player) ? 1 : 0);
226  sprintf(temp, "%d %d %d 0 * ", stand, x, y);
227  strcat(string, temp);
228  stand = (isset(star->inhabited, g.player) ? 1 : 0);
229  sprintf(temp, "%d %s;", stand, star->name);
230  strcat(string, temp);
231  }
232  }
233 }
234 
235 // TODO(jeffbailey): We remove DontDispPlanets as unused, but it really seems
236 // like we should be doing something here!
237 static void DispPlanet(const GameObj &g, const ScopeLevel level,
238  const Planet &p, char *name, int /* DontDispPlanets */,
239  Race *r, char *string) {
240  int x = 0; // TODO(jeffbailey): Check if init to 0 is right.
241  int y = 0;
242  int stand;
243 
244  *string = '\0';
245 
246  if (level == ScopeLevel::LEVEL_STAR) {
247  y = (int)(SCALE + (SCALE * (p.ypos - Lasty)) / (SYSTEMSIZE * Zoom));
248  x = (int)(SCALE + (SCALE * (p.xpos - Lastx)) / (SYSTEMSIZE * Zoom));
249  } else if (level == ScopeLevel::LEVEL_PLAN) {
250  y = (int)(SCALE + (SCALE * (-Lasty)) / (PLORBITSIZE * Zoom));
251  x = (int)(SCALE + (SCALE * (-Lastx)) / (PLORBITSIZE * Zoom));
252  }
253  if (x >= 0 && y >= 0) {
254  if (r->governor[g.governor].toggle.color) {
255  stand = (p.info[g.player - 1].explored ? g.player : 0) + '?';
256  sprintf(temp, "%c %d %d 0 %c ", (char)stand, x, y,
257  (stand > '0' ? Psymbol[p.type] : '?'));
258  strcat(string, temp);
259  stand = (p.info[g.player - 1].numsectsowned ? g.player : 0) + '?';
260  sprintf(temp, "%c %s", (char)stand, name);
261  strcat(string, temp);
262  } else {
263  stand = p.info[g.player - 1].explored ? 1 : 0;
264  sprintf(temp, "%d %d %d 0 %c ", stand, x, y,
265  (stand ? Psymbol[p.type] : '?'));
266  strcat(string, temp);
267  stand = p.info[g.player - 1].numsectsowned ? 1 : 0;
268  sprintf(temp, "%d %s", stand, name);
269  strcat(string, temp);
270  }
271  if (r->governor[g.governor].toggle.compat &&
272  p.info[g.player - 1].explored) {
273  sprintf(temp, "(%d)", (int)compatibility(p, r));
274  strcat(string, temp);
275  }
276  strcat(string, ";");
277  }
278 }
279 
280 static void DispShip(const GameObj &g, placetype *where, Ship *ship, Race *r,
281  char *string, const Planet &pl) {
282  int x;
283  int y;
284  int wm;
285  int stand;
286  double xt;
287  double yt;
288  double slope;
289 
290  if (!ship->alive) return;
291 
292  *string = '\0';
293 
294  switch (where->level) {
295  case ScopeLevel::LEVEL_PLAN:
296  x = (int)(SCALE +
297  (SCALE *
298  (ship->xpos - (Stars[where->snum]->xpos + pl.xpos) - Lastx)) /
299  (PLORBITSIZE * Zoom));
300  y = (int)(SCALE +
301  (SCALE *
302  (ship->ypos - (Stars[where->snum]->ypos + pl.ypos) - Lasty)) /
303  (PLORBITSIZE * Zoom));
304  break;
305  case ScopeLevel::LEVEL_STAR:
306  x = (int)(SCALE +
307  (SCALE * (ship->xpos - Stars[where->snum]->xpos - Lastx)) /
308  (SYSTEMSIZE * Zoom));
309  y = (int)(SCALE +
310  (SCALE * (ship->ypos - Stars[where->snum]->ypos - Lasty)) /
311  (SYSTEMSIZE * Zoom));
312  break;
313  case ScopeLevel::LEVEL_UNIV:
314  x = (int)(SCALE + (SCALE * (ship->xpos - Lastx)) / (UNIVSIZE * Zoom));
315  y = (int)(SCALE + (SCALE * (ship->ypos - Lasty)) / (UNIVSIZE * Zoom));
316  break;
317  default:
318  notify(g.player, g.governor, "WHOA! error in DispShip.\n");
319  return;
320  }
321 
322  switch (ship->type) {
323  case ShipType::STYPE_MIRROR:
324  if (ship->special.aimed_at.level == ScopeLevel::LEVEL_STAR) {
325  xt = Stars[ship->special.aimed_at.snum]->xpos;
326  yt = Stars[ship->special.aimed_at.snum]->ypos;
327  } else if (ship->special.aimed_at.level == ScopeLevel::LEVEL_PLAN) {
328  if (where->level == ScopeLevel::LEVEL_PLAN &&
329  ship->special.aimed_at.pnum == where->pnum) {
330  /* same planet */
331  xt = Stars[ship->special.aimed_at.snum]->xpos + pl.xpos;
332  yt = Stars[ship->special.aimed_at.snum]->ypos + pl.ypos;
333  } else { /* different planet */
334  const auto apl = getplanet(where->snum, where->pnum);
335  xt = Stars[ship->special.aimed_at.snum]->xpos + apl.xpos;
336  yt = Stars[ship->special.aimed_at.snum]->ypos + apl.ypos;
337  }
338  } else if (ship->special.aimed_at.level == ScopeLevel::LEVEL_SHIP) {
339  auto aship = getship(ship->special.aimed_at.shipno);
340  if (aship) {
341  xt = aship->xpos;
342  yt = aship->ypos;
343  } else
344  xt = yt = 0.0;
345  } else
346  xt = yt = 0.0;
347  wm = 0;
348 
349  if (xt == ship->xpos) {
350  if (yt > ship->ypos)
351  wm = 4;
352  else
353  wm = 0;
354  } else {
355  slope = (yt - ship->ypos) / (xt - ship->xpos);
356  if (yt == ship->ypos) {
357  if (xt > ship->xpos)
358  wm = 2;
359  else
360  wm = 6;
361  } else if (yt > ship->ypos) {
362  if (slope < -2.414) wm = 4;
363  if (slope > -2.414) wm = 5;
364  if (slope > -0.414) wm = 6;
365  if (slope > 0.000) wm = 2;
366  if (slope > 0.414) wm = 3;
367  if (slope > 2.414) wm = 4;
368  } else if (yt < ship->ypos) {
369  if (slope < -2.414) wm = 0;
370  if (slope > -2.414) wm = 1;
371  if (slope > -0.414) wm = 2;
372  if (slope > 0.000) wm = 6;
373  if (slope > 0.414) wm = 7;
374  if (slope > 2.414) wm = 0;
375  }
376  }
377 
378  /* (magnification) */
379  if (x >= 0 && y >= 0) {
380  if (r->governor[g.governor].toggle.color) {
381  sprintf(string, "%c %d %d %d %c %c %lu;", (char)(ship->owner + '?'),
382  x, y, wm, Shipltrs[ship->type], (char)(ship->owner + '?'),
383  ship->number);
384  } else {
385  stand = (ship->owner == r->governor[g.governor].toggle.highlight);
386  sprintf(string, "%d %d %d %d %c %d %lu;", stand, x, y, wm,
387  Shipltrs[ship->type], stand, ship->number);
388  }
389  }
390  break;
391 
392  case ShipType::OTYPE_CANIST:
393  case ShipType::OTYPE_GREEN:
394  break;
395 
396  default:
397  /* other ships can only be seen when in system */
398  wm = 0;
399  if (ship->whatorbits != ScopeLevel::LEVEL_UNIV ||
400  ((ship->owner == g.player) || g.god))
401  if (x >= 0 && y >= 0) {
402  if (r->governor[g.governor].toggle.color) {
403  sprintf(string, "%c %d %d %d %c %c %lu;", (char)(ship->owner + '?'),
404  x, y, wm, Shipltrs[ship->type], (char)(ship->owner + '?'),
405  ship->number);
406  } else {
407  stand = (ship->owner == r->governor[g.governor].toggle.highlight);
408  sprintf(string, "%d %d %d %d %c %d %lu;", stand, x, y, wm,
409  Shipltrs[ship->type], stand, ship->number);
410  }
411  }
412  break;
413  }
414 }
static double Lastx
Definition: orbit.cc:25
#define SYSTEMSIZE
Definition: tweakables.h:81
void orbit(const command_t &argv, GameObj &g)
Definition: orbit.cc:45
Planet getplanet(const starnum_t star, const planetnum_t pnum)
Definition: files_shl.cc:335
static double Zoom
Definition: orbit.cc:25
#define isset(a, i)
Definition: vars.h:312
static const int SCALE
Definition: orbit.cc:26
double compatibility(const Planet &planet, const Race *race)
Definition: max.cc:37
static void DispShip(const GameObj &, placetype *, Ship *, Race *, char *, const Planet &=Planet())
Definition: orbit.cc:280
#define PLORBITSIZE
Definition: tweakables.h:82
#define UNIVSIZE
Definition: tweakables.h:80
static void DispStar(const GameObj &, const ScopeLevel, startype *, int, Race *, char *)
Definition: orbit.cc:199
static void DispPlanet(const GameObj &, const ScopeLevel, const Planet &, char *, int, Race *, char *)
Definition: orbit.cc:237
static double Lasty
Definition: orbit.cc:25