Exemplo n.º 1
0
static int
verify_lands(int may_put)
{
    int retval = 0;
    int i;
    struct lndstr *lp;

    /* laziness: assumes land file is EFF_MEM */
    for (i = 0; (lp = getlandp(i)); i++) {
	if (lp->lnd_own) {
	    if (lp->lnd_ship >= 0 && lp->lnd_land >= 0) {
		verify_fail(EF_LAND, i, NULL, 0, "on two carriers");
		retval = -1;
	    }
	} else {
	    if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) {
		lp->lnd_ship = lp->lnd_land = -1;
		if (may_put)
		    putland(i, lp);
		verify_fail(EF_LAND, i, NULL, 0,
			    "ghost stuck on carrier (fixed)");
	    }
	}
    }
    return retval;
}
Exemplo n.º 2
0
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, &sect);
	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(&sect, 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(&sect);
    }
    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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
int
lload(void)
{
    int noisy;
    int load_unload;
    int type;
    struct nstr_item nbst;
    struct ichrstr *ich;
    int nunits;
    struct sctstr sect;
    struct lndstr land;
    int retval;
    char *p;
    char buf[1024];

    p = getstarg(player->argp[1],
		 "What commodity (or 'plane' or 'land')? ", buf);
    if (!p || !*p)
	return RET_SYN;
    if (!strncmp(p, "plane", 5))
	type = EF_PLANE;
    else if (!strncmp(p, "land", 4))
	type = EF_LAND;
    else if (NULL != (ich = item_by_name(p)))
	type = EF_SECTOR;
    else {
	pr("Can't load '%s'\n", p);
	return RET_SYN;
    }

    p = getstarg(player->argp[2], "Unit(s): ", buf);
    if (!p || !*p)
	return RET_SYN;

    noisy = isdigit(*p);

    if (!snxtitem(&nbst, EF_LAND, p, NULL))
	return RET_SYN;

    load_unload = player->argp[0][1] == 'l' ? LOAD : UNLOAD;

    nunits = 0;
    while (nxtitem(&nbst, &land)) {
	if (land.lnd_own == 0)
	    continue;
	if (!player->owner) {
	    if (load_unload == UNLOAD || !noisy)
		continue;
	    if (relations_with(land.lnd_own, player->cnum) != ALLIED)
		continue;
	}

	if (!getsect(land.lnd_x, land.lnd_y, &sect))	/* XXX */
	    continue;
	if (!player->owner) {
	    if (land.lnd_own != player->cnum)
		continue;
	    if (load_unload == LOAD) {
		if (noisy)
		    pr("Sector %s is not yours.\n",
		       xyas(sect.sct_x, sect.sct_y, player->cnum));
		continue;
	    }
	    if (relations_with(sect.sct_own, player->cnum) != ALLIED) {
		pr("Sector %s is not yours.\n",
		   xyas(sect.sct_x, sect.sct_y, player->cnum));
		continue;
	    }
	}

	if (opt_MARKET) {
	    if (ontradingblock(EF_LAND, &land)) {
		pr("You cannot load/unload an item on the trading block!\n");
		continue;
	    }
	}

	switch (type) {
	case EF_LAND:
	    retval = load_land_land(&sect, &land, noisy, load_unload,
				    &nunits);
	    if (retval != 0)
		return retval;
	    break;
	case EF_PLANE:
	    retval = load_plane_land(&sect, &land, noisy, load_unload,
				     &nunits);
	    if (retval != 0)
		return retval;
	    break;
	case EF_SECTOR:
	    retval = load_comm_land(&sect, &land, ich, load_unload,
				    &nunits);
	    if (retval != 0)
		return retval;
	}
	/* load/unload plague */
	if (sect.sct_pstage == PLG_INFECT
	    && land.lnd_pstage == PLG_HEALTHY)
	    land.lnd_pstage = PLG_EXPOSED;
	if (land.lnd_pstage == PLG_INFECT
	    && sect.sct_pstage == PLG_HEALTHY)
	    sect.sct_pstage = PLG_EXPOSED;

	putsect(&sect);
	putland(land.lnd_uid, &land);
    }
    if (nunits == 0)
	pr("No units affected\n");
    else
	pr("%d unit%s %sloaded\n", nunits, splur(nunits),
	   load_unload == UNLOAD ? "un" : "");
    return RET_OK;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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, &sect);
	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(&sect);
	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;
}
Exemplo n.º 8
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, &sect))
	    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(&sect, dam);
	putsect(&sect);

	if (chance(odds)) {
	    pr("%s dies in explosion.\n", prland(&land));
	    land.lnd_effic = 0;
	}
	putland(land.lnd_uid, &land);
    }
    return RET_OK;
}
Exemplo n.º 9
0
/*
 * Actually get the commod
 *
 * First, try to forage in the sector
 * Second look for a warehouse or headquarters to leech
 * Third, look for a ship we own in a harbor
 * Fourth, look for supplies in a supply unit we own
 *		(one good reason to do this last is that the supply
 *		 unit will then call resupply, taking more time)
 *
 * May want to put code to resupply with SAMs here, later --ts
 */
