int supp(void) { int nunits; struct nstr_item ni; struct lndstr land; if (!snxtitem(&ni, EF_LAND, player->argp[1], NULL)) return RET_SYN; nunits = 0; while (nxtitem(&ni, &land)) { if (!player->owner || land.lnd_own == 0) continue; nunits++; if (lnd_supply_all(&land)) pr("%s has supplies\n", prland(&land)); else pr("%s is out of supply\n", prland(&land)); } if (nunits == 0) { if (player->argp[1]) pr("%s: No unit(s)\n", player->argp[1]); else pr("%s: No unit(s)\n", ""); return RET_FAIL; } else pr("%d unit%s\n", nunits, splur(nunits)); return RET_OK; }
static int load_comm_land(struct sctstr *sectp, struct lndstr *lp, struct ichrstr *ich, int load_unload, int *nunitsp) { i_type item = ich->i_uid; struct lchrstr *lcp = &lchr[(int)lp->lnd_type]; int land_amt, sect_amt, move_amt; char prompt[512]; char *p; char buf[1024]; sprintf(prompt, "Number of %s to %s %s at %s? ", ich->i_name, (load_unload == UNLOAD) ? "unload from" : "load onto", prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum)); p = getstarg(player->argp[3], prompt, buf); if (!p || !*p) return RET_SYN; if (!still_ok_land(sectp, lp)) return RET_SYN; land_amt = lp->lnd_item[item]; sect_amt = sectp->sct_item[item]; move_amt = move_amount(sect_amt, land_amt, lcp->l_item[item], load_unload, atoi(p)); if (!load_comm_ok(sectp, lp->lnd_own, item, move_amt)) return RET_OK; sectp->sct_item[item] = sect_amt - move_amt; lp->lnd_item[item] = land_amt + move_amt; /* Did we put mils onto this unit? If so, reset the fortification */ if (item == I_MILIT && move_amt > 0) lp->lnd_harden = 0; if (move_amt >= 0) { pr("%d %s loaded onto %s at %s\n", move_amt, ich->i_name, prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum)); if (lp->lnd_own != player->cnum) { wu(0, lp->lnd_own, "%s loaded %d %s onto %s at %s\n", cname(player->cnum), move_amt, ich->i_name, prland(lp), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); } } else { pr("%d %s unloaded from %s at %s\n", -move_amt, ich->i_name, prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum)); if (sectp->sct_own != player->cnum) { wu(0, sectp->sct_own, "%s unloaded %d %s from %s at %s\n", cname(player->cnum), -move_amt, ich->i_name, prland(lp), xyas(lp->lnd_x, lp->lnd_y, sectp->sct_own)); } } ++*nunitsp; return 0; }
char * unit_nameof(struct empobj *gp) { switch (gp->ef_type) { case EF_SHIP: return prship((struct shpstr *)gp); case EF_PLANE: return prplane((struct plnstr *)gp); case EF_LAND: return prland((struct lndstr *)gp); case EF_NUKE: return prnuke((struct nukstr *)gp); } CANT_REACH(); return "The Beast #666"; }
int work(void) { int nunits; struct nstr_item ni; struct sctstr sect; struct lndstr land; int work_amt, eff_amt, w; char *p; char buf[1024]; double cost; struct natstr *natp = getnatp(player->cnum); if (!snxtitem(&ni, EF_LAND, player->argp[1], NULL)) return RET_SYN; p = getstarg(player->argp[2], "Amount: ", buf); if (!p || !*p) return RET_SYN; work_amt = atoi(p); if ((work_amt < 0) || (work_amt > land_mob_max)) { pr("Mobility used must be from 0 to %d\n", land_mob_max); return RET_FAIL; } nunits = 0; while (nxtitem(&ni, &land)) { if (!player->owner || land.lnd_own == 0) continue; if (!(lchr[(int)land.lnd_type].l_flags & L_ENGINEER)) continue; if (land.lnd_mobil <= 0) { pr("%s has no mobility!\n", prland(&land)); continue; } getsect(land.lnd_x, land.lnd_y, §); if (sect.sct_effic >= 100 && sect.sct_type == sect.sct_newtype) { pr("Nothing to do for %s in %s\n", prland(&land), xyas(sect.sct_x, sect.sct_y, player->cnum)); continue; } eff_amt = MIN(land.lnd_mobil, work_amt); w = (eff_amt * land.lnd_effic) / 600; if (w < 1) { pr("%s doesn't work enough to change efficiency (try increasing amount)\n", prland(&land)); continue; } cost = 0.0; w = buildeff(§, w, &cost); if (w == 0) { pr("%s can't change efficiency in %s\n", prland(&land), xyas(land.lnd_x, land.lnd_y, player->cnum)); continue; } if (player->dolcost + cost > natp->nat_money) { pr("You can't afford to work that much in %s!\n", xyas(land.lnd_x, land.lnd_y, player->cnum)); break; } player->dolcost += cost; land.lnd_mission = 0; land.lnd_mobil -= roundavg(w * 600.0 / land.lnd_effic); nunits++; pr("%s %s efficiency at %s to %d\n", prland(&land), sect.sct_type == sect.sct_newtype ? "raised" : "lowered", xyas(land.lnd_x, land.lnd_y, player->cnum), sect.sct_effic); putland(land.lnd_uid, &land); putsect(§); } if (nunits == 0) { if (player->argp[1]) pr("%s: No unit(s)\n", player->argp[1]); else pr("%s: No unit(s)\n", ""); return RET_FAIL; } else pr("%d unit%s\n", nunits, splur(nunits)); return RET_OK; }
static int load_land_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp) { struct nstr_item ni; struct lndstr land; int loaded = 0; char *p; char prompt[512]; char buf[1024]; if (load_unload == LOAD && lnd_nland(lp) >= lchr[lp->lnd_type].l_nland) { if (noisy) { if (lchr[lp->lnd_type].l_nland) pr("%s doesn't have room for any more land units!\n", prland(lp)); else pr("%s cannot carry land units!\n", prland(lp)); } return 0; } sprintf(prompt, "Land unit(s) to %s %s? ", load_unload == LOAD ? "load onto" : "unload from", prland(lp)); p = getstarg(player->argp[3], prompt, buf); if (!p) return RET_SYN; if (!snxtitem(&ni, EF_LAND, p, NULL)) return RET_SYN; if (!still_ok_land(sectp, lp)) return RET_SYN; if (noisy && p && *p) noisy = isdigit(*p); while (nxtitem(&ni, &land)) { if (!player->owner) continue; if (load_unload == LOAD) { if (land.lnd_ship > -1) { if (noisy) pr("%s is already on ship #%d!\n", prland(&land), land.lnd_ship); continue; } if (land.lnd_land > -1) { if (noisy) pr("%s is already on land #%d!\n", prland(&land), land.lnd_land); continue; } if (lnd_first_on_land(&land) >= 0) { if (noisy) pr("%s cannot be loaded since it is carrying units\n", prland(&land)); continue; } if (land.lnd_uid == lp->lnd_uid) { if (noisy) pr("%s can't be loaded onto itself!\n", prland(&land)); continue; } if (lchr[(int)land.lnd_type].l_flags & (L_HEAVY | L_TRAIN)) { if (noisy) pr("%s is too heavy to load.\n", prland(&land)); continue; } } /* Unit sanity done */ /* Find the right ship */ if (load_unload == UNLOAD) { if (land.lnd_land != lp->lnd_uid) continue; if (land.lnd_ship > -1) continue; } else if (lp->lnd_x != land.lnd_x || lp->lnd_y != land.lnd_y) continue; /* Fit unit on ship */ if (load_unload == LOAD) { if (lnd_nland(lp) >= lchr[lp->lnd_type].l_nland) { if (noisy) { if (lchr[lp->lnd_type].l_nland) pr("%s doesn't have room for any more land units!\n", prland(lp)); else pr("%s cannot carry land units!\n", prland(lp)); } break; } sprintf(buf, "loaded on your %s at %s", prland(lp), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); gift(lp->lnd_own, player->cnum, &land, buf); land.lnd_land = lp->lnd_uid; land.lnd_harden = 0; putland(land.lnd_uid, &land); #if 0 /* FIXME same issue as in load_land_ship() */ if (!lnd_supply_all(&land)) pr("WARNING: %s is out of supply!\n", prland(&land)); #else if (!lnd_in_supply(&land)) pr("WARNING: %s is out of supply!\n", prland(&land)); #endif } else { sprintf(buf, "unloaded in your %s at %s", dchr[sectp->sct_type].d_name, xyas(sectp->sct_x, sectp->sct_y, sectp->sct_own)); gift(sectp->sct_own, player->cnum, &land, buf); land.lnd_land = -1; putland(land.lnd_uid, &land); } pr("%s %s %s at %s.\n", prland(&land), (load_unload == UNLOAD) ? "unloaded from" : "loaded onto", prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum)); loaded = 1; } *nunitsp += loaded; return 0; }
static int load_plane_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp) { struct nstr_item ni; struct plnstr pln; int loaded = 0; char *p; char prompt[512]; char buf[1024]; struct lchrstr *lcp = lchr + lp->lnd_type; if (!lcp->l_nxlight) { if (noisy) pr("%s cannot carry extra-light planes.\n", prland(lp)); return 0; } if (load_unload == LOAD && lnd_nxlight(lp) >= lcp->l_nxlight) { if (noisy) pr("%s doesn't have room for any more extra-light planes\n", prland(lp)); return 0; } sprintf(prompt, "Plane(s) to %s %s? ", load_unload == LOAD ? "load onto" : "unload from", prland(lp)); p = getstarg(player->argp[3], prompt, buf); if (!p) return RET_SYN; if (!snxtitem(&ni, EF_PLANE, p, NULL)) return RET_SYN; if (!still_ok_land(sectp, lp)) return RET_SYN; if (noisy && p && *p) noisy = isdigit(*p); while (nxtitem(&ni, &pln)) { if (!player->owner) continue; if (!(plchr[(int)pln.pln_type].pl_flags & P_E)) { if (noisy) pr("You can only load xlight planes onto units.\n"); continue; } if (load_unload == LOAD && pln.pln_ship > -1) { if (noisy) pr("%s is already on ship #%d!\n", prplane(&pln), pln.pln_ship); continue; } if (load_unload == LOAD && pln.pln_land > -1) { if (noisy) pr("%s is already on unit #%d!\n", prplane(&pln), pln.pln_land); continue; } if (pln.pln_harden != 0) { if (noisy) pr("%s has been hardened and can't be loaded\n", prplane(&pln)); continue; } /* Plane sanity done */ /* Find the right unit */ if (load_unload == UNLOAD) { if (pln.pln_land != lp->lnd_uid) continue; } else if (lp->lnd_x != pln.pln_x || lp->lnd_y != pln.pln_y) continue; /* Fit plane on unit */ if (load_unload == LOAD) { if (!put_plane_on_land(&pln, lp)) { if (noisy) pr("Can't put plane %d on this unit!\n", pln.pln_uid); continue; } sprintf(buf, "loaded on %s at %s", prland(lp), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); gift(lp->lnd_own, player->cnum, &pln, buf); putplane(pln.pln_uid, &pln); } else { pln.pln_land = -1; sprintf(buf, "unloaded at your sector at %s", xyas(sectp->sct_x, sectp->sct_y, sectp->sct_own)); gift(sectp->sct_own, player->cnum, &pln, buf); putplane(pln.pln_uid, &pln); } pr("%s %s %s at %s.\n", prplane(&pln), (load_unload == UNLOAD) ? "unloaded from" : "loaded onto", prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum)); loaded = 1; } *nunitsp += loaded; return 0; }
static int load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp) { struct nstr_item ni; struct lndstr land; int loaded = 0; char *p; char prompt[512]; char buf[1024]; int load_spy = 0; if (load_unload == LOAD) { if ((mchr[(int)sp->shp_type].m_flags & M_SUB) && (mchr[(int)sp->shp_type].m_nland == 0)) { if (shp_nland(sp) >= 2) { pr("Non-land unit carrying subs can only carry up to two spy units.\n"); return 0; } /* Eh, let 'em load a spy only */ load_spy = 1; } if (!load_spy && shp_nland(sp) >= mchr[sp->shp_type].m_nland) { if (noisy) { if (mchr[(int)sp->shp_type].m_nland) pr("%s doesn't have room for any more land units!\n", prship(sp)); else pr("%s cannot carry land units!\n", prship(sp)); } return 0; } } sprintf(prompt, "Land unit(s) to %s %s? ", load_unload == LOAD ? "load onto" : "unload from", prship(sp)); p = getstarg(player->argp[3], prompt, buf); if (!p) return RET_SYN; if (!snxtitem(&ni, EF_LAND, p, NULL)) return RET_SYN; if (!still_ok_ship(sectp, sp)) return RET_SYN; if (noisy && p && *p) noisy = isdigit(*p); while (nxtitem(&ni, &land)) { if (!player->owner) continue; if (load_unload == LOAD) { if (land.lnd_ship > -1) { if (noisy) pr("%s is already on ship #%d!\n", prland(&land), land.lnd_ship); continue; } if (land.lnd_land > -1) { if (noisy) pr("%s is already on land #%d!\n", prland(&land), land.lnd_land); continue; } if (lnd_first_on_land(&land) >= 0) { if (noisy) pr("%s cannot be loaded since it is carrying units\n", prland(&land)); continue; } if (lchr[(int)land.lnd_type].l_flags & L_HEAVY) { if (noisy) pr("%s is too heavy to load.\n", prland(&land)); continue; } if (load_spy && !(lchr[(int)land.lnd_type].l_flags & L_SPY)) { if (noisy) pr("Subs can only carry spy units.\n"); continue; } } /* Unit sanity done */ /* Find the right ship */ if (load_unload == UNLOAD) { if (land.lnd_ship != sp->shp_uid) continue; if (land.lnd_land > -1) continue; } else if (sp->shp_x != land.lnd_x || sp->shp_y != land.lnd_y) continue; if ((!(lchr[(int)land.lnd_type].l_flags & L_LIGHT)) && (!((mchr[(int)sp->shp_type].m_flags & M_SUPPLY) && (!(mchr[(int)sp->shp_type].m_flags & M_SUB))))) { if (noisy) { pr("You can only load light units onto ships,\n"); pr("unless the ship is a non-sub supply ship\n"); pr("%s not loaded\n", prland(&land)); } continue; } /* Fit unit on ship */ if (load_unload == LOAD) { /* We have to check again, since it may have changed */ if ((mchr[(int)sp->shp_type].m_flags & M_SUB) && (mchr[(int)sp->shp_type].m_nland == 0)) { if (shp_nland(sp) >= 2) { pr("Non-land unit carrying subs can only carry up to two spy units.\n"); return 0; } /* Eh, let 'em load a spy only */ load_spy = 1; } if (!load_spy && shp_nland(sp) >= mchr[sp->shp_type].m_nland) { if (noisy) { if (mchr[(int)sp->shp_type].m_nland) pr("%s doesn't have room for any more land units!\n", prship(sp)); else pr("%s cannot carry land units!\n", prship(sp)); } return 0; } sprintf(buf, "loaded on your %s at %s", prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own)); gift(sp->shp_own, player->cnum, &land, buf); land.lnd_ship = sp->shp_uid; land.lnd_harden = 0; putland(land.lnd_uid, &land); #if 0 /* * FIXME if this supplies from the sector, the putsect in * load() / lload() duplicates those supplies, causing a * seqno mismatch */ if (!lnd_supply_all(&land)) pr("WARNING: %s is out of supply!\n", prland(&land)); #else if (!lnd_in_supply(&land)) pr("WARNING: %s is out of supply!\n", prland(&land)); #endif } else { sprintf(buf, "unloaded in your %s at %s", dchr[sectp->sct_type].d_name, xyas(sectp->sct_x, sectp->sct_y, sectp->sct_own)); /* Spies are unloaded quietly, others aren't */ if (!(lchr[(int)land.lnd_type].l_flags & L_SPY)) gift(sectp->sct_own, player->cnum, &land, buf); land.lnd_ship = -1; putland(land.lnd_uid, &land); } pr("%s %s %s at %s.\n", prland(&land), (load_unload == UNLOAD) ? "unloaded from" : "loaded onto", prship(sp), xyas(sp->shp_x, sp->shp_y, player->cnum)); loaded = 1; } *nshipsp += loaded; return 0; }
static int tend_land(struct shpstr *tenderp, char *units) { struct nstr_item lni; struct nstr_item targets; struct shpstr target; struct lndstr land; char buf[1024]; if (!snxtitem(&lni, EF_LAND, units, NULL)) return RET_SYN; while (nxtitem(&lni, &land)) { if (!player->owner) continue; if (land.lnd_ship != tenderp->shp_uid) { pr("%s is not on %s!\n", prland(&land), prship(tenderp)); continue; } if (!(lchr[(int)land.lnd_type].l_flags & L_ASSAULT)) { pr("%s does not have \"assault\" capability and can't be tended\n", prland(&land)); continue; } if (!snxtitem(&targets, EF_SHIP, player->argp[4], "Ship to be tended? ")) return RET_FAIL; if (!check_ship_ok(tenderp) || !check_land_ok(&land)) return RET_SYN; while (nxtitem(&targets, &target)) { if (!player->owner && relations_with(target.shp_own, player->cnum) < FRIENDLY) continue; if (target.shp_uid == tenderp->shp_uid) continue; if (tenderp->shp_x != target.shp_x || tenderp->shp_y != target.shp_y) continue; /* Fit unit on ship */ getship(target.shp_uid, &target); if ((!(lchr[(int)land.lnd_type].l_flags & L_LIGHT)) && (!((mchr[(int)target.shp_type].m_flags & M_SUPPLY) && (!(mchr[(int)target.shp_type].m_flags & M_SUB))))) { pr("You can only load light units onto ships,\n" "unless the ship is a non-sub supply ship\n" "%s not tended\n", prland(&land)); continue; } if ((mchr[(int)target.shp_type].m_flags & M_SUB) && (lchr[(int)land.lnd_type].l_flags & L_SPY) && !mchr[(int)target.shp_type].m_nland) { if (shp_nland(&target) > 1) { pr("%s doesn't have room for more than two spy units!\n", prship(&target)); continue; } } else if (shp_nland(&target) >= mchr[target.shp_type].m_nland) { if (mchr[(int)target.shp_type].m_nland) pr("%s doesn't have room for any more land units!\n", prship(&target)); else pr("%s doesn't carry land units!\n", prship(&target)); continue; } pr("%s transferred from %s to %s\n", prland(&land), prship(tenderp), prship(&target)); sprintf(buf, "loaded on your %s at %s", prship(&target), xyas(target.shp_x, target.shp_y, target.shp_own)); gift(target.shp_own, player->cnum, &land, buf); land.lnd_ship = target.shp_uid; land.lnd_harden = 0; putland(land.lnd_uid, &land); expose_ship(tenderp, &target); putship(target.shp_uid, &target); putship(tenderp->shp_uid, tenderp); } } return 0; }
int sabo(void) { struct nstr_item ni; struct lndstr land, tmp; struct sctstr sect; double odds; int dam; if (!snxtitem(&ni, EF_LAND, player->argp[1], NULL)) return RET_SYN; while (nxtitem(&ni, &land)) { if (!player->owner) continue; if (!(lchr[(int)land.lnd_type].l_flags & L_SPY)) { pr("%s is not a spy.\n", prland(&land)); continue; } if (land.lnd_ship >= 0) { pr("%s is on ship %d.\n", prland(&land), land.lnd_ship); continue; } if (land.lnd_land >= 0) { pr("%s is on unit %d.\n", prland(&land), land.lnd_land); continue; } if (!getsect(land.lnd_x, land.lnd_y, §)) continue; if (land.lnd_item[I_SHELL] == 0) { pr("%s has no shells.\n", prland(&land)); continue; } odds = LND_SPY_DETECT_CHANCE(land.lnd_effic); if (chance(odds)) { wu(0, sect.sct_own, "%s spy shot in %s during sabotage attempt.\n", cname(player->cnum), xyas(sect.sct_x, sect.sct_y, sect.sct_own)); pr("%s was shot and killed.\n", prland(&land)); land.lnd_effic = 0; putland(land.lnd_uid, &land); continue; } dam = lnd_sabo(&land, sect.sct_item); if (dam < 0) continue; pr("Explosion in %s causes %d damage.\n", xyas(land.lnd_x, land.lnd_y, player->cnum), dam); if (sect.sct_own) { wu(0, sect.sct_own, "Sabotage in sector %s caused %d damage.\n", xyas(sect.sct_x, sect.sct_y, sect.sct_own), dam); } /* hack: hide the spy so it don't gets blasted by sectdamage() */ tmp = land; tmp.lnd_own = 0; putland(land.lnd_uid, &tmp); land.lnd_seqno = tmp.lnd_seqno; sectdamage(§, dam); putsect(§); if (chance(odds)) { pr("%s dies in explosion.\n", prland(&land)); land.lnd_effic = 0; } putland(land.lnd_uid, &land); } return RET_OK; }
void takeover(struct sctstr *sp, natid newown) { struct plnstr *pp; struct lndstr *lp; int civ; int che_count; int oldche; int n; struct nstr_item ni; struct plnstr p; struct lndstr land; /* Wipe all the distribution info */ memset(sp->sct_dist, 0, sizeof(sp->sct_dist)); memset(sp->sct_del, 0, sizeof(sp->sct_del)); if (sp->sct_own == 0) sp->sct_off = 0; else sp->sct_off = 1; sp->sct_dist_x = sp->sct_x; sp->sct_dist_y = sp->sct_y; pp = &p; /* Take over planes */ snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); while (nxtitem(&ni, pp)) { if (pp->pln_own != sp->sct_own) continue; takeover_plane(pp, newown); } /* Take over land units */ lp = &land; snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); while (nxtitem(&ni, lp)) { if ((lp->lnd_own == newown) || (lp->lnd_own == 0)) continue; if (lp->lnd_own != sp->sct_own) continue; if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) continue; /* Spies get a chance to hide */ if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { if (!(chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic)))) continue; } n = lp->lnd_effic - (29 + roll(100)); if (n < 0) n = 0; lp->lnd_effic = n; if (lp->lnd_effic < LAND_MINEFF) { lp->lnd_effic = 0; mpr(newown, "%s blown up by the crew!\n", prland(lp)); wu(0, lp->lnd_own, "%s blown up by the crew when %s took %s!\n", prland(lp), cname(newown), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); } else { mpr(newown, "We have captured %s!\n", prland(lp)); wu(0, lp->lnd_own, "%s captured when %s took %s!\n", prland(lp), cname(newown), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); } takeover_land(lp, newown); } sp->sct_avail = 0; civ = sp->sct_item[I_CIVIL]; oldche = sp->sct_che; /* * create guerrillas from civilians * how spunky are these guys? * n: random number from -25:75 + (50 - loyalty) */ n = (50 - sp->sct_loyal) + (roll(100) - 26); if (n > 0 && sp->sct_own == sp->sct_oldown) { che_count = (civ * n / 3000) + 5; if (che_count * 2 > civ) che_count = civ / 2; che_count /= hap_fact(getnatp(newown), getnatp(sp->sct_own)); if (che_count + oldche > CHE_MAX) che_count = CHE_MAX - oldche; if (che_count > 0) { civ -= che_count; che_count += oldche; } else che_count = oldche; } else che_count = oldche; sp->sct_che = che_count; if (newown != sp->sct_oldown) sp->sct_che_target = newown; if (sp->sct_che_target == 0) sp->sct_che = 0; sp->sct_item[I_CIVIL] = civ; if (sp->sct_oldown == newown || civ == 0) { /* * taking over one of your old sectors */ sp->sct_loyal = 0; sp->sct_oldown = newown; } else { /* * taking over someone else's sector */ sp->sct_loyal = 50; } sp->sct_own = newown; if (opt_MOB_ACCESS) { game_tick_to_now(&sp->sct_access); sp->sct_mobil = -(etu_per_update / sect_mob_neg_factor); } else { sp->sct_mobil = 0; } }
static int lupgr(void) { struct sctstr sect; struct natstr *natp; struct nstr_item ni; struct lndstr land; struct lchrstr *lp; int n; int tlev; int avail, cost; int cash; if (!snxtitem(&ni, EF_LAND, player->argp[2], NULL)) return RET_SYN; natp = getnatp(player->cnum); cash = natp->nat_money; tlev = (int)natp->nat_level[NAT_TLEV]; n = 0; while (nxtitem(&ni, &land)) { if (land.lnd_own == 0) continue; getsect(land.lnd_x, land.lnd_y, §); if (sect.sct_own != player->cnum) continue; if (sect.sct_type != SCT_HEADQ || sect.sct_effic < 60) continue; if (relations_with(land.lnd_own, sect.sct_own) < FRIENDLY) { pr("You are not on friendly terms with the owner of unit %d!\n", land.lnd_uid); continue; } n++; lp = &lchr[(int)land.lnd_type]; avail = (LND_BLD_WORK(lp->l_lcm, lp->l_hcm) * UPGR_COST + 99) / 100; if (sect.sct_avail < avail) { pr("Not enough available work in %s to upgrade a %s\n", xyas(sect.sct_x, sect.sct_y, player->cnum), lp->l_name); pr(" (%d available work required)\n", avail); continue; } if (land.lnd_effic < 60) { pr("%s is too damaged to upgrade!\n", prland(&land)); continue; } if (land.lnd_tech >= tlev) { pr("%s tech: %d, yours is only %d\n", prland(&land), land.lnd_tech, tlev); continue; } cost = lp->l_cost * UPGR_COST / 100; if (cost + player->dolcost > cash) { pr("You don't have enough money to upgrade %s!\n", prland(&land)); continue; } sect.sct_avail -= avail; land.lnd_effic -= UPGR_EFF; lnd_set_tech(&land, tlev); land.lnd_harden = 0; land.lnd_mission = 0; putland(land.lnd_uid, &land); putsect(§); player->dolcost += cost; pr("%s upgraded to tech %d, at a cost of %d\n", prland(&land), land.lnd_tech, cost); if (land.lnd_own != player->cnum) wu(0, land.lnd_own, "%s upgraded by %s to tech %d, at a cost of %d\n", prland(&land), cname(player->cnum), land.lnd_tech, cost); } if (n == 0) { pr("No land units\n"); return RET_SYN; } return RET_OK; }
int detonate(struct nukstr *np, coord x, coord y, int airburst) { int nuketype = np->nuk_type; struct nchrstr *ncp; struct plnstr plane; struct sctstr sect; struct shpstr ship; struct lndstr land; struct nukstr nuke; natid own; int type; int damage; int fallout; int rad; struct nstr_sect ns; struct nstr_item ni; int changed = 0; pr("Releasing RV's for %s detonation...\n", airburst ? "airburst" : "groundburst"); getsect(x, y, §); ncp = &nchr[nuketype]; kaboom(x, y, ncp->n_blast); rad = ncp->n_blast; if (!airburst) rad = rad * 2 / 3; if (sect.sct_type == SCT_WATER) rad = 0; /* Nukes falling on water affect only 1 sector */ np->nuk_effic = 0; putnuke(np->nuk_uid, np); snxtsct_dist(&ns, x, y, rad); while (nxtsct(&ns, §)) { own = sect.sct_own; type = sect.sct_type; if ((damage = nukedamage(ncp, ns.curdist, airburst)) <= 0) continue; if (type == SCT_SANCT) { pr("bounced off %s\n", xyas(ns.x, ns.y, player->cnum)); mpr(own, "%s nuclear device bounced off %s\n", cname(player->cnum), xyas(ns.x, ns.y, own)); nreport(player->cnum, N_NUKE, own, 1); continue; } sect_damage(§, damage); if (opt_FALLOUT) { fallout = sect.sct_fallout; if (ncp->n_flags & N_NEUT) fallout += damage * 30; else fallout += damage * 3; sect.sct_fallout = MIN(fallout, FALLOUT_MAX); } if (damage > 100) { sect.sct_oldown = 0; sect.sct_own = 0; if (type == SCT_WATER || type == SCT_BSPAN || type == SCT_BTOWER) { if (type != SCT_WATER) { pr("left nothing but water in %s\n", xyas(ns.x, ns.y, player->cnum)); if (own != player->cnum) mpr(own, "%s nuclear device left nothing but water in %s\n", cname(player->cnum), xyas(ns.x, ns.y, own)); sect.sct_newtype = SCT_WATER; sect.sct_type = SCT_WATER; } } else { sect.sct_newtype = SCT_WASTE; sect.sct_type = SCT_WASTE; pr("turned %s into a radioactive wasteland\n", xyas(ns.x, ns.y, player->cnum)); if (own != player->cnum) mpr(own, "%s nuclear device turned %s into a radioactive wasteland\n", cname(player->cnum), xyas(ns.x, ns.y, own)); } changed |= map_set(player->cnum, sect.sct_x, sect.sct_y, dchr[sect.sct_type].d_mnem, 0); } else { pr("did %d%% damage in %s\n", damage, xyas(ns.x, ns.y, player->cnum)); if (own != player->cnum) mpr(own, "%s nuclear device did %d%% damage in %s\n", cname(player->cnum), damage, xyas(ns.x, ns.y, own)); } (void)putsect(§); if (type != SCT_WATER) nreport(player->cnum, N_NUKE, own, 1); } if (changed) writebmap(player->cnum); snxtitem_dist(&ni, EF_PLANE, x, y, rad); while (nxtitem(&ni, &plane)) { if ((own = plane.pln_own) == 0) continue; if (plane.pln_flags & PLN_LAUNCHED) continue; damage = nukedamage(ncp, ni.curdist, airburst) - plane.pln_harden; if (damage <= 0) continue; if (plane.pln_ship >= 0) { /* Are we on a sub? */ getship(plane.pln_ship, &ship); if (mchr[(int)ship.shp_type].m_flags & M_SUB) { struct sctstr sect1; /* Should we damage this sub? */ getsect(ship.shp_x, ship.shp_y, §1); if (sect1.sct_type == SCT_BSPAN || sect1.sct_type == SCT_BTOWER || sect1.sct_type == SCT_WATER) { /* Ok, we're not in a harbor or trapped inland. Now, did we get pasted directly? */ if (ship.shp_x != x || ship.shp_y != y) { /* Nope, so don't mess with it */ continue; } } } } planedamage(&plane, damage); if (own == player->cnum) { pr("%s at %s reports %d%% damage\n", prplane(&plane), xyas(plane.pln_x, plane.pln_y, player->cnum), damage); } else { mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", cname(player->cnum), damage, prplane(&plane), xyas(plane.pln_x, plane.pln_y, own)); } putplane(ni.cur, &plane); } snxtitem_dist(&ni, EF_LAND, x, y, rad); while (nxtitem(&ni, &land)) { if ((own = land.lnd_own) == 0) continue; if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) continue; if (land.lnd_ship >= 0) { /* Are we on a sub? */ getship(land.lnd_ship, &ship); if (mchr[(int)ship.shp_type].m_flags & M_SUB) { struct sctstr sect1; /* Should we damage this sub? */ getsect(ship.shp_x, ship.shp_y, §1); if (sect1.sct_type == SCT_BSPAN || sect1.sct_type == SCT_BTOWER || sect1.sct_type == SCT_WATER) { /* Ok, we're not in a harbor or trapped inland. Now, did we get pasted directly? */ if (ship.shp_x != x || ship.shp_y != y) { /* Nope, so don't mess with it */ continue; } } } } land_damage(&land, damage); if (own == player->cnum) { pr("%s at %s reports %d%% damage\n", prland(&land), xyas(land.lnd_x, land.lnd_y, player->cnum), damage); } else { mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", cname(player->cnum), damage, prland(&land), xyas(land.lnd_x, land.lnd_y, own)); } putland(land.lnd_uid, &land); } snxtitem_dist(&ni, EF_SHIP, x, y, rad); while (nxtitem(&ni, &ship)) { if ((own = ship.shp_own) == 0) continue; if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) continue; if (mchr[(int)ship.shp_type].m_flags & M_SUB) { struct sctstr sect1; /* Should we damage this sub? */ getsect(ship.shp_x, ship.shp_y, §1); if (sect1.sct_type == SCT_BSPAN || sect1.sct_type == SCT_BTOWER || sect1.sct_type == SCT_WATER) { /* Ok, we're not in a harbor or trapped inland. Now, did we get pasted directly? */ if (ship.shp_x != x || ship.shp_y != y) { /* Nope, so don't mess with it */ continue; } } } ship_damage(&ship, damage); if (own == player->cnum) { pr("%s at %s reports %d%% damage\n", prship(&ship), xyas(ship.shp_x, ship.shp_y, player->cnum), damage); } else { mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", cname(player->cnum), damage, prship(&ship), xyas(ship.shp_x, ship.shp_y, own)); } putship(ship.shp_uid, &ship); } snxtitem_dist(&ni, EF_NUKE, x, y, rad); while (nxtitem(&ni, &nuke)) { if ((own = nuke.nuk_own) == 0) continue; if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) continue; if (!pct_chance(damage)) continue; nuke.nuk_effic = 0; if (own == player->cnum) { pr("%s at %s destroyed\n", prnuke(&nuke), xyas(nuke.nuk_x, nuke.nuk_y, player->cnum)); } else { mpr(own, "%s nuclear device destroyed %s at %s\n", cname(player->cnum), prnuke(&nuke), xyas(nuke.nuk_x, nuke.nuk_y, own)); } putnuke(ni.cur, &nuke); } return nukedamage(ncp, 0, airburst); }
/* Knock down a bridge span. Note that this does NOT write the * sector out to the database, it's up to the caller to do that. */ static void knockdown(struct sctstr *sp) { struct lndstr land; struct plnstr plane; struct nukstr nuke; struct nstr_item ni; mpr(sp->sct_own, "Crumble... SCREEEECH! Splash! Bridge%s falls at %s!\n", sp->sct_type == SCT_BTOWER ? " tower" : "", xyas(sp->sct_x, sp->sct_y, sp->sct_own)); if (!SCT_MINES_ARE_SEAMINES(sp)) sp->sct_mines = 0; sp->sct_type = SCT_WATER; sp->sct_newtype = SCT_WATER; sp->sct_own = 0; sp->sct_oldown = 0; sp->sct_mobil = 0; sp->sct_effic = 0; /* Sink all the units */ snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); while (nxtitem(&ni, &land)) { if (land.lnd_own == 0) continue; if (land.lnd_ship >= 0) continue; mpr(land.lnd_own, " AARGH! %s tumbles to its doom!\n", prland(&land)); land.lnd_effic = 0; putland(land.lnd_uid, &land); } /* Sink all the planes */ snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); while (nxtitem(&ni, &plane)) { if (plane.pln_own == 0) continue; if (plane.pln_flags & PLN_LAUNCHED) continue; if (plane.pln_ship >= 0) continue; mpr(plane.pln_own, " AARGH! %s tumbles to its doom!\n", prplane(&plane)); plane.pln_effic = 0; putplane(plane.pln_uid, &plane); } /* Sink all the nukes */ snxtitem_xy(&ni, EF_NUKE, sp->sct_x, sp->sct_y); while (nxtitem(&ni, &nuke)) { if (nuke.nuk_own == 0) continue; if (nuke.nuk_plane >= 0) continue; mpr(nuke.nuk_own, " %s sinks to the bottom of the sea!\n", prnuke(&nuke)); nuke.nuk_effic = 0; putnuke(nuke.nuk_uid, &nuke); } memset(sp->sct_item, 0, sizeof(sp->sct_item)); memset(sp->sct_del, 0, sizeof(sp->sct_del)); memset(sp->sct_dist, 0, sizeof(sp->sct_dist)); sp->sct_pstage = PLG_HEALTHY; sp->sct_ptime = 0; sp->sct_che = 0; sp->sct_che_target = 0; }
int pln_equip(struct plist *plp, struct ichrstr *ip, char mission) { struct plchrstr *pcp; struct plnstr *pp; int load, needed; struct lndstr land; struct shpstr ship; struct sctstr sect; i_type itype; short *item; int own; int abandon_needed; pp = &plp->plane; pcp = plp->pcp; if (pp->pln_ship >= 0) { getship(pp->pln_ship, &ship); plp->pstage = ship.shp_pstage; item = ship.shp_item; own = ship.shp_own; } else if (pp->pln_land >= 0) { getland(pp->pln_land, &land); plp->pstage = land.lnd_pstage; item = land.lnd_item; own = land.lnd_own; } else { getsect(pp->pln_x, pp->pln_y, §); plp->pstage = sect.sct_pstage; item = sect.sct_item; own = sect.sct_oldown; } if (pcp->pl_fuel > item[I_PETROL]) { pr("%s not enough petrol there!\n", prplane(pp)); return -1; } item[I_PETROL] -= pcp->pl_fuel; load = pln_load(pp); itype = I_NONE; switch (mission) { case 's': /* strategic bomb */ case 'p': /* pinpoint bomb */ itype = I_SHELL; break; case 't': /* transport */ if (!(pcp->pl_flags & P_C) || !ip) break; itype = ip->i_uid; load *= 2; break; case 'm': /* mine */ if ((pcp->pl_flags & P_MINE) == 0) break; itype = I_SHELL; load *= 2; break; case 'd': /* drop */ if (!(pcp->pl_flags & P_C) || CANT_HAPPEN(!ip)) break; itype = ip->i_uid; if (pcp->pl_flags & P_V) load *= 2; break; case 'a': /* paradrop */ if (!(pcp->pl_flags & P_P)) break; itype = I_MILIT; if (pcp->pl_flags & P_V) load *= 2; break; case 'r': /* reconnaissance */ case 'e': /* escort */ load = 0; break; case 'i': /* missile interception */ if (CANT_HAPPEN(!(pcp->pl_flags & P_M) || !(pcp->pl_flags & (P_N | P_O)))) break; if (load) itype = I_SHELL; break; default: CANT_REACH(); load = 0; } if (itype != I_NONE) { needed = load / ichr[itype].i_lbs; if (needed <= 0) { pr("%s can't contribute to mission\n", prplane(pp)); return -1; } if (nuk_on_plane(pp) >= 0) { if (mission == 's' || mission == 't') needed = 0; else { pr("%s can't fly this mission" " while it is carrying a nuclear weapon", prplane(pp)); return -1; } } if (itype == I_CIVIL && pp->pln_own != own) { pr("You don't control those civilians!\n"); return -1; } #if 0 /* Supply is broken somewhere, so don't use it for now */ if (itype == I_SHELL && item[itype] < needed) item[itype] += supply_commod(plp->plane.pln_own, plp->plane.pln_x, plp->plane.pln_y, I_SHELL, needed); #endif if (pp->pln_ship >= 0 || pp->pln_land >= 0) abandon_needed = 0; else abandon_needed = !!would_abandon(§, itype, needed, NULL); if (item[itype] < needed + abandon_needed) { pr("Not enough %s for %s\n", ichr[itype].i_name, prplane(pp)); return -1; } item[itype] -= needed; plp->load = needed; } if (pp->pln_ship >= 0) { if (pp->pln_own != ship.shp_own) { wu(0, ship.shp_own, "%s %s prepares for takeoff from ship %s\n", cname(pp->pln_own), prplane(pp), prship(&ship)); } putship(ship.shp_uid, &ship); } else if (pp->pln_land >= 0) { if (pp->pln_own != land.lnd_own) { wu(0, land.lnd_own, "%s %s prepares for takeoff from unit %s\n", cname(pp->pln_own), prplane(pp), prland(&land)); } putland(land.lnd_uid, &land); } else { if (pp->pln_own != sect.sct_own) { wu(0, sect.sct_own, "%s %s prepares for takeoff from %s\n", cname(pp->pln_own), prplane(pp), xyas(sect.sct_x, sect.sct_y, sect.sct_own)); } putsect(§); } return 0; }
int assa(void) { struct combat off[1]; /* assaulting ship */ struct combat def[1]; /* defending sector */ int fort_sup, ship_sup, land_sup, plane_sup; struct emp_qelem olist; /* assaulting units */ struct emp_qelem dlist; /* defending units */ int ototal; /* total assaulting strength */ int a_engineer = 0; /* assaulter engineers are present */ int a_spy = 0; /* the best assaulter scout */ double osupport = 1.0; /* assault support */ double dsupport = 1.0; /* defense support */ char *p; char buf[1024]; int n; int ourtotal; struct emp_qelem *qp, *next; struct ulist *llp; int rel; att_combat_init(off, EF_SHIP); att_combat_init(def, EF_SECTOR); /* * Collect input from the assaulter */ /* What are we assaulting? */ if (!(p = getstarg(player->argp[1], "Sector : ", buf))) return RET_SYN; if (!sarg_xy(p, &def->x, &def->y)) return RET_SYN; if (att_abort(A_ASSAULT, NULL, def)) return RET_FAIL; /* * Ask the assaulter what he wants to assault with */ if ((off->shp_uid = onearg(player->argp[2], "Assault from ship # ")) < 0) { pr("You may only assault from one ship!\n"); return RET_FAIL; } if (att_abort(A_ASSAULT, off, def)) { pr("Assault aborted\n"); return RET_OK; } /* Show what we're assaulting */ att_show(def); /* Ask about offensive support */ att_ask_support(3, &fort_sup, &ship_sup, &land_sup, &plane_sup); if (att_abort(A_ASSAULT, off, def)) { att_empty_attack(A_ASSAULT, 0, def); return RET_OK; } /* Ask the player what he wants to assault with */ att_ask_offense(A_ASSAULT, off, def, &olist, &a_spy, &a_engineer); if (att_abort(A_ASSAULT, off, def)) { pr("Assault aborted\n"); att_empty_attack(A_ASSAULT, 0, def); return att_free_lists(&olist, NULL); } /* If we're assaulting our own sector, end here */ if (def->own == player->cnum) { if (off->troops) pr("You reinforce %s with %d troops\n", xyas(def->x, def->y, player->cnum), off->troops); if (off->troops || !QEMPTY(&olist)) att_move_in_off(A_ASSAULT, off, &olist, def); return RET_OK; } ototal = att_get_offense(A_ASSAULT, off, &olist, def); if (att_abort(A_ASSAULT, off, def)) { pr("Assault aborted\n"); att_empty_attack(A_ASSAULT, 0, def); return att_free_lists(&olist, NULL); } /* * We have now got all the answers from the assaulter. From this point * forward, we can assume that this battle is the _only_ thing * happening in the game. */ /* First, we check to see if the only thing we have are spies * assaulting. If so, we try to sneak them on land. If they * make it, the defenders don't see a thing. If they fail, well, * the spies die, and the defenders see them. */ ourtotal = 0; for (n = 0; n <= off->last; n++) { if (off[n].type == EF_BAD) continue; ourtotal += off[n].troops * att_combat_eff(off + n); } for (qp = olist.q_forw; qp != &olist; qp = next) { next = qp->q_forw; llp = (struct ulist *)qp; if (lchr[(int)llp->unit.land.lnd_type].l_flags & L_SPY) continue; ourtotal++; } /* If no attacking forces (i.e. we got here with only spies) * then try to sneak on-land. */ if (!ourtotal) { pr("Trying to sneak on shore...\n"); for (qp = olist.q_forw; qp != &olist; qp = next) { next = qp->q_forw; llp = (struct ulist *)qp; rel = relations_with(def->own, player->cnum); if (chance(0.10) || rel == ALLIED || !def->own) { pr("%s made it on shore safely.\n", prland(&llp->unit.land)); llp->unit.land.lnd_x = def->x; llp->unit.land.lnd_y = def->y; llp->unit.land.lnd_ship = -1; putland(llp->unit.land.lnd_uid, &llp->unit.land); } else { pr("%s was spotted", prland(&llp->unit.land)); if (rel <= HOSTILE) { wu(0, def->own, "%s spy shot and killed in %s.\n", cname(player->cnum), xyas(def->x, def->y, def->own)); pr(" and was killed in the attempt.\n"); llp->unit.land.lnd_effic = 0; putland(llp->unit.land.lnd_uid, &llp->unit.land); lnd_put_one(llp); } else { wu(0, def->own, "%s spy spotted in %s.\n", cname(player->cnum), xyas(def->x, def->y, def->own)); pr(" but made it ok.\n"); llp->unit.land.lnd_x = def->x; llp->unit.land.lnd_y = def->y; llp->unit.land.lnd_ship = -1; putland(llp->unit.land.lnd_uid, &llp->unit.land); } } } return RET_OK; } /* Get the real defense */ att_get_defense(&olist, def, &dlist, a_spy, ototal); /* Get assaulter and defender support */ att_get_support(A_ASSAULT, fort_sup, ship_sup, land_sup, plane_sup, &olist, off, &dlist, def, &osupport, &dsupport, a_engineer); if (att_abort(A_ASSAULT, off, def)) { pr("Assault aborted\n"); att_empty_attack(A_ASSAULT, 0, def); return att_free_lists(&olist, &dlist); } /* * Death, carnage, and destruction. */ att_fight(A_ASSAULT, off, &olist, osupport, def, &dlist, dsupport); return RET_OK; }
static void look_land(struct lndstr *lookland) { struct plnstr *pp; struct lndstr *lp; double drange; int range; int vrange; int i; int dist; drange = techfact(lookland->lnd_tech, lchr[lookland->lnd_type].l_spy); drange *= lookland->lnd_effic / 100.0; range = ldround(drange, 1); if (range == 0) return; for (i = 0; NULL != (lp = getlandp(i)); i++) { if (lp->lnd_own == player->cnum || lp->lnd_own == 0) continue; if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) continue; /* Don't always see spies */ if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { /* If it's on a ship or unit, assume it's hidden enough not to be seen */ if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) continue; if (!(chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic)))) continue; } vrange = ldround((lnd_vis(lp) * range) / 20.0, 1); dist = mapdist(lp->lnd_x, lp->lnd_y, lookland->lnd_x, lookland->lnd_y); if (dist > vrange) continue; pr("%s %s (approx %d mil) @ %s\n", prnatid(lp->lnd_own), prland(lp), roundintby(lp->lnd_item[I_MILIT], 20), xyas(lp->lnd_x, lp->lnd_y, player->cnum)); if (opt_HIDDEN) setcont(player->cnum, lp->lnd_own, FOUND_LOOK); } for (i = 0; NULL != (pp = getplanep(i)); i++) { if (pp->pln_own == player->cnum || pp->pln_own == 0) continue; if (pp->pln_ship >= 0 || pp->pln_land >= 0) continue; if (pp->pln_flags & PLN_LAUNCHED) continue; vrange = ldround((10 * range) / 20.0, 1); dist = mapdist(pp->pln_x, pp->pln_y, lookland->lnd_x, lookland->lnd_y); if (dist > vrange) continue; pr("%s %s @ %s\n", prnatid(pp->pln_own), prplane(pp), xyas(pp->pln_x, pp->pln_y, player->cnum)); if (opt_HIDDEN) setcont(player->cnum, pp->pln_own, FOUND_LOOK); } }