Galactic Bloodshed
shlmisc.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 /// \file shlmisc.cc
6 /// \brief Miscellaneous stuff included in the shell.
7 
8 #include "gb/shlmisc.h"
9 
10 #include <cctype>
11 #include <cmath>
12 #include <cstdio>
13 #include <cstdlib>
14 #include <cstring>
15 #include <ctime>
16 #include <sstream>
17 #include <string>
18 
19 #include "gb/GB_server.h"
20 #include "gb/buffers.h"
21 #include "gb/files.h"
22 #include "gb/files_shl.h"
23 #include "gb/max.h"
24 #include "gb/races.h"
25 #include "gb/ships.h"
26 #include "gb/tweakables.h"
27 #include "gb/vars.h"
28 
29 /**
30  * \brief Convert input string to a shipnum_t
31  * \param s User-provided input string
32  * \return If the user provided a valid number, return it.
33  */
35  if (s.size() > 1 && s[0] == '#') {
36  s.remove_prefix(1);
37  return string_to_shipnum(s);
38  }
39 
40  if (s.size() > 0 && std::isdigit(s[0])) {
41  return (std::stoi(std::string(s.begin(), s.end())));
42  }
43  return {};
44 }
45 
46 bool authorized(const governor_t Governor, const Ship &ship) {
47  return (!Governor || ship.governor == Governor);
48 }
49 
50 /**
51  * \brief Get start of ship lists from either a ship number or ScopeLevel
52  *
53  * start_shiplist and in_list work together so that a user can enter one of:
54  * * 1234 - a ship number
55  * * #1234 - a ship number prefixed by an octothorpe.
56  * * f - a letter representing the type of ship
57  * * frd - A sequence of letters representing the type of ship. Processing
58  * stops after first match.
59  * * \* - An Asterisk as a wildcard for first match.
60  *
61  * When a letter or asterisk is given, the shiplist is taken from the current
62  * scope.
63  *
64  * \param g Game object for scope
65  * \param p String that might contain ship number
66  * \return Ship number at the start of the ship list.
67  */
68 shipnum_t start_shiplist(GameObj &g, const std::string_view p) {
69  // If a ship number is given, return that.
70  auto s = string_to_shipnum(p);
71  if (s) {
72  return *s;
73  }
74 
75  // Ship number not given
76  switch (g.level) {
77  case ScopeLevel::LEVEL_UNIV:
78  getsdata(&Sdata);
79  return Sdata.ships;
80  case ScopeLevel::LEVEL_STAR:
81  getstar(&Stars[g.snum], g.snum); /*Stars doesn't need to be freed */
82  return Stars[g.snum]->ships;
83  case ScopeLevel::LEVEL_PLAN: {
84  const auto planet = getplanet(g.snum, g.pnum);
85  return planet.ships;
86  }
87  case ScopeLevel::LEVEL_SHIP:
88  auto ship = getship(g.shipno);
89  return ship->ships;
90  }
91 }
92 
93 /* Step through linked list at current player scope */
94 shipnum_t do_shiplist(Ship **s, shipnum_t *nextshipno) {
95  shipnum_t shipno;
96  if (!(shipno = *nextshipno)) return 0;
97 
98  if (!getship(s, shipno)) /* allocate memory, free in loop */
99  return 0;
100  *nextshipno = (*s)->nextship;
101  return shipno;
102 }
103 
104 /**
105  * \brief Check is the ship is in the given input string.
106  *
107  * See start_shiplist's comment for more details.
108  */
109 bool in_list(const player_t playernum, const std::string_view list,
110  const Ship &s, shipnum_t *nextshipno) {
111  if (s.owner != playernum || !s.alive) return false;
112 
113  if (list.length() == 0) return false;
114 
115  if (list[0] == '#' || std::isdigit(list[0])) {
116  *nextshipno = 0;
117  return true;
118  }
119 
120  // Match either the ship letter or * for wildcard.
121  for (const auto &p : list)
122  if (p == Shipltrs[s.type] || p == '*') return true;
123  return false;
124 }
125 
126 void DontOwnErr(int Playernum, int Governor, shipnum_t shipno) {
127  sprintf(buf, "You don't own ship #%lu.\n", shipno);
128  notify(Playernum, Governor, buf);
129 }
130 
131 int enufAP(int Playernum, int Governor, unsigned short AP, int x) {
132  int blah;
133 
134  if ((blah = (AP < x))) {
135  sprintf(buf, "You don't have %d action points there.\n", x);
136  notify(Playernum, Governor, buf);
137  }
138  return (!blah);
139 }
140 
141 /**
142  * \brief Find the player/governor that matches passwords
143  * \param racepass Password for the race
144  * \param govpass Password for the governor
145  * \return player and governor numbers, or 0 and 0 if not found
146  */
147 std::tuple<player_t, governor_t> getracenum(const std::string &racepass,
148  const std::string &govpass) {
149  for (auto race : races) {
150  if (racepass == race->password) {
151  for (governor_t j = 0; j <= MAXGOVERNORS; j++) {
152  if (*race->governor[j].password &&
153  govpass == race->governor[j].password) {
154  return {race->Playernum, j};
155  }
156  }
157  }
158  }
159  return {0, 0};
160 }
161 
162 /* returns player # from string containing that players name or #. */
163 player_t get_player(const std::string &name) {
164  player_t rnum = 0;
165 
166  if (isdigit(name[0])) {
167  if ((rnum = std::stoi(name)) < 1 || rnum > Num_races) return 0;
168  return rnum;
169  }
170  for (player_t i = 1; i <= Num_races; i++)
171  if (name == races[i - 1]->name) return i;
172  return 0;
173 }
174 
175 void allocateAPs(const command_t &argv, GameObj &g) {
176  player_t Playernum = g.player;
177  governor_t Governor = g.governor;
178  // TODO(jeffbailey): int APcount = 0;
179  int maxalloc;
180  int alloc;
181 
182  if (g.level == ScopeLevel::LEVEL_UNIV) {
183  sprintf(
184  buf,
185  "Change scope to the system you which to transfer global APs to.\n");
186  notify(Playernum, Governor, buf);
187  return;
188  }
189  alloc = std::stoi(argv[1]);
190  if (alloc <= 0) {
191  notify(Playernum, Governor,
192  "You must specify a positive amount of APs to allocate.\n");
193  return;
194  }
195 
196  getsdata(&Sdata);
197  maxalloc = MIN(Sdata.AP[Playernum - 1],
198  LIMIT_APs - Stars[g.snum]->AP[Playernum - 1]);
199  if (alloc > maxalloc) {
200  sprintf(buf, "Illegal value (%d) - maximum = %d\n", alloc, maxalloc);
201  notify(Playernum, Governor, buf);
202  return;
203  }
204  Sdata.AP[Playernum - 1] -= alloc;
205  putsdata(&Sdata);
206  getstar(&Stars[g.snum], g.snum);
207  Stars[g.snum]->AP[Playernum - 1] =
208  MIN(LIMIT_APs, Stars[g.snum]->AP[Playernum - 1] + alloc);
209  putstar(Stars[g.snum], g.snum);
210  sprintf(buf, "Allocated\n");
211  notify(Playernum, Governor, buf);
212 }
213 
214 void deductAPs(const player_t Playernum, const governor_t Governor,
215  unsigned int n, starnum_t snum, int sdata) {
216  if (n) {
217  if (!sdata) {
218  getstar(&Stars[snum], snum);
219 
220  if (Stars[snum]->AP[Playernum - 1] >= n)
221  Stars[snum]->AP[Playernum - 1] -= n;
222  else {
223  Stars[snum]->AP[Playernum - 1] = 0;
224  sprintf(buf,
225  "WHOA! You cheater! Oooohh! OOOOH!\n I'm "
226  "tellllllllliiiiiiinnnnnnnnnggggggggg!!!!!!!\n");
227  notify(Playernum, Governor, buf);
228  }
229 
230  putstar(Stars[snum], snum);
231  } else {
232  getsdata(&Sdata);
233  Sdata.AP[Playernum - 1] = std::max(0u, Sdata.AP[Playernum - 1] - n);
234  putsdata(&Sdata);
235  }
236  }
237 }
238 
239 double morale_factor(double x) {
240  return (atan((double)x / 10000.) / 3.14159565 + .5);
241 }
bool in_list(const player_t playernum, const std::string_view list, const Ship &s, shipnum_t *nextshipno)
Check is the ship is in the given input string.
Definition: shlmisc.cc:109
#define MAXGOVERNORS
Definition: tweakables.h:312
double morale_factor(double x)
Definition: shlmisc.cc:239
Planet getplanet(const starnum_t star, const planetnum_t pnum)
Definition: files_shl.cc:335
player_t get_player(const std::string &name)
Definition: shlmisc.cc:163
void DontOwnErr(int Playernum, int Governor, shipnum_t shipno)
Definition: shlmisc.cc:126
bool authorized(const governor_t Governor, const Ship &ship)
Definition: shlmisc.cc:46
#define MIN(x, y)
Definition: tweakables.h:213
shipnum_t start_shiplist(GameObj &g, const std::string_view p)
Get start of ship lists from either a ship number or ScopeLevel.
Definition: shlmisc.cc:68
void deductAPs(const player_t Playernum, const governor_t Governor, unsigned int n, starnum_t snum, int sdata)
Definition: shlmisc.cc:214
int enufAP(int Playernum, int Governor, unsigned short AP, int x)
Definition: shlmisc.cc:131
void putstar(startype *s, starnum_t snum)
Definition: files_shl.cc:813
std::optional< shipnum_t > string_to_shipnum(std::string_view s)
Convert input string to a shipnum_t.
Definition: shlmisc_test.cc:15
shipnum_t do_shiplist(Ship **s, shipnum_t *nextshipno)
Definition: shlmisc.cc:94
#define LIMIT_APs
Definition: tweakables.h:226
void getsdata(struct stardata *S)
Definition: files_shl.cc:272
void getstar(startype **s, int star)
Definition: files_shl.cc:281
std::tuple< player_t, governor_t > getracenum(const std::string &racepass, const std::string &govpass)
Find the player/governor that matches passwords.
Definition: shlmisc.cc:147
void putsdata(struct stardata *S)
Definition: files_shl.cc:804
void allocateAPs(const command_t &argv, GameObj &g)
Definition: shlmisc.cc:175