static int
s_commod(struct empobj *sink, short *vec,
	 i_type type, int wanted, int limit, int actually_doit)
{
    natid own = sink->own;
    coord x = sink->x;
    coord y = sink->y;
    int lookrange;
    struct sctstr sect;
    struct nstr_sect ns;
    struct nstr_item ni;
    struct lchrstr *lcp;
    struct shpstr ship;
    struct lndstr land;
    /* leave at least 1 military in sectors/ships */
    int minimum = 0;
    int can_move;
    double move_cost, weight, mobcost;
    int packing;
    struct dchrstr *dp;
    struct ichrstr *ip;

    if (wanted > limit)
	wanted = limit;
    if (wanted <= vec[type])
	return 1;
    wanted -= vec[type];

    /* try to get it from sector we're in */
    if (sink->ef_type != EF_SECTOR) {
	getsect(x, y, &sect);
	if (sect.sct_own == own) {
	    if (!opt_NOFOOD && type == I_FOOD)
		minimum = 1 + (int)ceil(food_needed(sect.sct_item,
						    etu_per_update));
	    if (sect.sct_item[type] - wanted >= minimum) {
		sect.sct_item[type] -= wanted;
		if (actually_doit) {
		    vec[type] += wanted;
		    putsect(&sect);
		    put_empobj(sink->ef_type, sink->uid, sink);
		}
		return 1;
	    } else if (sect.sct_item[type] - minimum > 0) {
		wanted -= sect.sct_item[type] - minimum;
		sect.sct_item[type] = minimum;
		if (actually_doit) {
		    vec[type] += sect.sct_item[type] - minimum;
		    putsect(&sect);
		}
	    }
	}
    }

    /* look for a headquarters or warehouse */
    lookrange = tfact(own, 10.0);
    snxtsct_dist(&ns, x, y, lookrange);
    while (nxtsct(&ns, &sect) && wanted) {
	if (ns.curdist == 0)
	    continue;
	if (sect.sct_own != own)
	    continue;
	if ((sect.sct_type != SCT_WAREH) &&
	    (sect.sct_type != SCT_HEADQ) && (sect.sct_type != SCT_HARBR))
	    continue;
	if ((sect.sct_type == SCT_HEADQ) &&
	    (sect.sct_dist_x == sect.sct_x) &&
	    (sect.sct_dist_y == sect.sct_y))
	    continue;
	if (sect.sct_effic < 60)
	    continue;
	move_cost = path_find(sect.sct_x, sect.sct_y, x, y, own, MOB_MOVE);
	if (move_cost < 0)
	    continue;
	if (!opt_NOFOOD && type == I_FOOD)
	    minimum = 1 + (int)ceil(food_needed(sect.sct_item,
						etu_per_update));
	if (sect.sct_item[type] <= minimum)
	    continue;
	ip = &ichr[type];
	dp = &dchr[sect.sct_type];
	packing = ip->i_pkg[dp->d_pkg];
	if (packing > 1 && sect.sct_effic < 60)
	    packing = 1;
	weight = (double)ip->i_lbs / packing;
	mobcost = move_cost * weight;
	if (mobcost > 0)
	    can_move = (double)sect.sct_mobil / mobcost;
	else
	    can_move = sect.sct_item[type] - minimum;
	if (can_move > sect.sct_item[type] - minimum)
	    can_move = sect.sct_item[type] - minimum;

	if (can_move >= wanted) {
	    int n;

	    sect.sct_item[type] -= wanted;

	    /* take off mobility for delivering sect */
	    n = roundavg(wanted * weight * move_cost);
	    sect.sct_mobil -= LIMIT_TO(n, 0, sect.sct_mobil);
	    if (actually_doit) {
		vec[type] += wanted;
		putsect(&sect);
		put_empobj(sink->ef_type, sink->uid, sink);
	    }
	    return 1;
	} else if (can_move > 0) {
	    int n;
	    wanted -= can_move;
	    sect.sct_item[type] -= can_move;

	    /* take off mobility for delivering sect */
	    n = roundavg(can_move * weight * move_cost);
	    sect.sct_mobil -= LIMIT_TO(n, 0, sect.sct_mobil);
	    if (actually_doit) {
		vec[type] += can_move;
		putsect(&sect);
	    }
	}
    }

    /* look for an owned ship in a harbor */
    snxtitem_dist(&ni, EF_SHIP, x, y, lookrange);
    while (nxtitem(&ni, &ship) && wanted) {
	if (sink->ef_type == EF_SHIP && sink->uid == ship.shp_uid)
	    continue;
	if (ship.shp_own != own)
	    continue;
	if (!(mchr[(int)ship.shp_type].m_flags & M_SUPPLY))
	    continue;
	getsect(ship.shp_x, ship.shp_y, &sect);
	if (sect.sct_type != SCT_HARBR)
	    continue;
	if (sect.sct_effic < 2)
	    continue;
	move_cost = path_find(sect.sct_x, sect.sct_y, x, y, own, MOB_MOVE);
	if (move_cost < 0)
	    continue;
	if (!opt_NOFOOD && type == I_FOOD)
	    minimum = 1 + (int)ceil(food_needed(ship.shp_item,
						etu_per_update));
	if (ship.shp_item[type] <= minimum)
	    continue;
	ip = &ichr[type];
	dp = &dchr[sect.sct_type];
	packing = ip->i_pkg[dp->d_pkg];
	if (packing > 1 && sect.sct_effic < 60)
	    packing = 1;
	weight = (double)ip->i_lbs / packing;
	mobcost = move_cost * weight;
	if (mobcost > 0)
	    can_move = (double)sect.sct_mobil / mobcost;
	else
	    can_move = ship.shp_item[type] - minimum;
	if (can_move > ship.shp_item[type] - minimum)
	    can_move = ship.shp_item[type] - minimum;
	if (can_move >= wanted) {
	    int n;
	    ship.shp_item[type] -= wanted;

	    n = roundavg(wanted * weight * move_cost);
	    sect.sct_mobil -= LIMIT_TO(n, 0, sect.sct_mobil);
	    if (actually_doit) {
		vec[type] += can_move;
		putship(ship.shp_uid, &ship);
		if (n)
		    putsect(&sect);
		put_empobj(sink->ef_type, sink->uid, sink);
	    }
	    return 1;
	} else if (can_move > 0) {
	    int n;
	    wanted -= can_move;
	    ship.shp_item[type] -= can_move;

	    n = roundavg(can_move * weight * move_cost);
	    sect.sct_mobil -= LIMIT_TO(n, 0, sect.sct_mobil);
	    if (actually_doit) {
		vec[type] += can_move;
		putship(ship.shp_uid, &ship);
		if (n)
		    putsect(&sect);
	    }
	}
    }

    /* look for an owned supply unit */
    snxtitem_dist(&ni, EF_LAND, x, y, lookrange);
    while (nxtitem(&ni, &land) && wanted) {
	int min;

	if (sink->ef_type == EF_LAND && sink->uid == land.lnd_uid)
	    continue;
	if (land.lnd_own != own)
	    continue;

	lcp = &lchr[(int)land.lnd_type];
	if (!(lcp->l_flags & L_SUPPLY))
	    continue;

	if (land.lnd_item[type] <= get_minimum(&land, type))
	    continue;

	if (land.lnd_ship >= 0) {
	    getsect(land.lnd_x, land.lnd_y, &sect);
	    if (sect.sct_type != SCT_HARBR || sect.sct_effic < 2)
		continue;
	}

	move_cost = path_find(land.lnd_x, land.lnd_y, x, y, own, MOB_MOVE);
	if (move_cost < 0)
	    continue;

#if 0
	/*
	 * Recursive supply is disabled for now.  It can introduce
	 * cycles into the "resupplies from" relation.  The code below
	 * attempts to break these cycles by temporarily zapping the
	 * commodity being supplied.  That puts the land file in a
	 * funny state temporarily, risking loss of supplies when
	 * something goes wrong on the way.  Worse, it increases
	 * lnd_seqno even when !actually_doit, which can lead to
	 * spurious seqno mismatch oopses in users of
	 * lnd_could_be_supplied().  I can't be bothered to clean up
	 * this mess right now, because recursive resupply is too dumb
	 * to be really useful anyway: each step uses the first source
	 * it finds, without consideration of mobility cost.  If you
	 * re-enable it, don't forget to uncomment its documentation
	 * in supply.t as well.
	 */
	if (land.lnd_item[type] - wanted < get_minimum(&land, type)) {
	    struct lndstr save;

	    /*
	     * Temporarily zap this unit's store, so the recursion
	     * avoids it.
	     */
	    save = land;
	    land.lnd_item[type] = 0;
	    putland(land.lnd_uid, &land);
	    save.lnd_seqno = land.lnd_seqno;

	    s_commod((struct empobj *)&land, land.lnd_item, type, wanted,
		     lchr[land.lnd_type].l_item[type] - wanted,
		     actually_doit);
	    land.lnd_item[type] += save.lnd_item[type];

	    if (actually_doit)
		putland(land.lnd_uid, &land);
	    else
		putland(save.lnd_uid, &save);
	}
#endif

	min = get_minimum(&land, type);
	ip = &ichr[type];
	weight = ip->i_lbs;
	mobcost = move_cost * weight;
	if (mobcost > 0)
	    can_move = (double)land.lnd_mobil / mobcost;
	else
	    can_move = land.lnd_item[type] - min;
	if (can_move > land.lnd_item[type] - min)
	    can_move = land.lnd_item[type] - min;

	if (can_move >= wanted) {
	    land.lnd_item[type] -= wanted;
	    land.lnd_mobil -= roundavg(wanted * weight * move_cost);
	    if (actually_doit) {
		vec[type] += wanted;
		putland(land.lnd_uid, &land);
		put_empobj(sink->ef_type, sink->uid, sink);
	    }
	    return 1;
	} else if (can_move > 0) {
	    wanted -= can_move;
	    land.lnd_item[type] -= can_move;
	    land.lnd_mobil -= roundavg(can_move * weight * move_cost);
	    if (actually_doit) {
		vec[type] += can_move;
		putland(land.lnd_uid, &land);
	    }
	}
    }

    if (actually_doit)
	put_empobj(sink->ef_type, sink->uid, sink);
    return 0;
}
Exemplo n.º 10
0
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, &sect);
    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, &sect)) {
        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(&sect, 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(&sect);
        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, &sect1);

                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, &sect1);

                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, &sect1);

            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);
}
Exemplo n.º 11
0
/* 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;
}
Exemplo n.º 12
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, &sect);
	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(&sect, 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(&sect);
    }
    return 0;
}
Exemplo n.º 13
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;
}