00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <config.h>
00036
00037 #include <limits.h>
00038 #include "commands.h"
00039 #include "game.h"
00040 #include "land.h"
00041 #include "lost.h"
00042 #include "map.h"
00043 #include "nuke.h"
00044 #include "optlist.h"
00045 #include "path.h"
00046 #include "plague.h"
00047 #include "plane.h"
00048 #include "ship.h"
00049 #include "treaty.h"
00050
00051 static int build_nuke(struct sctstr *sp,
00052 struct nchrstr *np, short *vec, int tlev);
00053 static int build_ship(struct sctstr *sp,
00054 struct mchrstr *mp, short *vec, int tlev);
00055 static int build_land(struct sctstr *sp,
00056 struct lchrstr *lp, short *vec, int tlev);
00057 static int build_bridge(struct sctstr *sp, short *vec);
00058 static int build_tower(struct sctstr *sp, short *vec);
00059 static int build_plane(struct sctstr *sp,
00060 struct plchrstr *pp, short *vec, int tlev);
00061 static int build_can_afford(double, char *);
00062
00063
00064
00065
00066 int
00067 buil(void)
00068 {
00069 struct sctstr sect;
00070 struct nstr_sect nstr;
00071 struct natstr *natp;
00072 int rqtech;
00073 int tlev;
00074 int rlev;
00075 int type;
00076 char what;
00077 struct lchrstr *lp;
00078 struct mchrstr *mp;
00079 struct plchrstr *pp;
00080 struct nchrstr *np;
00081 char *p;
00082 int gotsect = 0;
00083 int built;
00084 int number;
00085 char buf[1024];
00086
00087 natp = getnatp(player->cnum);
00088 if ((p =
00089 getstarg(player->argp[1],
00090 "Build (ship, nuke, bridge, plane, land unit, tower)? ",
00091 buf)) == 0)
00092 return RET_SYN;
00093 what = *p;
00094
00095 if (!snxtsct(&nstr, player->argp[2])) {
00096 pr("Bad sector specification.\n");
00097 return RET_SYN;
00098 }
00099 tlev = (int)natp->nat_level[NAT_TLEV];
00100 rlev = (int)natp->nat_level[NAT_RLEV];
00101
00102 switch (what) {
00103 case 'p':
00104 p = getstarg(player->argp[3], "Plane type? ", buf);
00105 if (p == 0 || *p == 0)
00106 return RET_SYN;
00107 type = ef_elt_byname(EF_PLANE_CHR, p);
00108 if (type >= 0) {
00109 pp = &plchr[type];
00110 rqtech = pp->pl_tech;
00111 if (rqtech > tlev)
00112 type = -1;
00113 }
00114 if (type < 0) {
00115 pr("You can't build that!\n");
00116 pr("Use `show plane build %d' to show types you can build.\n",
00117 tlev);
00118 return RET_FAIL;
00119 }
00120 break;
00121 case 's':
00122 p = getstarg(player->argp[3], "Ship type? ", buf);
00123 if (p == 0 || *p == 0)
00124 return RET_SYN;
00125 type = ef_elt_byname(EF_SHIP_CHR, p);
00126 if (type >= 0) {
00127 mp = &mchr[type];
00128 rqtech = mp->m_tech;
00129 if (rqtech > tlev)
00130 type = -1;
00131 if ((mp->m_flags & M_TRADE) && !opt_TRADESHIPS)
00132 type = -1;
00133 }
00134 if (type < 0) {
00135 pr("You can't build that!\n");
00136 pr("Use `show ship build %d' to show types you can build.\n",
00137 tlev);
00138 return RET_FAIL;
00139 }
00140 break;
00141 case 'l':
00142 p = getstarg(player->argp[3], "Land unit type? ", buf);
00143 if (p == 0 || *p == 0)
00144 return RET_SYN;
00145 type = ef_elt_byname(EF_LAND_CHR, p);
00146 if (type >= 0) {
00147 lp = &lchr[type];
00148 rqtech = lp->l_tech;
00149 if (rqtech > tlev)
00150 type = -1;
00151 if ((lp->l_flags & L_SPY) && !opt_LANDSPIES)
00152 type = -1;
00153 }
00154 if (type < 0) {
00155 pr("You can't build that!\n");
00156 pr("Use `show land build %d' to show types you can build.\n",
00157 tlev);
00158 return RET_FAIL;
00159 }
00160 break;
00161 case 'b':
00162 if (natp->nat_level[NAT_TLEV] + 0.005 < buil_bt) {
00163 pr("Building a span requires a tech of %.0f\n", buil_bt);
00164 return RET_FAIL;
00165 }
00166 break;
00167 case 't':
00168 if (!opt_BRIDGETOWERS) {
00169 pr("Bridge tower building is disabled.\n");
00170 return RET_FAIL;
00171 }
00172 if (natp->nat_level[NAT_TLEV] + 0.005 < buil_tower_bt) {
00173 pr("Building a tower requires a tech of %.0f\n",
00174 buil_tower_bt);
00175 return RET_FAIL;
00176 }
00177 break;
00178 case 'n':
00179 if (!ef_nelem(EF_NUKE_CHR)) {
00180 pr("There are no nukes in this game.\n");
00181 return RET_FAIL;
00182 }
00183 p = getstarg(player->argp[3], "Nuke type? ", buf);
00184 if (p == 0 || *p == 0)
00185 return RET_SYN;
00186 type = ef_elt_byname(EF_NUKE_CHR, p);
00187 if (type >= 0) {
00188 np = &nchr[type];
00189 rqtech = np->n_tech;
00190 if (rqtech > tlev
00191 || (drnuke_const > MIN_DRNUKE_CONST &&
00192 np->n_tech * drnuke_const > rlev))
00193 type = -1;
00194 }
00195 if (type < 0) {
00196 int tt = tlev;
00197 if (drnuke_const > MIN_DRNUKE_CONST)
00198 tt = (tlev < (rlev / drnuke_const) ? (int)tlev :
00199 (int)(rlev / drnuke_const));
00200 pr("You can't build that!\n");
00201 pr("Use `show nuke build %d' to show types you can build.\n",
00202 tt);
00203 return RET_FAIL;
00204 }
00205 break;
00206 default:
00207 pr("You can't build that!\n");
00208 return RET_SYN;
00209 }
00210
00211 number = 1;
00212 if (what != 'b' && what != 't') {
00213 if (player->argp[4]) {
00214 number = atoi(player->argp[4]);
00215 if (number > 20) {
00216 char bstr[80];
00217 sprintf(bstr,
00218 "Are you sure that you want to build %s of them? ",
00219 player->argp[4]);
00220 p = getstarg(player->argp[6], bstr, buf);
00221 if (p == 0 || *p != 'y')
00222 return RET_SYN;
00223 }
00224 }
00225 }
00226
00227 if (what != 'b' && what != 'n' && what != 't') {
00228 if (player->argp[5]) {
00229 tlev = atoi(player->argp[5]);
00230 if (tlev > natp->nat_level[NAT_TLEV] && !player->god) {
00231 pr("Your tech level is only %d.\n",
00232 (int)natp->nat_level[NAT_TLEV]);
00233 return RET_FAIL;
00234 }
00235 if (rqtech > tlev) {
00236 pr("Required tech is %d.\n", rqtech);
00237 return RET_FAIL;
00238 }
00239 pr("building with tech level %d.\n", tlev);
00240 }
00241 }
00242
00243 while (number-- > 0) {
00244 while (nxtsct(&nstr, §)) {
00245 gotsect++;
00246 if (!player->owner)
00247 continue;
00248 switch (what) {
00249 case 'l':
00250 built = build_land(§, lp, sect.sct_item, tlev);
00251 break;
00252 case 's':
00253 built = build_ship(§, mp, sect.sct_item, tlev);
00254 break;
00255 case 'b':
00256 built = build_bridge(§, sect.sct_item);
00257 break;
00258 case 't':
00259 built = build_tower(§, sect.sct_item);
00260 break;
00261 case 'n':
00262 built = build_nuke(§, np, sect.sct_item, tlev);
00263 break;
00264 case 'p':
00265 built = build_plane(§, pp, sect.sct_item, tlev);
00266 break;
00267 default:
00268 CANT_REACH();
00269 return RET_FAIL;
00270 }
00271 if (built) {
00272 putsect(§);
00273 }
00274 }
00275 snxtsct_rewind(&nstr);
00276 }
00277 if (!gotsect) {
00278 pr("Bad sector specification.\n");
00279 }
00280 return RET_OK;
00281 }
00282
00283 static int
00284 build_ship(struct sctstr *sp, struct mchrstr *mp, short *vec, int tlev)
00285 {
00286 struct shpstr ship;
00287 struct nstr_item nstr;
00288 int avail, i;
00289 double cost;
00290 double eff = SHIP_MINEFF / 100.0;
00291 int lcm, hcm;
00292 int freeship = 0;
00293
00294 hcm = roundavg(mp->m_hcm * eff);
00295 lcm = roundavg(mp->m_lcm * eff);
00296
00297 if (sp->sct_type != SCT_HARBR) {
00298 pr("Ships must be built in harbours.\n");
00299 return 0;
00300 }
00301 if (sp->sct_effic < 60 && !player->god) {
00302 pr("Sector %s is not 60%% efficient.\n",
00303 xyas(sp->sct_x, sp->sct_y, player->cnum));
00304 return 0;
00305 }
00306 if (vec[I_LCM] < lcm || vec[I_HCM] < hcm) {
00307 pr("Not enough materials in %s\n",
00308 xyas(sp->sct_x, sp->sct_y, player->cnum));
00309 return 0;
00310 }
00311 avail = (SHP_BLD_WORK(mp->m_lcm, mp->m_hcm) * SHIP_MINEFF + 99) / 100;
00312 if (sp->sct_avail < avail) {
00313 pr("Not enough available work in %s to build a %s\n",
00314 xyas(sp->sct_x, sp->sct_y, player->cnum), mp->m_name);
00315 pr(" (%d available work required)\n", avail);
00316 return 0;
00317 }
00318 cost = mp->m_cost * SHIP_MINEFF / 100.0;
00319 if (!build_can_afford(cost, mp->m_name))
00320 return 0;
00321 if (!trechk(player->cnum, 0, NEWSHP))
00322 return 0;
00323 if (!check_sect_ok(sp))
00324 return 0;
00325 sp->sct_avail -= avail;
00326 player->dolcost += cost;
00327 snxtitem_all(&nstr, EF_SHIP);
00328 while (nxtitem(&nstr, &ship)) {
00329 if (ship.shp_own == 0) {
00330 freeship++;
00331 break;
00332 }
00333 }
00334 if (freeship == 0) {
00335 ef_extend(EF_SHIP, 50);
00336 }
00337 memset(&ship, 0, sizeof(struct shpstr));
00338 ship.shp_x = sp->sct_x;
00339 ship.shp_y = sp->sct_y;
00340 ship.shp_destx[0] = sp->sct_x;
00341 ship.shp_desty[0] = sp->sct_y;
00342 ship.shp_destx[1] = sp->sct_x;
00343 ship.shp_desty[1] = sp->sct_y;
00344 ship.shp_autonav = 0;
00345
00346 for (i = 0; i < TMAX; ++i) {
00347 ship.shp_tstart[i] = I_NONE;
00348 ship.shp_tend[i] = I_NONE;
00349 ship.shp_lstart[i] = 0;
00350 ship.shp_lend[i] = 0;
00351 }
00352 ship.shp_mission = 0;
00353 ship.shp_own = player->cnum;
00354 ship.shp_type = mp - mchr;
00355 ship.shp_effic = SHIP_MINEFF;
00356 if (opt_MOB_ACCESS) {
00357 game_tick_to_now(&ship.shp_access);
00358 ship.shp_mobil = -(etu_per_update / sect_mob_neg_factor);
00359 } else {
00360 ship.shp_mobil = 0;
00361 }
00362 ship.shp_uid = nstr.cur;
00363 ship.shp_nplane = 0;
00364 ship.shp_nland = 0;
00365 ship.shp_nxlight = 0;
00366 ship.shp_nchoppers = 0;
00367 ship.shp_fleet = 0;
00368 memset(ship.shp_item, 0, sizeof(ship.shp_item));
00369 ship.shp_pstage = PLG_HEALTHY;
00370 ship.shp_ptime = 0;
00371 ship.shp_mobquota = 0;
00372 *ship.shp_path = 0;
00373 ship.shp_follow = nstr.cur;
00374 ship.shp_name[0] = 0;
00375 ship.shp_orig_own = player->cnum;
00376 ship.shp_orig_x = sp->sct_x;
00377 ship.shp_orig_y = sp->sct_y;
00378 ship.shp_fuel = mchr[(int)ship.shp_type].m_fuelc;
00379 ship.shp_rflags = 0;
00380 memset(ship.shp_rpath, 0, sizeof(ship.shp_rpath));
00381 shp_set_tech(&ship, tlev);
00382
00383 vec[I_LCM] -= lcm;
00384 vec[I_HCM] -= hcm;
00385
00386 if (sp->sct_pstage == PLG_INFECT)
00387 ship.shp_pstage = PLG_EXPOSED;
00388 makenotlost(EF_SHIP, ship.shp_own, ship.shp_uid,
00389 ship.shp_x, ship.shp_y);
00390 putship(ship.shp_uid, &ship);
00391 pr("%s", prship(&ship));
00392 pr(" built in sector %s\n", xyas(sp->sct_x, sp->sct_y, player->cnum));
00393 return 1;
00394 }
00395
00396 static int
00397 build_land(struct sctstr *sp, struct lchrstr *lp, short *vec, int tlev)
00398 {
00399 struct lndstr land;
00400 struct nstr_item nstr;
00401 int avail;
00402 double cost;
00403 double eff = LAND_MINEFF / 100.0;
00404 int mil, lcm, hcm, gun, shell;
00405 int freeland = 0;
00406
00407 #if 0
00408 mil = roundavg(lp->l_mil * eff);
00409 shell = roundavg(lp->l_shell * eff);
00410 gun = roundavg(lp->l_gun * eff);
00411 #else
00412 mil = shell = gun = 0;
00413 #endif
00414 hcm = roundavg(lp->l_hcm * eff);
00415 lcm = roundavg(lp->l_lcm * eff);
00416
00417 if (sp->sct_type != SCT_HEADQ) {
00418 pr("Land Units must be built in headquarters.\n");
00419 return 0;
00420 }
00421 if (sp->sct_effic < 60 && !player->god) {
00422 pr("Sector %s is not 60%% efficient.\n",
00423 xyas(sp->sct_x, sp->sct_y, player->cnum));
00424 return 0;
00425 }
00426 if (vec[I_LCM] < lcm || vec[I_HCM] < hcm) {
00427 pr("Not enough materials in %s\n",
00428 xyas(sp->sct_x, sp->sct_y, player->cnum));
00429 return 0;
00430 }
00431 #if 0
00432 if (vec[I_GUN] < gun || vec[I_GUN] == 0) {
00433 pr("Not enough guns in %s\n",
00434 xyas(sp->sct_x, sp->sct_y, player->cnum));
00435 return 0;
00436 }
00437 if (vec[I_SHELL] < shell) {
00438 pr("Not enough shells in %s\n",
00439 xyas(sp->sct_x, sp->sct_y, player->cnum));
00440 return 0;
00441 }
00442 if (vec[I_MILIT] < mil) {
00443 pr("Not enough military in %s\n",
00444 xyas(sp->sct_x, sp->sct_y, player->cnum));
00445 return 0;
00446 }
00447 #endif
00448 if (!trechk(player->cnum, 0, NEWLND))
00449 return 0;
00450 if (!check_sect_ok(sp))
00451 return 0;
00452 avail = (LND_BLD_WORK(lp->l_lcm, lp->l_hcm) * LAND_MINEFF + 99) / 100;
00453 if (sp->sct_avail < avail) {
00454 pr("Not enough available work in %s to build a %s\n",
00455 xyas(sp->sct_x, sp->sct_y, player->cnum), lp->l_name);
00456 pr(" (%d available work required)\n", avail);
00457 return 0;
00458 }
00459 cost = lp->l_cost * LAND_MINEFF / 100.0;
00460 if (!build_can_afford(cost, lp->l_name))
00461 return 0;
00462 sp->sct_avail -= avail;
00463 player->dolcost += cost;
00464 snxtitem_all(&nstr, EF_LAND);
00465 while (nxtitem(&nstr, &land)) {
00466 if (land.lnd_own == 0) {
00467 freeland++;
00468 break;
00469 }
00470 }
00471 if (freeland == 0) {
00472 ef_extend(EF_LAND, 50);
00473 }
00474 memset(&land, 0, sizeof(struct lndstr));
00475 land.lnd_x = sp->sct_x;
00476 land.lnd_y = sp->sct_y;
00477 land.lnd_own = player->cnum;
00478 land.lnd_mission = 0;
00479 land.lnd_type = lp - lchr;
00480 land.lnd_effic = LAND_MINEFF;
00481 if (opt_MOB_ACCESS) {
00482 game_tick_to_now(&land.lnd_access);
00483 land.lnd_mobil = -(etu_per_update / sect_mob_neg_factor);
00484 } else {
00485 land.lnd_mobil = 0;
00486 }
00487 land.lnd_uid = nstr.cur;
00488 land.lnd_army = 0;
00489 land.lnd_flags = 0;
00490 land.lnd_ship = -1;
00491 land.lnd_land = -1;
00492 land.lnd_nland = 0;
00493 land.lnd_harden = 0;
00494 land.lnd_retreat = morale_base;
00495 land.lnd_fuel = lp->l_fuelc;
00496 land.lnd_nxlight = 0;
00497 land.lnd_rflags = 0;
00498 memset(land.lnd_rpath, 0, sizeof(land.lnd_rpath));
00499 land.lnd_rad_max = 0;
00500 memset(land.lnd_item, 0, sizeof(land.lnd_item));
00501 land.lnd_pstage = PLG_HEALTHY;
00502 land.lnd_ptime = 0;
00503 lnd_set_tech(&land, tlev);
00504
00505 vec[I_LCM] -= lcm;
00506 vec[I_HCM] -= hcm;
00507 vec[I_MILIT] -= mil;
00508 vec[I_GUN] -= gun;
00509 vec[I_SHELL] -= shell;
00510
00511 if (sp->sct_pstage == PLG_INFECT)
00512 land.lnd_pstage = PLG_EXPOSED;
00513 putland(nstr.cur, &land);
00514 makenotlost(EF_LAND, land.lnd_own, land.lnd_uid,
00515 land.lnd_x, land.lnd_y);
00516 pr("%s", prland(&land));
00517 pr(" built in sector %s\n", xyas(sp->sct_x, sp->sct_y, player->cnum));
00518 return 1;
00519 }
00520
00521 static int
00522 build_bridge(struct sctstr *sp, short *vec)
00523 {
00524 struct sctstr sect;
00525 int val;
00526 int newx, newy;
00527 int avail;
00528 int nx, ny, i, good = 0;
00529 char *p;
00530 char buf[1024];
00531
00532 if (opt_EASY_BRIDGES == 0) {
00533 if (sp->sct_type != SCT_BTOWER) {
00534 if (sp->sct_type != SCT_BHEAD)
00535 return 0;
00536 if (sp->sct_newtype != SCT_BHEAD)
00537 return 0;
00538 }
00539 }
00540
00541 if (sp->sct_effic < 60 && !player->god) {
00542 pr("Sector %s is not 60%% efficient.\n",
00543 xyas(sp->sct_x, sp->sct_y, player->cnum));
00544 return 0;
00545 }
00546
00547 if (vec[I_HCM] < buil_bh) {
00548 pr("%s only has %d unit%s of hcm,\n",
00549 xyas(sp->sct_x, sp->sct_y, player->cnum),
00550 vec[I_HCM], vec[I_HCM] > 1 ? "s" : "");
00551 pr("(a bridge span requires %d)\n", buil_bh);
00552 return 0;
00553 }
00554
00555 if (!build_can_afford(buil_bc, dchr[SCT_BSPAN].d_name))
00556 return 0;
00557 avail = (SCT_BLD_WORK(0, buil_bh) * SCT_MINEFF + 99) / 100;
00558 if (sp->sct_avail < avail) {
00559 pr("Not enough available work in %s to build a bridge\n",
00560 xyas(sp->sct_x, sp->sct_y, player->cnum));
00561 pr(" (%d available work required)\n", avail);
00562 return 0;
00563 }
00564 if (!player->argp[3]) {
00565 pr("Bridge head at %s\n",
00566 xyas(sp->sct_x, sp->sct_y, player->cnum));
00567 nav_map(sp->sct_x, sp->sct_y, 1);
00568 }
00569 p = getstarg(player->argp[3], "build span in what direction? ", buf);
00570 if (!p || !*p) {
00571 return 0;
00572 }
00573
00574 if (!check_sect_ok(sp))
00575 return 0;
00576
00577 if ((val = chkdir(*p, DIR_FIRST, DIR_LAST)) < 0) {
00578 pr("'%c' is not a valid direction...\n", *p);
00579 direrr(0, 0, 0);
00580 return 0;
00581 }
00582 newx = sp->sct_x + diroff[val][0];
00583 newy = sp->sct_y + diroff[val][1];
00584 if (getsect(newx, newy, §) == 0 || sect.sct_type != SCT_WATER) {
00585 pr("%s is not a water sector\n", xyas(newx, newy, player->cnum));
00586 return 0;
00587 }
00588 if (opt_EASY_BRIDGES) {
00589 good = 0;
00590
00591 for (i = 1; i <= 6; i++) {
00592 struct sctstr s2;
00593 nx = sect.sct_x + diroff[i][0];
00594 ny = sect.sct_y + diroff[i][1];
00595 getsect(nx, ny, &s2);
00596 if ((s2.sct_type != SCT_WATER) && (s2.sct_type != SCT_BSPAN))
00597 good = 1;
00598 }
00599 if (!good) {
00600 pr("Bridges must be built adjacent to land or bridge towers.\n");
00601 pr("That sector is not adjacent to land or a bridge tower.\n");
00602 return 0;
00603 }
00604 }
00605 sp->sct_avail -= avail;
00606 player->dolcost += buil_bc;
00607 sect.sct_type = SCT_BSPAN;
00608 sect.sct_newtype = SCT_BSPAN;
00609 sect.sct_effic = SCT_MINEFF;
00610 sect.sct_road = 0;
00611 sect.sct_rail = 0;
00612 sect.sct_defense = 0;
00613 if (opt_MOB_ACCESS) {
00614 game_tick_to_now(§.sct_access);
00615 sect.sct_mobil = -(etu_per_update / sect_mob_neg_factor);
00616 } else {
00617 sect.sct_mobil = 0;
00618 }
00619 sect.sct_mines = 0;
00620 map_set(player->cnum, sect.sct_x, sect.sct_y, dchr[SCT_BSPAN].d_mnem, 2);
00621 writemap(player->cnum);
00622 putsect(§);
00623 pr("Bridge span built over %s\n",
00624 xyas(sect.sct_x, sect.sct_y, player->cnum));
00625 vec[I_HCM] -= buil_bh;
00626 return 1;
00627 }
00628
00629 static int
00630 build_nuke(struct sctstr *sp, struct nchrstr *np, short *vec, int tlev)
00631 {
00632 struct nukstr nuke;
00633 struct nstr_item nstr;
00634 int avail;
00635 int freenuke;
00636
00637 if (sp->sct_type != SCT_NUKE && !player->god) {
00638 pr("Nuclear weapons must be built in nuclear plants.\n");
00639 return 0;
00640 }
00641 if (sp->sct_effic < 60 && !player->god) {
00642 pr("Sector %s is not 60%% efficient.\n",
00643 xyas(sp->sct_x, sp->sct_y, player->cnum));
00644 return 0;
00645 }
00646 if (vec[I_HCM] < np->n_hcm || vec[I_LCM] < np->n_lcm ||
00647 vec[I_OIL] < np->n_oil || vec[I_RAD] < np->n_rad) {
00648 pr("Not enough materials for a %s bomb in %s\n",
00649 np->n_name, xyas(sp->sct_x, sp->sct_y, player->cnum));
00650 pr("(%d hcm, %d lcm, %d oil, & %d rads).\n",
00651 np->n_hcm, np->n_lcm, np->n_oil, np->n_rad);
00652 return 0;
00653 }
00654 if (!build_can_afford(np->n_cost, np->n_name))
00655 return 0;
00656 avail = NUK_BLD_WORK(np->n_lcm, np->n_hcm, np->n_oil, np->n_rad);
00657
00658
00659
00660
00661
00662 if (sp->sct_avail < avail) {
00663 pr("Not enough available work in %s to build a %s;\n",
00664 xyas(sp->sct_x, sp->sct_y, player->cnum), np->n_name);
00665 pr(" (%d available work required)\n", avail);
00666 return 0;
00667 }
00668 if (!trechk(player->cnum, 0, NEWNUK))
00669 return 0;
00670 if (!check_sect_ok(sp))
00671 return 0;
00672 sp->sct_avail -= avail;
00673 player->dolcost += np->n_cost;
00674 snxtitem_all(&nstr, EF_NUKE);
00675 freenuke = 0;
00676 while (nxtitem(&nstr, &nuke)) {
00677 if (nuke.nuk_own == 0) {
00678 freenuke++;
00679 break;
00680 }
00681 }
00682 if (freenuke == 0) {
00683 ef_extend(EF_NUKE, 50);
00684 }
00685 memset(&nuke, 0, sizeof(struct nukstr));
00686 nuke.nuk_x = sp->sct_x;
00687 nuke.nuk_y = sp->sct_y;
00688 nuke.nuk_own = sp->sct_own;
00689 nuke.nuk_type = np - nchr;
00690 nuke.nuk_effic = 100;
00691 nuke.nuk_stockpile = 0;
00692 nuke.nuk_ship = nuke.nuk_plane = nuke.nuk_land = -1;
00693 nuke.nuk_uid = nstr.cur;
00694 nuke.nuk_tech = tlev;
00695
00696 vec[I_HCM] -= np->n_hcm;
00697 vec[I_LCM] -= np->n_lcm;
00698 vec[I_OIL] -= np->n_oil;
00699 vec[I_RAD] -= np->n_rad;
00700
00701 makenotlost(EF_NUKE, nuke.nuk_own, nuke.nuk_uid,
00702 nuke.nuk_x, nuke.nuk_y);
00703 putnuke(nuke.nuk_uid, &nuke);
00704 pr("%s created in %s\n", prnuke(&nuke),
00705 xyas(sp->sct_x, sp->sct_y, player->cnum));
00706 return 1;
00707 }
00708
00709 static int
00710 build_plane(struct sctstr *sp, struct plchrstr *pp, short *vec, int tlev)
00711 {
00712 struct plnstr plane;
00713 struct nstr_item nstr;
00714 int avail;
00715 double cost;
00716 double eff = PLANE_MINEFF / 100.0;
00717 int hcm, lcm, mil;
00718 int freeplane;
00719
00720 mil = roundavg(pp->pl_crew * eff);
00721
00722 if (mil == 0 && pp->pl_crew > 0)
00723 mil = 1;
00724 hcm = roundavg(pp->pl_hcm * eff);
00725 lcm = roundavg(pp->pl_lcm * eff);
00726 if (sp->sct_type != SCT_AIRPT && !player->god) {
00727 pr("Planes must be built in airports.\n");
00728 return 0;
00729 }
00730 if (sp->sct_effic < 60 && !player->god) {
00731 pr("Sector %s is not 60%% efficient.\n",
00732 xyas(sp->sct_x, sp->sct_y, player->cnum));
00733 return 0;
00734 }
00735 if (vec[I_LCM] < lcm || vec[I_HCM] < hcm) {
00736 pr("Not enough materials in %s\n",
00737 xyas(sp->sct_x, sp->sct_y, player->cnum));
00738 return 0;
00739 }
00740 avail = (PLN_BLD_WORK(pp->pl_lcm, pp->pl_hcm) * PLANE_MINEFF + 99) / 100;
00741 if (sp->sct_avail < avail) {
00742 pr("Not enough available work in %s to build a %s\n",
00743 xyas(sp->sct_x, sp->sct_y, player->cnum), pp->pl_name);
00744 pr(" (%d available work required)\n", avail);
00745 return 0;
00746 }
00747 cost = pp->pl_cost * PLANE_MINEFF / 100.0;
00748 if (!build_can_afford(cost, pp->pl_name))
00749 return 0;
00750 if (vec[I_MILIT] < mil || (vec[I_MILIT] == 0 && pp->pl_crew > 0)) {
00751 pr("Not enough military for crew in %s\n",
00752 xyas(sp->sct_x, sp->sct_y, player->cnum));
00753 return 0;
00754 }
00755 if (!trechk(player->cnum, 0, NEWPLN))
00756 return 0;
00757 if (!check_sect_ok(sp))
00758 return 0;
00759 sp->sct_avail -= avail;
00760 player->dolcost += cost;
00761 snxtitem_all(&nstr, EF_PLANE);
00762 freeplane = 0;
00763 while (nxtitem(&nstr, &plane)) {
00764 if (plane.pln_own == 0) {
00765 freeplane++;
00766 break;
00767 }
00768 }
00769 if (freeplane == 0) {
00770 ef_extend(EF_PLANE, 50);
00771 }
00772 memset(&plane, 0, sizeof(struct plnstr));
00773 plane.pln_x = sp->sct_x;
00774 plane.pln_y = sp->sct_y;
00775 plane.pln_own = sp->sct_own;
00776 plane.pln_type = pp - plchr;
00777 plane.pln_effic = PLANE_MINEFF;
00778 if (opt_MOB_ACCESS) {
00779 game_tick_to_now(&plane.pln_access);
00780 plane.pln_mobil = -(etu_per_update / sect_mob_neg_factor);
00781 } else {
00782 plane.pln_mobil = 0;
00783 }
00784 plane.pln_mission = 0;
00785 plane.pln_opx = 0;
00786 plane.pln_opy = 0;
00787 plane.pln_radius = 0;
00788 plane.pln_range = UCHAR_MAX;
00789 plane.pln_range_max = plane.pln_range;
00790 plane.pln_wing = 0;
00791 plane.pln_ship = -1;
00792 plane.pln_land = -1;
00793 plane.pln_uid = nstr.cur;
00794 plane.pln_nuketype = -1;
00795 plane.pln_harden = 0;
00796 plane.pln_flags = 0;
00797 pln_set_tech(&plane, tlev);
00798
00799 vec[I_LCM] -= lcm;
00800 vec[I_HCM] -= hcm;
00801 vec[I_MILIT] -= mil;
00802
00803 makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid,
00804 plane.pln_x, plane.pln_y);
00805 putplane(plane.pln_uid, &plane);
00806 pr("%s built in sector %s\n", prplane(&plane),
00807 xyas(sp->sct_x, sp->sct_y, player->cnum));
00808 return 1;
00809 }
00810
00811 static int
00812 build_tower(struct sctstr *sp, short *vec)
00813 {
00814 struct sctstr sect;
00815 int val;
00816 int newx, newy;
00817 int avail;
00818 char *p;
00819 char buf[1024];
00820 int good;
00821 int i;
00822 int nx;
00823 int ny;
00824
00825 if (sp->sct_type != SCT_BSPAN) {
00826 pr("Bridge towers can only be built from bridge spans.\n");
00827 return 0;
00828 }
00829
00830 if (sp->sct_effic < 60 && !player->god) {
00831 pr("Sector %s is not 60%% efficient.\n",
00832 xyas(sp->sct_x, sp->sct_y, player->cnum));
00833 return 0;
00834 }
00835
00836 if (vec[I_HCM] < buil_tower_bh) {
00837 pr("%s only has %d unit%s of hcm,\n",
00838 xyas(sp->sct_x, sp->sct_y, player->cnum),
00839 vec[I_HCM], vec[I_HCM] > 1 ? "s" : "");
00840 pr("(a bridge tower requires %d)\n", buil_tower_bh);
00841 return 0;
00842 }
00843
00844 if (!build_can_afford(buil_tower_bc, dchr[SCT_BTOWER].d_name))
00845 return 0;
00846 avail = (SCT_BLD_WORK(0, buil_tower_bh) * SCT_MINEFF + 99) / 100;
00847 if (sp->sct_avail < avail) {
00848 pr("Not enough available work in %s to build a bridge tower\n",
00849 xyas(sp->sct_x, sp->sct_y, player->cnum));
00850 pr(" (%d available work required)\n", avail);
00851 return 0;
00852 }
00853 if (!player->argp[3]) {
00854 pr("Building from %s\n", xyas(sp->sct_x, sp->sct_y, player->cnum));
00855 nav_map(sp->sct_x, sp->sct_y, 1);
00856 }
00857 p = getstarg(player->argp[3], "build tower in what direction? ", buf);
00858 if (!p || !*p) {
00859 return 0;
00860 }
00861
00862 if (!check_sect_ok(sp))
00863 return 0;
00864
00865 if ((val = chkdir(*p, DIR_FIRST, DIR_LAST)) < 0) {
00866 pr("'%c' is not a valid direction...\n", *p);
00867 direrr(0, 0, 0);
00868 return 0;
00869 }
00870 newx = sp->sct_x + diroff[val][0];
00871 newy = sp->sct_y + diroff[val][1];
00872 if (getsect(newx, newy, §) == 0 || sect.sct_type != SCT_WATER) {
00873 pr("%s is not a water sector\n", xyas(newx, newy, player->cnum));
00874 return 0;
00875 }
00876
00877
00878
00879 good = 0;
00880 for (i = 1; i <= 6; i++) {
00881 struct sctstr s2;
00882 nx = sect.sct_x + diroff[i][0];
00883 ny = sect.sct_y + diroff[i][1];
00884 getsect(nx, ny, &s2);
00885 if ((s2.sct_type != SCT_WATER) &&
00886 (s2.sct_type != SCT_BTOWER) && (s2.sct_type != SCT_BSPAN)) {
00887 good = 1;
00888 break;
00889 }
00890 }
00891 if (good) {
00892 pr("Bridge towers cannot be built adjacent to land.\n");
00893 pr("That sector is adjacent to land.\n");
00894 return 0;
00895 }
00896
00897 sp->sct_avail -= avail;
00898 player->dolcost += buil_tower_bc;
00899 sect.sct_type = SCT_BTOWER;
00900 sect.sct_newtype = SCT_BTOWER;
00901 sect.sct_effic = SCT_MINEFF;
00902 sect.sct_road = 0;
00903 sect.sct_rail = 0;
00904 sect.sct_defense = 0;
00905 if (opt_MOB_ACCESS) {
00906 game_tick_to_now(§.sct_access);
00907 sect.sct_mobil = -(etu_per_update / sect_mob_neg_factor);
00908 } else {
00909 sect.sct_mobil = 0;
00910 }
00911 sect.sct_mines = 0;
00912 map_set(player->cnum, sect.sct_x, sect.sct_y, dchr[SCT_BTOWER].d_mnem, 2);
00913 writemap(player->cnum);
00914 putsect(§);
00915 pr("Bridge tower built in %s\n",
00916 xyas(sect.sct_x, sect.sct_y, player->cnum));
00917 vec[I_HCM] -= buil_tower_bh;
00918 return 1;
00919 }
00920
00921 static int
00922 build_can_afford(double cost, char *what)
00923 {
00924 struct natstr *natp = getnatp(player->cnum);
00925 if (natp->nat_money < player->dolcost + cost) {
00926 pr("Not enough money left to build a %s\n", what);
00927 return 0;
00928 }
00929 return 1;
00930 }