16 #include "gb/GB_server.h" 17 #include "gb/buffers.h" 18 #include "gb/config.h" 20 #include "gb/files_shl.h" 22 #include "gb/getplace.h" 25 #include "gb/shipdata.h" 27 #include "gb/shlmisc.h" 28 #include "gb/shootblast.h" 30 #include "gb/tweakables.h" 36 static std::optional<ScopeLevel>
build_at_ship(GameObj &, Ship *,
int *,
int *);
47 static void Getship(Ship *, ShipType, Race *);
52 const Planet &planet,
const Sector §or,
53 const int x,
const int y,
char *string) {
54 auto shipc = Shipltrs[what];
56 sprintf(string,
"You have no more civs in the sector!\n");
59 if (sector.condition == SectorType::SEC_WASTED) {
60 sprintf(string,
"You can't build on wasted sectors.\n");
63 if (sector.owner != Race->Playernum && !Race->God) {
64 sprintf(string,
"You don't own that sector.\n");
67 if ((!(Shipdata[what][ABIL_BUILD] & 1)) && !Race->God) {
68 sprintf(string,
"This ship type cannot be built on a planet.\n");
69 sprintf(temp,
"Use 'build ? %c' to find out where it can be built.\n",
74 if (what == ShipType::OTYPE_QUARRY) {
75 Shiplist shiplist(planet.ships);
76 for (
auto s : shiplist) {
77 if (s.alive && s.type == ShipType::OTYPE_QUARRY && s.land_x == x &&
79 sprintf(string,
"There already is a quarry here.\n");
89 void upgrade(
const command_t &argv, GameObj &g) {
90 const player_t Playernum = g.player;
91 const governor_t Governor = g.governor;
100 if (g.level != ScopeLevel::LEVEL_SHIP) {
101 g.out <<
"You have to change scope to the ship you wish to upgrade.\n";
104 auto dirship = getship(g.shipno);
106 g.out <<
"Illegal dir value.\n";
109 if (testship(Playernum, Governor, *dirship)) {
112 if (dirship->damage) {
113 g.out <<
"You cannot upgrade damaged ships.\n";
116 if (dirship->type == ShipType::OTYPE_FACTORY) {
117 g.out <<
"You can't upgrade factories.\n";
121 Race = races[Playernum - 1];
122 auto ship = *dirship;
124 if (argv.size() == 3)
125 value = std::stoi(argv[2]);
130 g.out <<
"That's a ridiculous setting.\n";
134 if (!Shipdata[dirship->build_type][ABIL_MOD]) {
135 g.out <<
"This ship cannot be upgraded.\n";
139 if (argv[1] ==
"armor") {
140 ship.armor =
MAX(dirship->armor,
MIN(value, 100));
141 }
else if (argv[1] ==
"crew" && Shipdata[dirship->build_type][ABIL_MAXCREW]) {
142 ship.max_crew =
MAX(dirship->max_crew,
MIN(value, 10000));
143 }
else if (argv[1] ==
"cargo" && Shipdata[dirship->build_type][ABIL_CARGO]) {
144 ship.max_resource =
MAX(dirship->max_resource,
MIN(value, 10000));
145 }
else if (argv[1] ==
"hanger" &&
146 Shipdata[dirship->build_type][ABIL_HANGER]) {
147 ship.max_hanger =
MAX(dirship->max_hanger,
MIN(value, 10000));
148 }
else if (argv[1] ==
"fuel" && Shipdata[dirship->build_type][ABIL_FUELCAP]) {
149 ship.max_fuel =
MAX(dirship->max_fuel,
MIN(value, 10000));
150 }
else if (argv[1] ==
"mount" && Shipdata[dirship->build_type][ABIL_MOUNT] &&
153 g.out <<
"Your race does not now how to utilize crystal power yet.\n";
156 ship.mount = !ship.mount;
157 }
else if (argv[1] ==
"destruct" &&
158 Shipdata[dirship->build_type][ABIL_DESTCAP]) {
159 ship.max_destruct =
MAX(dirship->max_destruct,
MIN(value, 10000));
160 }
else if (argv[1] ==
"speed" && Shipdata[dirship->build_type][ABIL_SPEED]) {
161 ship.max_speed =
MAX(dirship->max_speed,
MAX(1,
MIN(value, 9)));
162 }
else if (argv[1] ==
"hyperdrive" &&
163 Shipdata[dirship->build_type][ABIL_JUMP] &&
165 ship.hyper_drive.has = 1;
166 }
else if (argv[1] ==
"primary" &&
167 Shipdata[dirship->build_type][ABIL_PRIMARY]) {
168 if (argv[2] ==
"strength") {
169 if (ship.primtype == GTYPE_NONE) {
170 g.out <<
"No caliber defined.\n";
173 ship.primary = std::stoi(argv[3]);
174 ship.primary =
MAX(ship.primary, dirship->primary);
175 }
else if (argv[2] ==
"caliber") {
176 if (argv[3] ==
"light")
177 ship.primtype =
MAX(GTYPE_LIGHT, dirship->primtype);
178 else if (argv[3] ==
"medium")
179 ship.primtype =
MAX(GTYPE_MEDIUM, dirship->primtype);
180 else if (argv[3] ==
"heavy")
181 ship.primtype =
MAX(GTYPE_HEAVY, dirship->primtype);
183 g.out <<
"No such caliber.\n";
187 MIN(Shipdata[dirship->build_type][ABIL_PRIMARY], ship.primtype);
189 g.out <<
"No such gun characteristic.\n";
192 }
else if (argv[1] ==
"secondary" &&
193 Shipdata[dirship->build_type][ABIL_SECONDARY]) {
194 if (argv[2] ==
"strength") {
195 if (ship.sectype == GTYPE_NONE) {
196 g.out <<
"No caliber defined.\n";
199 ship.secondary = std::stoi(argv[3]);
200 ship.secondary =
MAX(ship.secondary, dirship->secondary);
201 }
else if (argv[2] ==
"caliber") {
202 if (argv[3] ==
"light")
203 ship.sectype =
MAX(GTYPE_LIGHT, dirship->sectype);
204 else if (argv[3] ==
"medium")
205 ship.sectype =
MAX(GTYPE_MEDIUM, dirship->sectype);
206 else if (argv[3] ==
"heavy")
207 ship.sectype =
MAX(GTYPE_HEAVY, dirship->sectype);
209 g.out <<
"No such caliber.\n";
213 MIN(Shipdata[dirship->build_type][ABIL_SECONDARY], ship.sectype);
215 g.out <<
"No such gun characteristic.\n";
218 }
else if (argv[1] ==
"cew" && Shipdata[dirship->build_type][ABIL_CEW]) {
220 g.out <<
"Your race cannot build confined energy weapons.\n";
223 if (!Shipdata[dirship->build_type][ABIL_CEW]) {
224 g.out <<
"This kind of ship cannot mount confined energy weapons.\n";
227 value = std::stoi(argv[3]);
228 if (argv[2] ==
"strength") {
230 }
else if (argv[2] ==
"range") {
231 ship.cew_range = value;
233 g.out <<
"No such option for CEWs.\n";
236 }
else if (argv[1] ==
"laser" && Shipdata[dirship->build_type][ABIL_LASER]) {
238 g.out <<
"Your race cannot build lasers.\n";
241 if (Shipdata[dirship->build_type][ABIL_LASER])
244 g.out <<
"That ship cannot be fitted with combat lasers.\n";
248 g.out <<
"That characteristic either doesn't exist or can't be modified.\n";
253 if ((complex = complexity(ship)) > Race->tech) {
254 sprintf(buf,
"This upgrade requires an engineering technology of %.1f.\n",
256 notify(Playernum, Governor, buf);
262 std::optional<Ship> s2;
263 if (dirship->whatorbits == ScopeLevel::LEVEL_SHIP) {
264 s2 = getship(dirship->destshipno);
265 if (s2->max_hanger - (s2->hanger - dirship->size) < ship_size(ship)) {
266 sprintf(buf,
"Not enough free hanger space on %c%ld.\n",
267 Shipltrs[s2->type], dirship->destshipno);
268 notify(Playernum, Governor, buf);
270 buf,
"%d more needed.\n",
271 ship_size(ship) - (s2->max_hanger - (s2->hanger - dirship->size)));
272 notify(Playernum, Governor, buf);
278 newcost = Race->God ? 0 : (
int)cost(ship);
279 oldcost = Race->God ? 0 : dirship->build_cost;
280 netcost = Race->God ? 0 : 2 * (newcost - oldcost);
281 if (newcost < oldcost) {
282 g.out <<
"You cannot downgrade ships!\n";
285 if (!Race->God) netcost += !netcost;
287 if (netcost > dirship->resource) {
288 sprintf(buf,
"Old value %dr New value %dr\n", oldcost, newcost);
289 notify(Playernum, Governor, buf);
290 sprintf(buf,
"You need %d resources on board to make this modification.\n",
292 notify(Playernum, Governor, buf);
293 }
else if (netcost || Race->God) {
294 sprintf(buf,
"Old value %dr New value %dr\n", oldcost, newcost);
295 notify(Playernum, Governor, buf);
296 sprintf(buf,
"Characteristic modified at a cost of %d resources.\n",
298 notify(Playernum, Governor, buf);
299 bcopy(&ship, &*dirship,
sizeof(Ship));
300 dirship->resource -= netcost;
301 if (dirship->whatorbits == ScopeLevel::LEVEL_SHIP) {
302 s2->hanger -= dirship->size;
303 dirship->size = ship_size(*dirship);
304 s2->hanger += dirship->size;
307 dirship->size = ship_size(*dirship);
308 dirship->base_mass = getmass(*dirship);
309 dirship->build_cost = Race->God ? 0 : cost(*dirship);
310 dirship->complexity = complexity(*dirship);
314 g.out <<
"You can not make this modification.\n";
318 const player_t Playernum = g.player;
319 const governor_t Governor = g.governor;
321 if (argv[0] ==
"make")
331 if (g.level != ScopeLevel::LEVEL_SHIP) {
332 g.out <<
"You have to change scope to an installation.\n";
336 auto dirship = getship(g.shipno);
338 g.out <<
"Illegal dir value.\n";
341 if (testship(Playernum, Governor, *dirship)) {
344 if (dirship->type != ShipType::OTYPE_FACTORY) {
345 g.out <<
"That is not a factory.\n";
348 if (dirship->on && argv.size() > 1) {
349 g.out <<
"This factory is already online.\n";
352 Race = races[Playernum - 1];
356 size = dirship->size;
357 dirship->size = ship_size(*dirship);
360 if (argv.size() < 2) {
361 if (!dirship->build_type) {
362 g.out <<
"No ship type specified.\n";
365 notify(Playernum, Governor,
366 " --- Current Production Specifications ---\n");
367 sprintf(buf,
"%s\t\t\tArmor: %4d\t\tGuns:",
368 (dirship->on ?
"Online" :
"Offline"), dirship->armor);
369 notify(Playernum, Governor, buf);
370 if (Shipdata[dirship->build_type][ABIL_PRIMARY] &&
371 dirship->primtype != GTYPE_NONE) {
372 sprintf(buf,
"%3lu%c", dirship->primary,
373 (dirship->primtype == GTYPE_LIGHT
375 : dirship->primtype == GTYPE_MEDIUM
377 : dirship->primtype == GTYPE_HEAVY ?
'H' :
'N'));
378 notify(Playernum, Governor, buf);
380 if (Shipdata[dirship->build_type][ABIL_SECONDARY] &&
381 dirship->sectype != GTYPE_NONE) {
382 sprintf(buf,
"/%lu%c", dirship->secondary,
383 (dirship->sectype == GTYPE_LIGHT
385 : dirship->sectype == GTYPE_MEDIUM
387 : dirship->sectype == GTYPE_HEAVY ?
'H' :
'N'));
388 notify(Playernum, Governor, buf);
391 sprintf(buf,
"Ship: %-16.16s\tCrew: %4d",
392 Shipnames[dirship->build_type], dirship->max_crew);
393 notify(Playernum, Governor, buf);
394 if (Shipdata[dirship->build_type][ABIL_MOUNT]) {
395 sprintf(buf,
"\t\tXtal Mount: %s\n", (dirship->mount ?
"yes" :
"no"));
396 notify(Playernum, Governor, buf);
399 sprintf(buf,
"Class: %s\t\tFuel: %4d", dirship->shipclass,
401 notify(Playernum, Governor, buf);
402 if (Shipdata[dirship->build_type][ABIL_JUMP]) {
403 sprintf(buf,
"\t\tHyperdrive: %s\n",
404 (dirship->hyper_drive.has ?
"yes" :
"no"));
405 notify(Playernum, Governor, buf);
408 sprintf(buf,
"Cost: %d r\t\tCargo: %4lu", dirship->build_cost,
409 dirship->max_resource);
410 notify(Playernum, Governor, buf);
411 if (Shipdata[dirship->build_type][ABIL_LASER]) {
412 sprintf(buf,
"\t\tCombat Lasers: %s\n",
413 (dirship->laser ?
"yes" :
"no"));
414 notify(Playernum, Governor, buf);
417 sprintf(buf,
"Mass: %.1f\t\tHanger: %4u", dirship->base_mass,
418 dirship->max_hanger);
419 notify(Playernum, Governor, buf);
420 if (Shipdata[dirship->build_type][ABIL_CEW]) {
421 sprintf(buf,
"\t\tCEW: %s\n", (dirship->cew ?
"yes" :
"no"));
422 notify(Playernum, Governor, buf);
425 sprintf(buf,
"Size: %-6d\t\tDestruct: %4d", dirship->size,
426 dirship->max_destruct);
427 notify(Playernum, Governor, buf);
428 if (Shipdata[dirship->build_type][ABIL_CEW] && dirship->cew) {
429 sprintf(buf,
"\t\t Opt Range: %4d\n", dirship->cew_range);
430 notify(Playernum, Governor, buf);
433 sprintf(buf,
"Tech: %.1f (%.1f)\tSpeed: %4d", dirship->complexity,
434 Race->tech, dirship->max_speed);
435 notify(Playernum, Governor, buf);
436 if (Shipdata[dirship->build_type][ABIL_CEW] && dirship->cew) {
437 sprintf(buf,
"\t\t Energy: %4d\n", dirship->cew);
438 notify(Playernum, Governor, buf);
442 if (Race->tech < dirship->complexity)
443 notify(Playernum, Governor,
444 "Your engineering capability is not " 445 "advanced enough to produce this " 452 auto i = get_build_type(shipc);
454 if ((!i) || ((*i == ShipType::STYPE_POD) && (!Race->pods))) {
455 g.out <<
"Illegal ship letter.\n";
458 if (Shipdata[*i][ABIL_GOD] && !Race->God) {
459 g.out <<
"Nice try!\n";
462 if (!(Shipdata[*i][ABIL_BUILD] &
463 Shipdata[ShipType::OTYPE_FACTORY][ABIL_CONSTRUCT])) {
464 g.out <<
"This kind of ship does not require a factory to construct.\n";
468 dirship->build_type = *i;
469 dirship->armor = Shipdata[*i][ABIL_ARMOR];
470 dirship->guns = GTYPE_NONE;
471 dirship->primary = Shipdata[*i][ABIL_GUNS];
472 dirship->primtype = Shipdata[*i][ABIL_PRIMARY];
473 dirship->secondary = Shipdata[*i][ABIL_GUNS];
474 dirship->sectype = Shipdata[*i][ABIL_SECONDARY];
475 dirship->max_crew = Shipdata[*i][ABIL_MAXCREW];
476 dirship->max_resource = Shipdata[*i][ABIL_CARGO];
477 dirship->max_hanger = Shipdata[*i][ABIL_HANGER];
478 dirship->max_fuel = Shipdata[*i][ABIL_FUELCAP];
479 dirship->max_destruct = Shipdata[*i][ABIL_DESTCAP];
480 dirship->max_speed = Shipdata[*i][ABIL_SPEED];
482 dirship->mount = Shipdata[*i][ABIL_MOUNT] *
Crystal(Race);
483 dirship->hyper_drive.has = Shipdata[*i][ABIL_JUMP] *
Hyper_drive(Race);
484 dirship->cloak = Shipdata[*i][ABIL_CLOAK] *
Cloak(Race);
485 dirship->laser = Shipdata[*i][ABIL_LASER] *
Laser(Race);
489 dirship->size = ship_size(*dirship);
490 dirship->complexity = complexity(*dirship);
492 sprintf(dirship->shipclass,
"mod %ld", g.shipno);
494 sprintf(buf,
"Factory designated to produce %ss.\n", Shipnames[*i]);
495 notify(Playernum, Governor, buf);
496 sprintf(buf,
"Design complexity %.1f (%.1f).\n", dirship->complexity,
498 notify(Playernum, Governor, buf);
499 if (dirship->complexity > Race->tech)
500 g.out <<
"You can't produce this design yet!\n";
502 }
else if (mode == 1) {
503 if (!dirship->build_type) {
504 g.out <<
"No ship design specified. Use 'make <ship type>' first.\n";
508 if (argv.size() < 2) {
509 g.out <<
"You have to specify the characteristic you wish to modify.\n";
513 if (argv.size() == 3)
514 value = std::stoi(argv[2]);
519 g.out <<
"That's a ridiculous setting.\n";
523 if (Shipdata[dirship->build_type][ABIL_MOD]) {
524 if (argv[1] ==
"armor") {
525 dirship->armor =
MIN(value, 100);
526 }
else if (argv[1] ==
"crew" &&
527 Shipdata[dirship->build_type][ABIL_MAXCREW]) {
528 dirship->max_crew =
MIN(value, 10000);
529 }
else if (argv[1] ==
"cargo" &&
530 Shipdata[dirship->build_type][ABIL_CARGO]) {
531 dirship->max_resource =
MIN(value, 10000);
532 }
else if (argv[1] ==
"hanger" &&
533 Shipdata[dirship->build_type][ABIL_HANGER]) {
534 dirship->max_hanger =
MIN(value, 10000);
535 }
else if (argv[1] ==
"fuel" &&
536 Shipdata[dirship->build_type][ABIL_FUELCAP]) {
537 dirship->max_fuel =
MIN(value, 10000);
538 }
else if (argv[1] ==
"destruct" &&
539 Shipdata[dirship->build_type][ABIL_DESTCAP]) {
540 dirship->max_destruct =
MIN(value, 10000);
541 }
else if (argv[1] ==
"speed" &&
542 Shipdata[dirship->build_type][ABIL_SPEED]) {
543 dirship->max_speed =
MAX(1,
MIN(value, 9));
544 }
else if (argv[1] ==
"mount" &&
545 Shipdata[dirship->build_type][ABIL_MOUNT] &&
Crystal(Race)) {
546 dirship->mount = !dirship->mount;
547 }
else if (argv[1] ==
"hyperdrive" &&
548 Shipdata[dirship->build_type][ABIL_JUMP] &&
550 dirship->hyper_drive.has = !dirship->hyper_drive.has;
551 }
else if (argv[1] ==
"primary" &&
552 Shipdata[dirship->build_type][ABIL_PRIMARY]) {
553 if (argv[2] ==
"strength") {
554 dirship->primary = std::stoi(argv[3]);
555 }
else if (argv[2] ==
"caliber") {
556 if (argv[3] ==
"light")
557 dirship->primtype = GTYPE_LIGHT;
558 else if (argv[3] ==
"medium")
559 dirship->primtype = GTYPE_MEDIUM;
560 else if (argv[3] ==
"heavy")
561 dirship->primtype = GTYPE_HEAVY;
563 g.out <<
"No such caliber.\n";
566 dirship->primtype =
MIN(Shipdata[dirship->build_type][ABIL_PRIMARY],
569 g.out <<
"No such gun characteristic.\n";
572 }
else if (argv[1] ==
"secondary" &&
573 Shipdata[dirship->build_type][ABIL_SECONDARY]) {
574 if (argv[2] ==
"strength") {
575 dirship->secondary = std::stoi(argv[3]);
576 }
else if (argv[2] ==
"caliber") {
577 if (argv[3] ==
"light")
578 dirship->sectype = GTYPE_LIGHT;
579 else if (argv[3] ==
"medium")
580 dirship->sectype = GTYPE_MEDIUM;
581 else if (argv[3] ==
"heavy")
582 dirship->sectype = GTYPE_HEAVY;
584 g.out <<
"No such caliber.\n";
587 dirship->sectype =
MIN(Shipdata[dirship->build_type][ABIL_SECONDARY],
590 g.out <<
"No such gun characteristic.\n";
593 }
else if (argv[1] ==
"cew" && Shipdata[dirship->build_type][ABIL_CEW]) {
595 g.out <<
"Your race does not understand confined energy weapons.\n";
598 if (!Shipdata[dirship->build_type][ABIL_CEW]) {
599 g.out <<
"This kind of ship cannot mount confined energy weapons.\n";
602 value = std::stoi(argv[3]);
603 if (argv[2] ==
"strength") {
604 dirship->cew = value;
605 }
else if (argv[2] ==
"range") {
606 dirship->cew_range = value;
608 g.out <<
"No such option for CEWs.\n";
611 }
else if (argv[1] ==
"laser" &&
612 Shipdata[dirship->build_type][ABIL_LASER]) {
614 g.out <<
"Your race does not understand lasers yet.\n";
617 if (Shipdata[dirship->build_type][ABIL_LASER])
618 dirship->laser = !dirship->laser;
620 g.out <<
"That ship cannot be fitted with combat lasers.\n";
624 g.out <<
"That characteristic either doesn't exist or can't be " 629 if (argv[1] ==
"hyperdrive") {
630 dirship->hyper_drive.has = !dirship->hyper_drive.has;
632 g.out <<
"You may only modify hyperdrive " 633 "installation on this kind of ship.\n";
637 g.out <<
"Sorry, but you can't modify this ship right now.\n";
641 g.out <<
"Weird error.\n";
646 if ((cost0 = cost(*dirship)) > 65535.0) {
647 g.out <<
"Woah!! YOU CHEATER!!! The max cost allowed " 648 "is 65535!!! I'm Telllllllling!!!\n";
652 dirship->build_cost = Race->God ? 0 : (
int)cost0;
653 sprintf(buf,
"The current cost of the ship is %d resources.\n",
654 dirship->build_cost);
655 notify(Playernum, Governor, buf);
656 dirship->size = ship_size(*dirship);
657 dirship->base_mass = getmass(*dirship);
658 sprintf(buf,
"The current base mass of the ship is %.1f - size is %d.\n",
659 dirship->base_mass, dirship->size);
660 notify(Playernum, Governor, buf);
661 dirship->complexity = complexity(*dirship);
663 "Ship complexity is %.1f (you have %.1f engineering technology).\n",
664 dirship->complexity, Race->tech);
665 notify(Playernum, Governor, buf);
668 dirship->size = size;
673 void build(
const command_t &argv, GameObj &g) {
674 const player_t Playernum = g.player;
675 const governor_t Governor = g.governor;
688 ScopeLevel build_level;
698 std::optional<Ship> builder;
701 if (argv.size() > 1 && argv[1][0] ==
'?') {
703 if (argv.size() == 2) {
705 g.out <<
" - Default ship parameters -\n";
707 "%1s %-15s %5s %5s %3s %4s %3s %3s %3s %4s %4s %2s %4s %4s\n",
708 "?",
"name",
"cargo",
"hang",
"arm",
"dest",
"gun",
"pri",
"sec",
709 "fuel",
"crew",
"sp",
"tech",
"cost");
710 notify(Playernum, Governor, buf);
711 Race = races[Playernum - 1];
713 ShipType i{ShipVector[j]};
714 if ((!Shipdata[i][ABIL_GOD]) || Race->God) {
715 if (Race->pods || (i != ShipType::STYPE_POD)) {
716 if (Shipdata[i][ABIL_PROGRAMMED]) {
718 "%1c %-15.15s %5ld %5ld %3ld %4ld %3ld %3ld %3ld " 719 "%4ld %4ld %2ld %4.0f %4d\n",
720 Shipltrs[i], Shipnames[i], Shipdata[i][ABIL_CARGO],
721 Shipdata[i][ABIL_HANGER], Shipdata[i][ABIL_ARMOR],
722 Shipdata[i][ABIL_DESTCAP], Shipdata[i][ABIL_GUNS],
723 Shipdata[i][ABIL_PRIMARY], Shipdata[i][ABIL_SECONDARY],
724 Shipdata[i][ABIL_FUELCAP], Shipdata[i][ABIL_MAXCREW],
725 Shipdata[i][ABIL_SPEED], (
double)Shipdata[i][ABIL_TECH],
727 notify(Playernum, Governor, buf);
735 auto i = get_build_type(argv[2][0]);
737 g.out <<
"No such ship type.\n";
738 else if (!Shipdata[*i][ABIL_PROGRAMMED])
739 g.out <<
"This ship type has not been programmed.\n";
741 if ((fd = fopen(
EXAM_FL,
"r")) ==
nullptr) {
747 for (j = 0; j <= i; j++)
748 while (fgetc(fd) !=
'~')
751 while ((c = fgetc(fd)) !=
'~') {
752 sprintf(temp,
"%c", c);
757 if (Shipdata[*i][ABIL_BUILD] & 1) {
758 sprintf(temp,
"\nCan be constructed on planet.");
762 sprintf(temp,
"\nCan be built by ");
764 if (Shipdata[*i][ABIL_BUILD] & Shipdata[j][ABIL_CONSTRUCT]) n++;
769 if (Shipdata[*i][ABIL_BUILD] & Shipdata[j][ABIL_CONSTRUCT]) {
772 sprintf(temp,
"%c, ", Shipltrs[j]);
774 sprintf(temp,
"%c and ", Shipltrs[j]);
776 sprintf(temp,
"%c ", Shipltrs[j]);
780 sprintf(temp,
"type ships.\n");
785 "\n%1s %-15s %5s %5s %3s %4s %3s %3s %3s %4s %4s %2s %4s %4s\n",
786 "?",
"name",
"cargo",
"hang",
"arm",
"dest",
"gun",
"pri",
"sec",
787 "fuel",
"crew",
"sp",
"tech",
"cost");
789 Race = races[Playernum - 1];
791 "%1c %-15.15s %5ld %5ld %3ld %4ld %3ld %3ld %3ld %4ld " 792 "%4ld %2ld %4.0f %4d\n",
793 Shipltrs[*i], Shipnames[*i], Shipdata[*i][ABIL_CARGO],
794 Shipdata[*i][ABIL_HANGER], Shipdata[*i][ABIL_ARMOR],
795 Shipdata[*i][ABIL_DESTCAP], Shipdata[*i][ABIL_GUNS],
796 Shipdata[*i][ABIL_PRIMARY], Shipdata[*i][ABIL_SECONDARY],
797 Shipdata[*i][ABIL_FUELCAP], Shipdata[*i][ABIL_MAXCREW],
798 Shipdata[*i][ABIL_SPEED], (
double)Shipdata[*i][ABIL_TECH],
801 notify(Playernum, Governor, buf);
808 if (level != ScopeLevel::LEVEL_SHIP && level != ScopeLevel::LEVEL_PLAN) {
809 g.out <<
"You must change scope to a ship or planet to build.\n";
814 Race = races[Playernum - 1];
816 std::optional<ShipType> what;
819 case ScopeLevel::LEVEL_PLAN:
821 if (argv.size() < 2) {
822 g.out <<
"Build what?\n";
825 what = get_build_type(argv[1][0]);
827 g.out <<
"No such ship type.\n";
830 if (!can_build_this(*what, *Race, buf) && !Race->God) {
831 notify(Playernum, Governor, buf);
834 if (!(Shipdata[*what][ABIL_BUILD] & 1) && !Race->God) {
835 g.out <<
"This ship cannot be built by a planet.\n";
838 if (argv.size() < 3) {
839 g.out <<
"Build where?\n";
844 g.out <<
"You can't build that here.\n";
847 sscanf(argv[2].c_str(),
"%d,%d", &x, &y);
848 if (x < 0 || x >= planet.Maxx || y < 0 || y >= planet.Maxy) {
849 g.out <<
"Illegal sector.\n";
853 if (!can_build_on_sector(*what, Race, planet, sector, x, y, buf) &&
855 notify(Playernum, Governor, buf);
858 if (!(count = getcount(argv, 4))) {
859 g.out <<
"Give a positive number of builds.\n";
862 Getship(&newship, *what, Race);
864 if ((shipcost = newship.build_cost) >
865 planet.info[Playernum - 1].resource) {
866 sprintf(buf,
"You need %dr to construct this ship.\n", shipcost);
867 notify(Playernum, Governor, buf);
872 if (Race->governor[Governor].toggle.autoload &&
873 what != ShipType::OTYPE_TRANSDEV && !Race->God)
883 case ScopeLevel::LEVEL_SHIP:
885 builder = getship(g.shipno);
887 auto test_build_level = build_at_ship(g, &*builder, &snum, &pnum);
888 if (!test_build_level) {
889 g.out <<
"You can't build here.\n";
892 build_level = test_build_level.value();
893 switch (builder->type) {
894 case ShipType::OTYPE_FACTORY:
895 if (!(count = getcount(argv, 2))) {
896 g.out <<
"Give a positive number of builds.\n";
899 if (!landed(*builder)) {
900 g.out <<
"Factories can only build when landed on a planet.\n";
903 Getfactship(&newship, &*builder);
906 case ShipType::STYPE_SHUTTLE:
907 case ShipType::STYPE_CARGO:
908 if (landed(*builder)) {
909 g.out <<
"This ships cannot build when landed.\n";
913 [[clang::fallthrough]];
917 if (argv.size() < 2) {
918 g.out <<
"Build what?\n";
921 if ((what = get_build_type(argv[1][0])) < 0) {
922 g.out <<
"No such ship type.\n";
925 if (!can_build_on_ship(*what, Race, &*builder, buf)) {
926 notify(Playernum, Governor, buf);
929 if (!(count = getcount(argv, 3))) {
930 g.out <<
"Give a positive number of builds.\n";
933 Getship(&newship, *what, Race);
936 if ((tech = builder->type == ShipType::OTYPE_FACTORY
937 ? complexity(*builder)
938 : Shipdata[*what][ABIL_TECH]) > Race->tech &&
941 "You are not advanced enough to build this ship.\n%.1f " 942 "enginering technology needed. You have %.1f.\n",
944 notify(Playernum, Governor, buf);
947 if (outside && build_level == ScopeLevel::LEVEL_PLAN) {
949 if (builder->type == ShipType::OTYPE_FACTORY) {
951 g.out <<
"You can't build that here.\n";
956 what = builder->build_type;
958 if (!can_build_on_sector(*what, Race, planet, sector, x, y,
960 notify(Playernum, Governor, buf);
967 switch (builder->type) {
968 case ShipType::OTYPE_FACTORY:
969 if ((shipcost = newship.build_cost) >
970 planet.info[Playernum - 1].resource) {
971 sprintf(buf,
"You need %dr to construct this ship.\n", shipcost);
972 notify(Playernum, Governor, buf);
975 create_ship_by_planet(Playernum, Governor, Race, &newship, &planet,
977 if (Race->governor[Governor].toggle.autoload &&
978 what != ShipType::OTYPE_TRANSDEV && !Race->God) {
979 autoload_at_planet(Playernum, &newship, &planet, sector,
980 &load_crew, &load_fuel);
986 case ShipType::STYPE_SHUTTLE:
987 case ShipType::STYPE_CARGO:
988 if (builder->resource < (shipcost = newship.build_cost)) {
989 sprintf(buf,
"You need %dr to construct the ship.\n", shipcost);
990 notify(Playernum, Governor, buf);
993 create_ship_by_ship(Playernum, Governor, Race, 1, &planet, &newship,
995 if (Race->governor[Governor].toggle.autoload &&
996 what != ShipType::OTYPE_TRANSDEV && !Race->God)
997 autoload_at_ship(&newship, &*builder, &load_crew, &load_fuel);
1004 if (builder->hanger + ship_size(newship) > builder->max_hanger) {
1005 g.out <<
"Not enough hanger space.\n";
1008 if (builder->resource < (shipcost = newship.build_cost)) {
1009 sprintf(buf,
"You need %dr to construct the ship.\n", shipcost);
1010 notify(Playernum, Governor, buf);
1013 create_ship_by_ship(Playernum, Governor, Race, 0,
nullptr, &newship,
1015 if (Race->governor[Governor].toggle.autoload &&
1016 what != ShipType::OTYPE_TRANSDEV && !Race->God)
1017 autoload_at_ship(&newship, &*builder, &load_crew, &load_fuel);
1036 case ScopeLevel::LEVEL_PLAN:
1040 case ScopeLevel::LEVEL_SHIP:
1041 if (outside)
switch (build_level) {
1042 case ScopeLevel::LEVEL_PLAN:
1044 if (landed(*builder)) {
1048 case ScopeLevel::LEVEL_STAR:
1051 case ScopeLevel::LEVEL_UNIV:
1067 static int getcount(
const command_t &argv,
const size_t elem) {
1068 int count = argv.size() > elem ? std::stoi(argv[elem]) : 1;
1069 if (count <= 0) count = 0;
1074 const Planet &planet) {
1075 player_t Playernum = g.player;
1076 governor_t Governor = g.governor;
1077 if (planet.slaved_to && planet.slaved_to != Playernum) {
1078 sprintf(buf,
"This planet is enslaved by player %d.\n", planet.slaved_to);
1079 notify(Playernum, Governor, buf);
1082 if (Governor && star->governor[Playernum - 1] != Governor) {
1083 g.out <<
"You are not authorized in this system.\n";
1090 for (
int i = 0; i < std::extent<
decltype(Shipltrs)>::value; ++i) {
1091 if (Shipltrs[i] == shipc)
return ShipType{i};
1098 if (what == ShipType::STYPE_POD && !race.pods) {
1099 sprintf(string,
"Only Metamorphic races can build Spore Pods.\n");
1102 if (!Shipdata[what][ABIL_PROGRAMMED]) {
1103 sprintf(string,
"This ship type has not been programmed.\n");
1106 if (Shipdata[what][ABIL_GOD] && !race.God) {
1107 sprintf(string,
"Only Gods can build this type of ship.\n");
1110 if (what == ShipType::OTYPE_VN && !
Vn(&race)) {
1111 sprintf(string,
"You have not discovered VN technology.\n");
1114 if (what == ShipType::OTYPE_TRANSDEV && !
Avpm(&race)) {
1115 sprintf(string,
"You have not discovered AVPM technology.\n");
1118 if (Shipdata[what][ABIL_TECH] > race.tech && !race.God) {
1120 "You are not advanced enough to build this ship.\n%.1f " 1121 "enginering technology needed. You have %.1f.\n",
1122 (
double)Shipdata[what][ABIL_TECH], race.tech);
1130 if (!(Shipdata[what][ABIL_BUILD] & Shipdata[builder->type][ABIL_CONSTRUCT]) &&
1132 sprintf(string,
"This ship type cannot be built by a %s.\n",
1133 Shipnames[builder->type]);
1134 sprintf(temp,
"Use 'build ? %c' to find out where it can be built.\n",
1136 strcat(string, temp);
1143 int *snum,
int *pnum) {
1144 player_t Playernum = g.player;
1145 governor_t Governor = g.governor;
1146 if (testship(Playernum, Governor, *builder))
return {};
1147 if (!Shipdata[builder->type][ABIL_CONSTRUCT]) {
1148 g.out <<
"This ship cannot construct other ships.\n";
1151 if (!builder->popn) {
1152 g.out <<
"This ship has no crew.\n";
1156 g.out <<
"Undock this ship first.\n";
1159 if (builder->damage) {
1160 g.out <<
"This ship is damaged and cannot build.\n";
1163 if (builder->type == ShipType::OTYPE_FACTORY && !builder->on) {
1164 g.out <<
"This factory is not online.\n";
1167 if (builder->type == ShipType::OTYPE_FACTORY && !landed(*builder)) {
1168 g.out <<
"Factories must be landed on a planet.\n";
1171 *snum = builder->storbits;
1172 *pnum = builder->pnumorbits;
1173 return (builder->whatorbits);
1177 Sector §or,
int *crew,
double *fuel) {
1178 *crew =
MIN(s->max_crew, sector.popn);
1179 *fuel =
MIN((
double)s->max_fuel, (
double)planet->info[Playernum - 1].fuel);
1180 sector.popn -= *crew;
1181 if (!sector.popn && !sector.troops) sector.owner = 0;
1182 planet->info[Playernum - 1].fuel -= (
int)(*fuel);
1186 *crew =
MIN(s->max_crew, b->popn);
1187 *fuel =
MIN((
double)s->max_fuel, (
double)b->fuel);
1193 double load_fuel,
int load_crew) {
1194 player_t Playernum = g.player;
1195 governor_t Governor = g.governor;
1196 newship->speed = newship->max_speed;
1197 newship->owner = Playernum;
1198 newship->governor = Governor;
1199 newship->fuel = Race->God ? newship->max_fuel : load_fuel;
1200 newship->popn = Race->God ? newship->max_crew : load_crew;
1201 newship->troops = 0;
1202 newship->resource = Race->God ? newship->max_resource : 0;
1203 newship->destruct = Race->God ? newship->max_destruct : 0;
1204 newship->crystals = 0;
1205 newship->hanger = 0;
1206 newship->mass = newship->base_mass + (
double)newship->popn * Race->mass +
1211 newship->active = 1;
1212 newship->protect.self = newship->guns ? 1 : 0;
1213 newship->hyper_drive.on = 0;
1214 newship->hyper_drive.ready = 0;
1215 newship->hyper_drive.charge = 0;
1216 newship->mounted = Race->God ? newship->mount : 0;
1218 newship->cloaked = 0;
1219 newship->fire_laser = 0;
1222 newship->damage = Race->God ? 0 : Shipdata[newship->type][ABIL_DAMAGE];
1223 newship->retaliate = newship->primary;
1226 switch (newship->type) {
1227 case ShipType::OTYPE_VN:
1228 newship->special.mind.busy = 1;
1229 newship->special.mind.progenitor = Playernum;
1230 newship->special.mind.generation = 1;
1231 newship->special.mind.target = 0;
1232 newship->special.mind.tampered = 0;
1234 case ShipType::STYPE_MINE:
1235 newship->special.trigger.radius = 100;
1236 g.out <<
"Mine disarmed.\nTrigger radius set at 100.\n";
1238 case ShipType::OTYPE_TRANSDEV:
1239 newship->special.transport.target = 0;
1241 g.out <<
"Receive OFF. Change with order.\n";
1243 case ShipType::OTYPE_AP:
1244 g.out <<
"Processor OFF.\n";
1246 case ShipType::OTYPE_STELE:
1247 case ShipType::OTYPE_GTELE:
1248 sprintf(buf,
"Telescope range is %.2f.\n",
1250 notify(Playernum, Governor, buf);
1255 if (newship->damage) {
1257 "Warning: This ship is constructed with a %d%% damage level.\n",
1259 notify(Playernum, Governor, buf);
1260 if (!Shipdata[newship->type][ABIL_REPAIR] && newship->max_crew)
1261 notify(Playernum, Governor,
1262 "It will need resources to become fully operational.\n");
1264 if (Shipdata[newship->type][ABIL_REPAIR] && newship->max_crew)
1265 g.out <<
"This ship does not need resources to repair.\n";
1266 if (newship->type == ShipType::OTYPE_FACTORY)
1268 <<
"This factory may not begin repairs until it has been activated.\n";
1269 if (!newship->max_crew)
1270 g.out <<
"This ship is robotic, and may not repair itself.\n";
1271 sprintf(buf,
"Loaded with %d crew and %.1f fuel.\n", load_crew, load_fuel);
1272 notify(Playernum, Governor, buf);
1276 Ship *newship, Planet *planet,
int snum,
1277 int pnum,
int x,
int y) {
1280 newship->tech = Race->tech;
1281 newship->xpos = Stars[snum]->xpos + planet->xpos;
1282 newship->ypos = Stars[snum]->ypos + planet->ypos;
1283 newship->land_x = x;
1284 newship->land_y = y;
1285 sprintf(newship->shipclass, (((newship->type == ShipType::OTYPE_TERRA) ||
1286 (newship->type == ShipType::OTYPE_PLOW))
1289 newship->whatorbits = ScopeLevel::LEVEL_PLAN;
1290 newship->whatdest = ScopeLevel::LEVEL_PLAN;
1291 newship->deststar = snum;
1292 newship->destpnum = pnum;
1293 newship->storbits = snum;
1294 newship->pnumorbits = pnum;
1295 newship->docked = 1;
1296 planet->info[Playernum - 1].resource -= newship->build_cost;
1300 newship->number = shipno;
1301 newship->owner = Playernum;
1302 newship->governor = Governor;
1304 insert_sh_plan(planet, newship);
1305 if (newship->type == ShipType::OTYPE_TOXWC) {
1306 sprintf(buf,
"Toxin concentration on planet was %d%%,",
1307 planet->conditions[
TOXIC]);
1308 notify(Playernum, Governor, buf);
1310 newship->special.waste.toxic =
TOXMAX;
1312 newship->special.waste.toxic = planet->conditions[
TOXIC];
1313 planet->conditions[
TOXIC] -= newship->special.waste.toxic;
1314 sprintf(buf,
" now %d%%.\n", planet->conditions[
TOXIC]);
1315 notify(Playernum, Governor, buf);
1317 sprintf(buf,
"%s built at a cost of %d resources.\n",
1318 ship_to_string(*newship).c_str(), newship->build_cost);
1319 notify(Playernum, Governor, buf);
1320 sprintf(buf,
"Technology %.1f.\n", newship->tech);
1321 notify(Playernum, Governor, buf);
1322 sprintf(buf,
"%s is on sector %d,%d.\n", ship_to_string(*newship).c_str(),
1323 newship->land_x, newship->land_y);
1324 notify(Playernum, Governor, buf);
1328 int outside, Planet *planet, Ship *newship,
1335 newship->number = shipno;
1336 newship->owner = Playernum;
1337 newship->governor = Governor;
1339 newship->whatorbits = builder->whatorbits;
1340 newship->whatdest = ScopeLevel::LEVEL_UNIV;
1341 newship->deststar = builder->deststar;
1342 newship->destpnum = builder->destpnum;
1343 newship->storbits = builder->storbits;
1344 newship->pnumorbits = builder->pnumorbits;
1345 newship->docked = 0;
1346 switch (builder->whatorbits) {
1347 case ScopeLevel::LEVEL_PLAN:
1348 insert_sh_plan(planet, newship);
1350 case ScopeLevel::LEVEL_STAR:
1351 insert_sh_star(Stars[builder->storbits], newship);
1353 case ScopeLevel::LEVEL_UNIV:
1354 insert_sh_univ(&Sdata, newship);
1356 case ScopeLevel::LEVEL_SHIP:
1361 newship->whatorbits = ScopeLevel::LEVEL_SHIP;
1362 newship->whatdest = ScopeLevel::LEVEL_SHIP;
1363 newship->deststar = builder->deststar;
1364 newship->destpnum = builder->destpnum;
1365 newship->destshipno = builder->number;
1366 newship->storbits = builder->storbits;
1367 newship->pnumorbits = builder->pnumorbits;
1368 newship->docked = 1;
1369 insert_sh_ship(newship, builder);
1371 newship->tech = Race->tech;
1372 newship->xpos = builder->xpos;
1373 newship->ypos = builder->ypos;
1374 newship->land_x = builder->land_x;
1375 newship->land_y = builder->land_y;
1376 sprintf(newship->shipclass, (((newship->type == ShipType::OTYPE_TERRA) ||
1377 (newship->type == ShipType::OTYPE_PLOW))
1380 builder->resource -= newship->build_cost;
1382 sprintf(buf,
"%s built at a cost of %d resources.\n",
1383 ship_to_string(*newship).c_str(), newship->build_cost);
1384 notify(Playernum, Governor, buf);
1385 sprintf(buf,
"Technology %.1f.\n", newship->tech);
1386 notify(Playernum, Governor, buf);
1389 static void Getship(Ship *s, ShipType i, Race *r) {
1390 bzero((
char *)s,
sizeof(Ship));
1392 s->armor = Shipdata[i][ABIL_ARMOR];
1393 s->guns = Shipdata[i][ABIL_PRIMARY] ?
PRIMARY : GTYPE_NONE;
1394 s->primary = Shipdata[i][ABIL_GUNS];
1395 s->primtype = Shipdata[i][ABIL_PRIMARY];
1396 s->secondary = Shipdata[i][ABIL_GUNS];
1397 s->sectype = Shipdata[i][ABIL_SECONDARY];
1398 s->max_crew = Shipdata[i][ABIL_MAXCREW];
1399 s->max_resource = Shipdata[i][ABIL_CARGO];
1400 s->max_hanger = Shipdata[i][ABIL_HANGER];
1401 s->max_destruct = Shipdata[i][ABIL_DESTCAP];
1402 s->max_fuel = Shipdata[i][ABIL_FUELCAP];
1403 s->max_speed = Shipdata[i][ABIL_SPEED];
1405 s->mount = r->God ? Shipdata[i][ABIL_MOUNT] : 0;
1406 s->hyper_drive.has = r->God ? Shipdata[i][ABIL_JUMP] : 0;
1408 s->laser = r->God ? Shipdata[i][ABIL_LASER] : 0;
1411 s->size = ship_size(*s);
1412 s->base_mass = getmass(*s);
1413 s->mass = getmass(*s);
1414 s->build_cost = r->God ? 0 : (
int)cost(*s);
1415 if (s->type == ShipType::OTYPE_VN || s->type == ShipType::OTYPE_BERS)
1416 s->special.mind.progenitor = r->Playernum;
1420 bzero((
char *)s,
sizeof(Ship));
1421 s->type = b->build_type;
1422 s->armor = b->armor;
1423 s->primary = b->primary;
1424 s->primtype = b->primtype;
1425 s->secondary = b->secondary;
1426 s->sectype = b->sectype;
1427 s->guns = s->primary ?
PRIMARY : GTYPE_NONE;
1428 s->max_crew = b->max_crew;
1429 s->max_resource = b->max_resource;
1430 s->max_hanger = b->max_hanger;
1431 s->max_destruct = b->max_destruct;
1432 s->max_fuel = b->max_fuel;
1433 s->max_speed = b->max_speed;
1434 s->build_type = b->build_type;
1435 s->build_cost = b->build_cost;
1436 s->mount = b->mount;
1437 s->hyper_drive.has = b->hyper_drive.has;
1439 s->laser = b->laser;
1441 s->cew_range = b->cew_range;
1442 s->size = ship_size(*s);
1443 s->base_mass = getmass(*s);
1444 s->mass = getmass(*s);
1451 return ((
int)cost(s));
1455 void sell(
const command_t &argv, GameObj &g) {
1456 const player_t Playernum = g.player;
1457 const governor_t Governor = g.governor;
1468 if (g.level != ScopeLevel::LEVEL_PLAN) {
1469 g.out <<
"You have to be in a planet scope to sell.\n";
1474 if (argv.size() < 3) {
1475 g.out <<
"Syntax: sell <commodity> <amount>\n";
1478 if (Governor && Stars[snum]->governor[Playernum - 1] != Governor) {
1479 g.out <<
"You are not authorized in this system.\n";
1482 Race = races[Playernum - 1];
1484 g.out <<
"Guest races can't sell anything.\n";
1488 commod = argv[1][0];
1489 amount = std::stoi(argv[2]);
1491 g.out <<
"Try using positive values.\n";
1494 APcount =
MIN(APcount, amount);
1495 if (!
enufAP(Playernum
, Governor
, Stars[snum]->AP[Playernum - 1]
, APcount
))
1499 if (p.slaved_to && p.slaved_to != Playernum) {
1500 sprintf(buf,
"This planet is enslaved to player %d.\n", p.slaved_to);
1501 notify(Playernum, Governor, buf);
1506 Shiplist shiplist(p.ships);
1507 for (
auto s : shiplist) {
1508 if (s.alive && (s.owner == Playernum) && !s.damage &&
1509 Shipdata[s.type][ABIL_PORT]) {
1515 g.out <<
"You don't have an undamaged space port or government center " 1521 if (!p.info[Playernum - 1].resource) {
1522 g.out <<
"You don't have any resources here to sell!\n";
1525 amount =
MIN(amount, p.info[Playernum - 1].resource);
1526 p.info[Playernum - 1].resource -= amount;
1530 if (!p.info[Playernum - 1].destruct) {
1531 g.out <<
"You don't have any destruct here to sell!\n";
1534 amount =
MIN(amount, p.info[Playernum - 1].destruct);
1535 p.info[Playernum - 1].destruct -= amount;
1539 if (!p.info[Playernum - 1].fuel) {
1540 g.out <<
"You don't have any fuel here to sell!\n";
1543 amount =
MIN(amount, p.info[Playernum - 1].fuel);
1544 p.info[Playernum - 1].fuel -= amount;
1548 if (!p.info[Playernum - 1].crystals) {
1549 g.out <<
"You don't have any crystals here to sell!\n";
1552 amount =
MIN(amount, p.info[Playernum - 1].crystals);
1553 p.info[Playernum - 1].crystals -= amount;
1557 g.out <<
"Permitted commodities are r, d, f, and x.\n";
1561 c.owner = Playernum;
1562 c.governor = Governor;
1569 c.planet_from = pnum;
1575 sprintf(buf,
"Lot #%d - %d units of %s.\n", commodno, amount, Commod[item]);
1576 notify(Playernum, Governor, buf);
1577 sprintf(buf,
"Lot #%d - %d units of %s for sale by %s [%d].\n", commodno,
1578 amount, Commod[item], races[Playernum - 1]->name, Playernum);
1580 for (player_t i = 1; i <= Num_races; i++) notify_race(i, buf);
1586 void bid(
const command_t &argv, GameObj &g) {
1587 const player_t Playernum = g.player;
1588 const governor_t Governor = g.governor;
1602 if (argv.size() == 1) {
1604 notify(Playernum, Governor,
1605 "+++ Galactic Bloodshed Commodities Market +++\n\n");
1606 notify(Playernum, Governor,
1607 " Lot Stock Type Owner Bidder Amount " 1608 "Cost/Unit Ship Dest\n");
1611 if (c->owner && c->amount) {
1612 rate = (
double)c->bid / (
double)c->amount;
1613 if (c->bidder == Playernum)
1614 sprintf(temp,
"%4.4s/%-4.4s", Stars[c->star_to]->name,
1615 Stars[c->star_to]->pnames[c->planet_to]);
1619 buf,
" %4d%c%5lu%10s%7d%8d%8ld%10.2f%8d %10s\n", i,
1620 c->deliver ?
'*' :
' ', c->amount, Commod[c->type], c->owner,
1621 c->bidder, c->bid, rate,
1624 notify(Playernum, Governor, buf);
1628 }
else if (argv.size() == 2) {
1630 commod = argv[1][0];
1645 g.out <<
"No such type of commodity.\n";
1648 g.out <<
"+++ Galactic Bloodshed Commodities Market +++\n\n";
1649 g.out <<
" Lot Stock Type Owner Bidder Amount " 1650 "Cost/Unit Ship Dest\n";
1653 if (c->owner && c->amount && (c->type == item)) {
1654 rate = (
double)c->bid / (
double)c->amount;
1655 if (c->bidder == Playernum)
1656 sprintf(temp,
"%4.4s/%-4.4s", Stars[c->star_to]->name,
1657 Stars[c->star_to]->pnames[c->planet_to]);
1661 buf,
" %4d%c%5lu%10s%7d%8d%8ld%10.2f%8d %10s\n", i,
1662 c->deliver ?
'*' :
' ', c->amount, Commod[c->type], c->owner,
1663 c->bidder, c->bid, rate,
1666 notify(Playernum, Governor, buf);
1671 if (g.level != ScopeLevel::LEVEL_PLAN) {
1672 g.out <<
"You have to be in a planet scope to buy.\n";
1677 if (Governor && Stars[snum]->governor[Playernum - 1] != Governor) {
1678 g.out <<
"You are not authorized in this system.\n";
1683 if (p.slaved_to && p.slaved_to != Playernum) {
1684 sprintf(buf,
"This planet is enslaved to player %d.\n", p.slaved_to);
1685 notify(Playernum, Governor, buf);
1689 Shiplist shiplist(p.ships);
1691 for (
auto s : shiplist) {
1692 if (s.alive && (s.owner == Playernum) && !s.damage &&
1693 Shipdata[s.type][ABIL_PORT]) {
1699 g.out <<
"You don't have an undamaged space port or " 1700 "government center here.\n";
1704 lot = std::stoi(argv[1]);
1705 money_t bid0 = std::stoi(argv[2]);
1707 g.out <<
"Illegal lot number.\n";
1712 g.out <<
"No such lot for sale.\n";
1716 if (c->owner == g.player &&
1717 (c->star_from != g.snum || c->planet_from != g.pnum)) {
1718 g.out <<
"You can only set a minimum price for your " 1719 "lot from the location it was sold.\n";
1723 money_t minbid = (
int)((
double)c->bid * (1.0 +
UP_BID));
1724 if (bid0 < minbid) {
1725 sprintf(buf,
"You have to bid more than %ld.\n", minbid);
1726 notify(Playernum, Governor, buf);
1730 Race = races[Playernum - 1];
1732 g.out <<
"Guest races cannot bid.\n";
1736 if (bid0 > Race->governor[Governor].money) {
1737 g.out <<
"Sorry, no buying on credit allowed.\n";
1744 "The bid on lot #%d (%lu %s) has been upped to %ld by %s [%d].\n",
1745 lot, c->amount, Commod[c->type], bid0, Race->name, Playernum);
1746 notify((
int)c->bidder, (
int)c->bidder_gov, buf);
1749 c->bidder = Playernum;
1750 c->bidder_gov = Governor;
1752 c->planet_to = pnum;
1758 "There will be an additional %d charged to you for shipping costs.\n",
1760 notify(Playernum, Governor, buf);
1762 g.out <<
"Bid accepted.\n";
1772 *dist = sqrt(
Distsq(Stars[to]->xpos, Stars[to]->ypos, Stars[from]->xpos,
1773 Stars[from]->ypos));
1775 junk = (
int)(*dist / 10000.0);
1780 fcost = factor * (
double)value;
#define Distsq(x1, y1, x2, y2)
void post(const char *origmsg, int type)
static int can_build_at_planet(GameObj &, startype *, const Planet &)
static void Getfactship(Ship *, Ship *)
void bid(const command_t &argv, GameObj &g)
int Shipcost(ShipType i, Race *r)
Planet getplanet(const starnum_t star, const planetnum_t pnum)
static std::optional< ShipType > get_build_type(const char)
bool can_build_on_sector(const int what, const racetype *Race, const Planet &planet, const Sector §or, const int x, const int y, char *string)
void putsector(const Sector &s, const Planet &p, const int x, const int y)
void sell(const command_t &argv, GameObj &g)
static void autoload_at_planet(int, Ship *, Planet *, Sector &, int *, double *)
void build(const command_t &argv, GameObj &g)
void make_mod(const command_t &argv, GameObj &g)
void upgrade(const command_t &argv, GameObj &g)
static void initialize_new_ship(GameObj &g, racetype *Race, Ship *newship, double load_fuel, int load_crew)
void putcommod(commodtype *c, int commodnum)
void deductAPs(const player_t Playernum, const governor_t Governor, unsigned int n, starnum_t snum, int sdata)
int enufAP(int Playernum, int Governor, unsigned short AP, int x)
static void create_ship_by_planet(int Playernum, int Governor, racetype *Race, Ship *newship, Planet *planet, int snum, int pnum, int x, int y)
static void Getship(Ship *, ShipType, Race *)
void putstar(startype *s, starnum_t snum)
static void create_ship_by_ship(int Playernum, int Governor, racetype *Race, int outside, Planet *planet, Ship *newship, Ship *builder)
int shipping_cost(int to, int from, double *dist, int value)
void putplanet(const Planet &p, startype *star, const int pnum)
static void autoload_at_ship(Ship *, Ship *, int *, double *)
static int getcount(const command_t &, const size_t)
int getcommod(commodtype **c, commodnum_t commodnum)
void putsdata(struct stardata *S)
static int can_build_on_ship(int what, racetype *Race, Ship *builder, char *string)
static bool can_build_this(const ShipType, const Race &, char *)
double tele_range(int, double)
static std::optional< ScopeLevel > build_at_ship(GameObj &, Ship *, int *, int *)
Sector getsector(const Planet &p, const int x, const int y)