7 #include "gb/doturncmd.h" 15 #include "gb/GB_server.h" 16 #include "gb/buffers.h" 18 #include "gb/doplanet.h" 19 #include "gb/doship.h" 20 #include "gb/doturn.h" 22 #include "gb/files_shl.h" 23 #include "gb/moveplanet.h" 27 #include "gb/shlmisc.h" 29 #include "gb/tweakables.h" 30 #include "gb/utils/rand.h" 34 static constexpr void maintain(Race &r, Race::gov &governor,
35 const money_t amount)
noexcept {
36 if (governor.money >= amount)
37 governor.money -= amount;
39 r.morale -= (amount - governor.money) / 10;
45 static int APadd(
int,
int, Race *);
55 unsigned long dummy[2];
70 bzero((
char *)starpopns,
sizeof(starpopns));
71 bzero((
char *)starnumships,
sizeof(starnumships));
72 bzero((
char *)Sdatanumships,
sizeof(Sdatanumships));
73 bzero((
char *)Stinfo,
sizeof(Stinfo));
74 bzero((
char *)StarsInhab,
sizeof(StarsInhab));
75 bzero((
char *)Power,
sizeof(Power));
76 bzero((
char *)inhabited,
sizeof(inhabited));
81 for (shipnum_t i = 1; i <= Num_ships; i++)
domine(i
, 0
);
83 ships = (Ship **)malloc(
sizeof(Ship *) * (Num_ships + 1));
84 for (shipnum_t i = 1; i <= Num_ships; i++) (
void)getship(&ships[i], i);
89 for (starnum_t star = 0; star < Sdata.numstars; star++) {
93 for (planetnum_t i = 0; i < Stars[star]->numplanets; i++) {
95 if (planets[star][i]->type != PlanetType::ASTEROID) Planet_count++;
97 if (Stars[star]->pnames[i] ==
nullptr)
98 sprintf(Stars[star]->pnames[i],
"NULL-%d", i);
100 if (Stars[star]->name[0] ==
'\0')
101 sprintf(Stars[star]->name,
"NULL-%d", star);
104 VN_brain.Most_mad = 0;
106 for (player_t i = 1; i <= Num_races; i++) {
110 races[i - 1]->controlled_planets = 0;
111 races[i - 1]->planet_points = 0;
112 for (
auto &governor : races[i - 1]->governor)
113 if (governor.active) {
115 governor.maintain = 0;
116 governor.cost_market = 0;
117 governor.profit_market = 0;
119 governor.cost_tech = 0;
123 VN_brain.Total_mad += Sdata.VN_hitlist[i - 1];
125 if (VN_brain.Most_mad > 0 &&
126 Sdata.VN_hitlist[VN_brain.Most_mad - 1] <= Sdata.VN_hitlist[i - 1])
127 VN_brain.Most_mad = i;
140 for (commodnum_t i = Num_commods; i >= 1; i--) {
148 if (c->owner && c->bidder &&
149 (races[c->bidder - 1]->governor[c->bidder_gov].money >= c->bid)) {
150 races[c->bidder - 1]->governor[c->bidder_gov].money -= c->bid;
151 races[c->owner - 1]->governor[c->governor].money += c->bid;
154 races[c->bidder - 1]->governor[c->bidder_gov].cost_market +=
156 races[c->owner - 1]->governor[c->governor].profit_market += c->bid;
157 maintain(*races[c->bidder - 1],
158 races[c->bidder - 1]->governor[c->bidder_gov], cost);
161 planets[c->star_to][c->planet_to]->info[c->bidder - 1].resource +=
165 planets[c->star_to][c->planet_to]->info[c->bidder - 1].fuel +=
169 planets[c->star_to][c->planet_to]->info[c->bidder - 1].destruct +=
173 planets[c->star_to][c->planet_to]->info[c->bidder - 1].crystals +=
178 "Lot %lu purchased from %s [%d] at a cost of %ld.\n %ld " 179 "%s arrived at /%s/%s\n",
180 i, races[c->owner - 1]->name, c->owner, c->bid, c->amount,
181 Commod[c->type], Stars[c->star_to]->name,
182 Stars[c->star_to]->pnames[c->planet_to]);
183 push_telegram((
int)c->bidder, (
int)c->bidder_gov, buf);
184 sprintf(buf,
"Lot %lu (%lu %s) sold to %s [%d] at a cost of %ld.\n", i,
185 c->amount, Commod[c->type], races[c->bidder - 1]->name,
187 push_telegram((
int)c->owner, (
int)c->governor, buf);
188 c->owner = c->governor = 0;
189 c->bidder = c->bidder_gov = 0;
191 c->bidder = c->bidder_gov = 0;
202 for (shipnum_t i = 1; i <= Num_ships; i++)
203 if (ships[i]->alive) {
209 for (
int j = 0; j <= 9; j++)
210 for (shipnum_t i = 1; i <= Num_ships; i++) {
211 if (ships[i]->alive && ships[i]->speed == j) {
213 if ((ships[i]->type == ShipType::STYPE_MISSILE) &&
222 for (shipnum_t i = 1; i <= Num_ships; i++)
223 if (ships[i]->alive && Shipdata[ships[i]->type][ABIL_MAINTAIN]) {
225 races[ships[i]->owner - 1]->governor[ships[i]->governor].maintain +=
226 ships[i]->build_cost;
227 if (ships[i]->troops)
228 races[ships[i]->owner - 1]->governor[ships[i]->governor].maintain +=
235 for (shipnum_t i = 1; i <= Num_ships; i++)
239 for (shipnum_t i = 1; i <= Num_ships; i++) {
240 ships[i]->nextship = 0;
245 for (starnum_t star = 0; star < Sdata.numstars; star++) {
246 Stars[star]->ships = 0;
247 for (planetnum_t i = 0; i < Stars[star]->numplanets; i++)
248 planets[star][i]->ships = 0;
252 for (shipnum_t i = Num_ships; i >= 1; i--) {
253 if (ships[i]->alive) {
254 switch (ships[i]->whatorbits) {
255 case ScopeLevel::LEVEL_UNIV:
256 insert_sh_univ(&Sdata, ships[i]);
258 case ScopeLevel::LEVEL_STAR:
259 insert_sh_star(Stars[ships[i]->storbits], ships[i]);
261 case ScopeLevel::LEVEL_PLAN:
262 insert_sh_plan(planets[ships[i]->storbits][ships[i]->pnumorbits],
265 case ScopeLevel::LEVEL_SHIP:
266 insert_sh_ship(ships[i], ships[ships[i]->destshipno]);
274 for (shipnum_t i = 1; i <= Num_ships; i++)
275 if ((ships[i]->type == ShipType::OTYPE_ABM) && ships[i]->alive)
278 for (shipnum_t i = 1; i <= Num_ships; i++)
279 if ((ships[i]->type == ShipType::STYPE_MISSILE) && ships[i]->alive &&
283 for (shipnum_t i = Num_ships; i >= 1; i--)
putship(ships[i]
);
285 for (starnum_t star = 0; star < Sdata.numstars; star++) {
286 for (planetnum_t i = 0; i < Stars[star]->numplanets; i++) {
288 for (player_t j = 1; j <= Num_races; j++) {
289 if (planets[star][i]->info[j - 1].numsectsowned) {
290 setbit(inhabited[star], j);
291 setbit(Stars[star]->inhabited, j);
293 if (planets[star][i]->type != PlanetType::ASTEROID &&
294 (planets[star][i]->info[j - 1].numsectsowned >
295 planets[star][i]->Maxx * planets[star][i]->Maxy / 2))
296 races[j - 1]->controlled_planets++;
298 if (planets[star][i]->info[j - 1].numsectsowned)
299 races[j - 1]->planet_points += planet_points(*planets[star][i]);
314 for (player_t i = 1; i <= Num_races; i++) {
315 if (starpopns[star][i - 1])
316 setbit(Stars[star]->inhabited, i);
318 clrbit(Stars[star]->inhabited, i);
320 if (
isset(Stars[star]->inhabited, i)) {
323 APs = Stars[star]->AP[i - 1] + APadd((
int)starnumships[star][i - 1],
324 (
int)starpopns[star][i - 1],
327 Stars[star]->AP[i - 1] = APs;
332 if (inhabited[star][0] + inhabited[star][1]) {
333 dummy[0] = (Blocks[i - 1].invite[0] & Blocks[i - 1].pledge[0]);
334 dummy[1] = (Blocks[i - 1].invite[1] & Blocks[i - 1].pledge[1]);
335 Blocks[i - 1].systems_owned +=
336 ((inhabited[star][0] | dummy[0]) == dummy[0]) &&
337 ((inhabited[star][1] | dummy[1]) == dummy[1]);
345 for (player_t i = 1; i <= Num_races; i++) {
346 Blocks[i - 1].systems_owned = 0;
347 if (governed(races[i - 1])) {
350 APs = Sdata.AP[i - 1] + races[i - 1]->planet_points;
352 Sdata.AP[i - 1] = APs;
363 (
struct victstruct *)malloc(Num_races *
sizeof(
struct victstruct));
364 for (player_t i = 1; i <= Num_races; i++) {
365 victory[i - 1].numsects = 0;
366 victory[i - 1].shipcost = 0;
367 victory[i - 1].shiptech = 0;
368 victory[i - 1].morale = races[i - 1]->morale;
369 victory[i - 1].res = 0;
370 victory[i - 1].des = 0;
371 victory[i - 1].fuel = 0;
372 victory[i - 1].money = races[i - 1]->governor[0].money;
373 for (
auto &governor : races[i - 1]->governor)
374 if (governor.active) victory[i - 1].money += governor.money;
377 for (starnum_t star = 0; star < Sdata.numstars; star++) {
379 for (planetnum_t i = 0; i < Stars[star]->numplanets; i++) {
380 for (player_t j = 0; j < Num_races; j++) {
381 if (!planets[star][i]->info[j].explored)
continue;
382 victory[j].numsects += (
int)planets[star][i]->info[j].numsectsowned;
383 victory[j].res += (
int)planets[star][i]->info[j].resource;
384 victory[j].des += (
int)planets[star][i]->info[j].destruct;
385 victory[j].fuel += (
int)planets[star][i]->info[j].fuel;
390 for (shipnum_t i = 1; i <= Num_ships; i++) {
391 if (!ships[i]->alive)
continue;
392 victory[ships[i]->owner - 1].shipcost += ships[i]->build_cost;
393 victory[ships[i]->owner - 1].shiptech += ships[i]->tech;
394 victory[ships[i]->owner - 1].res += ships[i]->resource;
395 victory[ships[i]->owner - 1].des += ships[i]->destruct;
396 victory[ships[i]->owner - 1].fuel += ships[i]->fuel;
400 for (player_t i = 0; i < Num_races; i++) {
401 races[i]->victory_score =
404 (
VICT_TECH * (
int)victory[i].shiptech))) +
405 (
VICT_RES * ((
int)victory[i].res + (
int)victory[i].des)) +
409 races[i]->victory_score = (
int)(morale_factor((
double)victory[i].morale) *
410 races[i]->victory_score);
415 for (shipnum_t i = 1; i <= Num_ships; i++) {
421 for (player_t i = 1; i <= Num_races; i++) {
423 if (races[i - 1]->collective_iq) {
424 double x = ((2. / 3.14159265) *
426 races[i - 1]->IQ = races[i - 1]->IQ_limit * x * x;
428 races[i - 1]->tech += (
double)(races[i - 1]->IQ) / 100.0;
429 races[i - 1]->morale += Power[i - 1].planets_owned;
430 make_discoveries(races[i - 1]);
431 races[i - 1]->turn += 1;
432 if (races[i - 1]->controlled_planets >=
434 races[i - 1]->victory_turns++;
436 races[i - 1]->victory_turns = 0;
438 if (races[i - 1]->controlled_planets >=
440 for (player_t j = 1; j <= Num_races; j++)
441 races[j - 1]->translate[i - 1] = 100;
443 Blocks[i - 1].VPs = 10 * Blocks[i - 1].systems_owned;
445 for (
auto &governor : races[i - 1]->governor)
447 maintain(*races[i - 1], governor, governor.maintain);
450 for (player_t i = 1; i <= Num_races; i++) putrace(races[i - 1]);
456 compute_power_blocks();
457 for (player_t i = 1; i <= Num_races; i++) {
458 Power[i - 1].money = 0;
459 for (
auto &governor : races[i - 1]->governor)
460 if (governor.active) Power[i - 1].money += governor.money;
466 for (player_t j = 1; j <= Num_races; j++) {
468 notify_race(j,
"Finished with update.\n");
470 notify_race(j,
"Finished with movement segment.\n");
477 static int APadd(
int sh,
int popn, Race *race) {
480 APs = round_rand((
double)sh / 10.0 + 5. * log10(1.0 + (
double)popn));
484 return round_rand((
double)APs / 20.);
488 return (race->Gov_ship && race->Gov_ship <= Num_ships &&
489 ships[race->Gov_ship] !=
nullptr && ships[race->Gov_ship]->alive &&
490 ships[race->Gov_ship]->docked &&
491 (ships[race->Gov_ship]->whatdest == ScopeLevel::LEVEL_PLAN ||
492 (ships[race->Gov_ship]->whatorbits == ScopeLevel::LEVEL_SHIP &&
493 ships[ships[race->Gov_ship]->destshipno]->type ==
494 ShipType::STYPE_HABITAT &&
495 (ships[ships[race->Gov_ship]->destshipno]->whatorbits ==
496 ScopeLevel::LEVEL_PLAN ||
497 ships[ships[race->Gov_ship]->destshipno]->whatorbits ==
498 ScopeLevel::LEVEL_STAR))));
506 if (s->nova_stage > 0) {
507 if (s->nova_stage > 14) {
510 sprintf(telegram_buf,
"Notice\n");
511 sprintf(buf,
"\n Scientists report that star %s\n", s->name);
512 strcat(telegram_buf, buf);
513 sprintf(buf,
"is no longer undergoing nova.\n");
514 strcat(telegram_buf, buf);
515 for (i = 1; i <= Num_races; i++) push_telegram_race(i, telegram_buf);
520 }
else if (s->stability > 20) {
523 if ((s->stability + a) > 100) {
526 sprintf(telegram_buf,
"***** BULLETIN! ******\n");
527 sprintf(buf,
"\n Scientists report that star %s\n", s->name);
528 strcat(telegram_buf, buf);
529 sprintf(buf,
"is undergoing nova.\n");
530 strcat(telegram_buf, buf);
531 for (i = 1; i <= Num_races; i++) push_telegram_race(i, telegram_buf);
536 if (((
int)s->stability + a) < 0)
549 int win_category[64];
551 const int BIG_WINNER = 1;
552 const int LITTLE_WINNER = 2;
554 for (i = 1; i <= Num_races; i++) {
555 win_category[i - 1] = 0;
556 if (races[i - 1]->controlled_planets >=
557 Planet_count * VICTORY_PERCENT / 100) {
558 win_category[i - 1] = LITTLE_WINNER;
560 if (races[i - 1]->victory_turns >= VICTORY_UPDATES) {
562 win_category[i - 1] = BIG_WINNER;
566 for (i = 1; i <= Num_races; i++) {
567 sprintf(telegram_buf,
"*** Attention ***");
568 push_telegram_race(i, telegram_buf);
569 sprintf(telegram_buf,
"This game of Galactic Bloodshed is now *over*");
570 push_telegram_race(i, telegram_buf);
571 sprintf(telegram_buf,
"The big winner%s",
572 (game_over == 1) ?
" is" :
"s are");
573 push_telegram_race(i, telegram_buf);
574 for (j = 1; j <= Num_races; j++)
575 if (win_category[j - 1] == BIG_WINNER) {
576 sprintf(telegram_buf,
"*** [%2d] %-30.30s ***", j,
578 push_telegram_race(i, telegram_buf);
580 sprintf(telegram_buf,
"Lesser winners:");
581 push_telegram_race(i, telegram_buf);
582 for (j = 1; j <= Num_races; j++)
583 if (win_category[j - 1] == LITTLE_WINNER) {
584 sprintf(telegram_buf,
"+++ [%2d] %-30.30s +++", j,
586 push_telegram_race(i, telegram_buf);
596 push_telegram_race(r->Playernum,
597 "You have discovered HYPERDRIVE technology.\n");
601 push_telegram_race(r->Playernum,
"You have discovered LASER technology.\n");
605 push_telegram_race(r->Playernum,
"You have discovered CEW technology.\n");
606 r->discoveries[
D_CEW] = 1;
609 push_telegram_race(r->Playernum,
"You have discovered VN technology.\n");
610 r->discoveries[
D_VN] = 1;
613 push_telegram_race(r->Playernum,
614 "You have discovered TRACTOR BEAM technology.\n");
618 push_telegram_race(r->Playernum,
619 "You have discovered TRANSPORTER technology.\n");
623 push_telegram_race(r->Playernum,
"You have discovered AVPM technology.\n");
624 r->discoveries[
D_AVPM] = 1;
627 push_telegram_race(r->Playernum,
"You have discovered CLOAK technology.\n");
631 push_telegram_race(r->Playernum,
632 "You have discovered WORMHOLE technology.\n");
636 push_telegram_race(r->Playernum,
637 "You have discovered CRYSTAL technology.\n");
643 if (ship->whatdest == ScopeLevel::LEVEL_PLAN)
return 1;
653 for (star = 0; star < Sdata.numstars; star++)
654 for (i = 1; i <= Num_races; i++)
655 for (j = 1; j <= Num_races; j++)
656 if (ground_assaults[i - 1][j - 1][star]) {
657 sprintf(buf,
"%s: %s [%d] assaults %s [%d] %d times.\n",
658 Stars[star]->name, races[i - 1]->name, i, races[j - 1]->name,
659 j, ground_assaults[i - 1][j - 1][star]);
661 ground_assaults[i - 1][j - 1][star] = 0;
667 case PlanetType::ASTEROID:
669 case PlanetType::EARTH:
671 case PlanetType::MARS:
673 case PlanetType::ICEBALL:
675 case PlanetType::GASGIANT:
677 case PlanetType::WATER:
679 case PlanetType::FOREST:
681 case PlanetType::DESERT:
void post(const char *origmsg, int type)
Planet getplanet(const starnum_t star, const planetnum_t pnum)
void makecommoddead(int commodnum)
static void output_ground_attacks()
#define UPDATE_TROOP_COST
static int governed(Race *)
static int planet_points(const Planet &)
void makeshipdead(int shipnum)
static void make_discoveries(Race *)
void moveplanet(int, Planet *, int)
void putcommod(commodtype *c, int commodnum)
#define TECH_TRACTOR_BEAM
void Putblock(struct block b[MAXPLAYERS])
void putstar(startype *s, starnum_t snum)
int doplanet(const int, Planet *, const int)
void getsdata(struct stardata *S)
int shipping_cost(int to, int from, double *dist, int value)
void putplanet(const Planet &p, startype *star, const int pnum)
static constexpr void maintain(Race &r, Race::gov &governor, const money_t amount) noexcept
static void fix_stability(startype *)
void getstar(startype **s, int star)
static int APadd(int, int, Race *)
int getcommod(commodtype **c, commodnum_t commodnum)
void putsdata(struct stardata *S)
static int attack_planet(Ship *)
void Putpower(struct power p[MAXPLAYERS])