Пример #1
0
static int
still_ok_ship(struct sctstr *sectp, struct shpstr *shipp)
{
    if (!check_sect_ok(sectp))
	return 0;
    if (!check_ship_ok(shipp))
	return 0;
    return 1;
}
Пример #2
0
int
tend(void)
{
    struct nstr_item targets;
    struct nstr_item tenders;
    struct shpstr tender;
    struct shpstr target;
    struct ichrstr *ip;
    struct mchrstr *vbase;
    int amt;
    int retval;
    int ontender;
    int ontarget;
    int maxtender;
    int maxtarget;
    int transfer;
    int total;
    int type;
    char *p;
    char prompt[512];
    char buf[1024];

    p = getstarg(player->argp[1], "Tend what commodity (or 'land')? ",
		 buf);
    if (!p || !*p)
	return RET_SYN;

    if (!strncmp(p, "land", 4))
	type = EF_LAND;
    else if (NULL != (ip = item_by_name(p)))
	type = EF_SECTOR;
    else {
	pr("Can't tend '%s'\n", p);
	return RET_SYN;
    }

    if (!snxtitem(&tenders, EF_SHIP, player->argp[2], "Tender(s)? "))
	return RET_SYN;

    while (nxtitem(&tenders, &tender)) {
	if (!player->owner)
	    continue;
	if (type == EF_LAND) {
	    sprintf(prompt, "Land unit(s) to tend from %s? ",
		    prship(&tender));
	    p = getstarg(player->argp[3], prompt, buf);
	    if (!p)
		return RET_FAIL;
	    if (!*p)
		continue;
	    if (!check_ship_ok(&tender))
		return RET_SYN;
	    if (0 != (retval = tend_land(&tender, p)))
		return retval;
	    continue;
	}
	sprintf(prompt, "Number of %s to tend from %s? ",
		ip->i_name, prship(&tender));
	p = getstarg(player->argp[3], prompt, buf);
	if (!p)
	    return RET_FAIL;
	if (!*p)
	    continue;
	if (!check_ship_ok(&tender))
	    return RET_SYN;
	if (!(amt = atoi(p))) {
	    pr("Amount must be non-zero!\n");
	    return RET_SYN;
	}
	ontender = tender.shp_item[ip->i_uid];
	if (ontender == 0 && amt > 0) {
	    pr("No %s on %s\n", ip->i_name, prship(&tender));
	    return RET_FAIL;
	}
	vbase = &mchr[(int)tender.shp_type];
	maxtender = vbase->m_item[ip->i_uid];
	if (maxtender == 0) {
	    pr("A %s cannot hold any %s\n",
	       mchr[(int)tender.shp_type].m_name, ip->i_name);
	    break;
	}
	if (!snxtitem(&targets, EF_SHIP,
		      player->argp[4], "Ships to be tended? "))
	    return RET_FAIL;
	if (!check_ship_ok(&tender))
	    return RET_SYN;
	total = 0;
	while (nxtitem(&targets, &target)) {
	    if (!player->owner
		&& relations_with(target.shp_own, player->cnum) < FRIENDLY)
		continue;
	    if (target.shp_uid == tender.shp_uid)
		continue;
	    if (tender.shp_x != target.shp_x ||
		tender.shp_y != target.shp_y)
		continue;
	    if (ip->i_uid == I_CIVIL && tender.shp_own != target.shp_own)
		continue;
	    ontarget = target.shp_item[ip->i_uid];
	    vbase = &mchr[(int)target.shp_type];
	    maxtarget = vbase->m_item[ip->i_uid];
	    if (amt < 0) {
		/* take from target and give to tender */
		if (!player->owner)
		    continue;
		if (ontarget == 0) {
		    pr("No %s on %s\n", ip->i_name, prship(&target));
		    continue;
		}
		transfer = MIN(ontarget, -amt);
		transfer = MIN(maxtender - ontender, transfer);
		if (transfer == 0)
		    continue;
		target.shp_item[ip->i_uid] = ontarget - transfer;
		ontender += transfer;
		total += transfer;
	    } else {
		/* give to target from tender */
		transfer = MIN(ontender, amt);
		transfer = MIN(transfer, maxtarget - ontarget);
		if (transfer == 0)
		    continue;
		target.shp_item[ip->i_uid] = ontarget + transfer;
		ontender -= transfer;
		total += transfer;
		if (transfer && target.shp_own != player->cnum) {
		    wu(0, target.shp_own, "%s tended %d %s to %s\n",
		       cname(player->cnum), total, ip->i_name,
		       prship(&target));
		}
	    }
	    expose_ship(&tender, &target);
	    putship(target.shp_uid, &target);
	    if (amt > 0 && ontender == 0) {
		pr("%s out of %s\n", prship(&tender), ip->i_name);
		break;
	    }
	}
	pr("%d total %s transferred %s %s\n",
	   total, ip->i_name, (amt > 0) ? "off of" : "to",
	   prship(&tender));
	tender.shp_item[ip->i_uid] = ontender;
	tender.shp_mission = 0;
	putship(tender.shp_uid, &tender);
    }
    return RET_OK;
}
Пример #3
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;
}
Пример #4
0
int
orde(void)
{
    int sub, level;
    int scuttling = 0;
    struct nstr_item nb;
    struct shpstr ship;
    struct ichrstr *i1;
    coord p0x, p0y, p1x, p1y;
    int i;
    char *p, *p1, *dest;
    char buf1[128];
    char buf[1024];
    char prompt[128];

    if (!snxtitem(&nb, EF_SHIP, player->argp[1], NULL))
	return RET_SYN;
    while (!player->aborted && nxtitem(&nb, (&ship))) {
	if (!player->owner || ship.shp_own == 0)
	    continue;
	if (opt_SAIL) {
	    if (*ship.shp_path) {
		pr("Ship #%d has a \"sail\" path!\n", ship.shp_uid);
		continue;
	    }
	}
	sprintf(prompt,
		"Ship #%d, declare, cancel, suspend, resume, level? ",
		ship.shp_uid);
	p = getstarg(player->argp[2], prompt, buf);
	if (player->aborted || !p || !*p)
	    return RET_FAIL;
	if (!check_ship_ok(&ship))
	    return RET_FAIL;
	switch (*p) {
	default:
	    pr("Bad order type!\n");
	    return RET_SYN;
	case 'c':		/* clear ship fields  */
	    ship.shp_mission = 0;
	    ship.shp_autonav &= ~(AN_AUTONAV + AN_STANDBY + AN_LOADING);
	    for (i = 0; i < TMAX; i++) {
		ship.shp_tstart[i] = I_NONE;
		ship.shp_tend[i] = I_NONE;
		ship.shp_lstart[i] = 0;
		ship.shp_lend[i] = 0;
	    }
	    break;
	case 's':		/* suspend ship movement  */
	    ship.shp_mission = 0;
	    ship.shp_autonav |= AN_STANDBY;
	    break;
	case 'r':		/* resume ship movement   */
	    ship.shp_mission = 0;
	    ship.shp_autonav &= ~AN_STANDBY;
	    break;
	case 'd':		/* declare path */
	    scuttling = 0;
	    /* Need location */
	    p = getstarg(player->argp[3], "Destination? ", buf);
	    if (!p || !*p)
		return RET_SYN;
	    if (!sarg_xy(p, &p0x, &p0y))
		return RET_SYN;
	    p1x = p0x;
	    p1y = p0y;

	    p = getstarg(player->argp[4], "Second dest? ", buf);
	    if (!p)
		return RET_FAIL;
	    if (!check_ship_ok(&ship))
		return RET_FAIL;
	    if (!*p || !strcmp(p, "-")) {
		pr("A one-way order has been accepted.\n");
	    } else if (!strncmp(p, "s", 1)) {
		if (!(mchr[(int)ship.shp_type].m_flags & M_TRADE)) {
		    pr("You can't auto-scuttle that ship!\n");
		    return RET_SYN;
		}
		pr("A scuttle order has been accepted.\n");
		scuttling = 1;
	    } else {
		if (!sarg_xy(p, &p1x, &p1y))
		    return RET_SYN;
		pr("A circular order has been accepted.\n");
	    }

	    /*
	     *  Set new destination and trade type fields.
	     */
	    ship.shp_mission = 0;
	    ship.shp_destx[1] = p1x;
	    ship.shp_desty[1] = p1y;
	    ship.shp_destx[0] = p0x;
	    ship.shp_desty[0] = p0y;

	    ship.shp_autonav &= ~(AN_STANDBY | AN_LOADING);
	    ship.shp_autonav |= AN_AUTONAV;

	    if (scuttling)
		ship.shp_autonav |= AN_SCUTTLE;
	    break;

	    /* set cargo levels on the ship */

	case 'l':
	    /* convert player->argp[3] to an integer */
	    sprintf(buf1, "Field (1-%d) ", TMAX);
	    if (!getstarg(player->argp[3], buf1, buf))
		return RET_SYN;
	    if (!check_ship_ok(&ship))
		return RET_FAIL;
	    sub = atoi(buf);
	    /* check to make sure value in within range. */
	    if (sub > TMAX || sub < 1) {
		pr("Value must range from 1 to %d\n", TMAX);
		return RET_FAIL;
	    }

	    /* to keep sub in range of our arrays
	       subtract 1 so the new range is 0-(TMAX-1)
	     */
	    sub = sub - 1;;

	    if (ship.shp_autonav & AN_AUTONAV) {
		dest = getstarg(player->argp[4], "Start or end? ", buf);
		if (!dest)
		    return RET_FAIL;
		switch (*dest) {
		default:
		    pr("You must enter 'start' or 'end'\n");
		    return RET_SYN;
		case 'e':
		case 'E':
		    i1 = whatitem(player->argp[5], "Commodity? ");
		    if (!i1)
			return RET_FAIL;
		    p1 = getstarg(player->argp[6], "Amount? ", buf);
		    if (!p1)
			return RET_SYN;
		    if (!check_ship_ok(&ship))
			return RET_FAIL;
		    level = atoi(p1);
		    if (level < 0) {
			level = 0;	/* prevent negatives. */
			pr("You must use positive number! Level set to 0.\n");
		    }
		    ship.shp_tstart[sub] = i1->i_uid;
		    ship.shp_lstart[sub] = level;
		    pr("Order set\n");
		    break;
		case 's':
		case 'S':
		    i1 = whatitem(player->argp[5], "Commodity? ");
		    if (!i1)
			return RET_FAIL;
		    p1 = getstarg(player->argp[6], "Amount? ", buf);
		    if (!p1)
			return RET_SYN;
		    if (!check_ship_ok(&ship))
			return RET_FAIL;
		    level = atoi(p1);
		    if (level < 0) {
			level = 0;
			pr("You must use positive number! Level set to 0.\n");
		    }
		    ship.shp_tend[sub] = i1->i_uid;
		    ship.shp_lend[sub] = level;
		    pr("Order Set \n");
		    break;
		}
	    } else
		pr("You need to 'declare' a ship path first, see 'info order'\n");

	    break;
	}			/* end of switch (*p) */



	/*
	 *  Set loading flag if ship is already in one
	 *  of the specified harbors and a cargo has been
	 *  specified.
	 */

	if (((ship.shp_x == ship.shp_destx[0])
	     && (ship.shp_y == ship.shp_desty[0])
	     && (ship.shp_lstart[0] != ' '))
	    || ((ship.shp_x == ship.shp_desty[1])
		&& (ship.shp_y == ship.shp_desty[1])
		&& (ship.shp_lstart[1] != ' '))) {

	    coord tcord;
	    i_type tcomm;
	    short lev[TMAX];
	    int i;

	    ship.shp_autonav |= AN_LOADING;

	    /*  swap variables, this keeps
	       the load_it() procedure happy. CZ
	     */
	    tcord = ship.shp_destx[0];
	    ship.shp_destx[0] = ship.shp_destx[1];
	    ship.shp_destx[1] = tcord;
	    tcord = ship.shp_desty[0];
	    ship.shp_desty[0] = ship.shp_desty[1];
	    ship.shp_desty[1] = tcord;

	    for (i = 0; i < TMAX; i++) {
		lev[i] = ship.shp_lstart[i];
		ship.shp_lstart[i] = ship.shp_lend[i];
		ship.shp_lend[i] = lev[i];
		tcomm = ship.shp_tstart[i];
		ship.shp_tstart[i] = ship.shp_tend[i];
		ship.shp_tend[i] = tcomm;
	    }
	}

	putship(ship.shp_uid, &ship);
    }
    return RET_OK;
}
Пример #5
0
int
torp(void)
{
    natid vshipown;
    int range;
    int dam;
    int subno;
    int victno;
    int erange;
    double hitchance;
    struct shpstr vship;
    struct shpstr sub;
    struct mchrstr *sub_mcp;
    char *ptr;
    struct nstr_item nbst;
    char buf[1024];
    int ntorping = 0;
    char prompt[128];

    if (!snxtitem(&nbst, EF_SHIP, player->argp[1], "From ship(s)? "))
	return RET_SYN;
    while (nxtitem(&nbst, &sub)) {
	if (sub.shp_own != player->cnum)
	    continue;
	if ((mchr[(int)sub.shp_type].m_flags & M_TORP) == 0)
	    continue;
	if (sub.shp_item[I_GUN] == 0
	    || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS)
	    continue;
	if (sub.shp_item[I_MILIT] < 1)
	    continue;
	if (sub.shp_effic < 60)
	    continue;
	if (sub.shp_mobil <= 0)
	    continue;
	ntorping++;
    }
    pr("%d ships are eligible to torpedo\n", ntorping);
    snxtitem_rewind(&nbst);
    while (nxtitem(&nbst, &sub)) {
	if (!sub.shp_own)
	    continue;
	if (sub.shp_own != player->cnum) {
	    continue;
	}
	sub_mcp = &mchr[sub.shp_type];
	if (!(sub_mcp->m_flags & M_TORP)) {
	    pr("Ship # %d: A %s can't fire torpedoes!\n",
	       sub.shp_uid, sub_mcp->m_name);
	    continue;
	}
	if (sub.shp_item[I_GUN] == 0
	    || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS) {
	    pr("Ship #%d has insufficient armament\n", sub.shp_uid);
	    continue;
	}
	if (sub.shp_item[I_MILIT] < 1) {
	    pr("Ship #%d has insufficient crew\n", sub.shp_uid);
	    continue;
	}
	if (sub.shp_effic < 60) {
	    pr("Ship #%d torpedo tubes inoperative.\n", sub.shp_uid);
	    continue;
	}
	if (sub.shp_mobil <= 0) {
	    pr("Ship #%d has insufficient mobility\n", sub.shp_uid);
	    continue;
	}
	subno = sub.shp_uid;
	sprintf(prompt, "Ship %d, target? ", sub.shp_uid);
	if (!(ptr = getstarg(player->argp[2], prompt, buf)))
	    return RET_SYN;
	if (!check_ship_ok(&sub))
	    return RET_FAIL;
	if ((victno = atoi(ptr)) < 0)
	    return RET_SYN;
	if (!getship(victno, &vship))
	    return RET_FAIL;
	if (!vship.shp_own)
	    return RET_FAIL;
	vshipown = vship.shp_own;
	if (victno == subno) {
	    pr("Shooting yourself, eh?  How strange...\n");
	    continue;
	}
	if (mchr[(int)vship.shp_type].m_flags & M_SUB) {
	    if (!(sub_mcp->m_flags & M_SUBT)) {
		pr("You can't torpedo a submarine!\n");
		continue;
	    }
	}
	dam = shp_torp(&sub, 1);
	sub.shp_mission = 0;
	putship(sub.shp_uid, &sub);
	if (CANT_HAPPEN(dam < 0)) {
	    pr("Ship #%d has insufficient armament\n", sub.shp_uid);
	    continue;
	}

	if (!(sub_mcp->m_flags & M_SUB)) {
	    pr("Starting our attack run...\n");
	    anti_torp(sub.shp_uid, ntorping, vshipown);
	}
	getship(sub.shp_uid, &sub);
	if (sub.shp_own == 0)
	    continue;

	erange = roundrange(torprange(&sub));
	pr("Effective torpedo range is %d.0\n", erange);
	pr("Whooosh... ");
	getship(victno, &vship);
	vshipown = vship.shp_own;
	range = mapdist(sub.shp_x, sub.shp_y, vship.shp_x, vship.shp_y);
	hitchance = shp_torp_hitchance(&sub, range);
	if (range <= erange) {
	    pr("Hitchance = %.0f%%\n", hitchance * 100);
	}
	if (range > erange)
	    pr("Out of range\n");
	else if (!line_of_sight(NULL, sub.shp_x, sub.shp_y,
				vship.shp_x, vship.shp_y)) {
	    pr("BOOM!... Torpedo slams into land before reaching target.\n");
	    /* We only tell the victim if we were within range. */
	    if (vshipown != 0 && vshipown != player->cnum)
		wu(0, vshipown, "Torpedo sighted @ %s by %s\n",
		   xyas(sub.shp_x, sub.shp_y, vshipown),
		   prship(&vship));
	} else if (chance(hitchance)) {
	    pr("BOOM!...\n");
	    if (vshipown != 0 && vshipown != player->cnum)
		wu(0, vshipown, "%s in %s torpedoed %s for %d damage.\n",
		   sub_mcp->m_flags & M_SUB ? "sub" : prship(&sub),
		   xyas(sub.shp_x, sub.shp_y, vshipown),
		   prship(&vship), dam);
	    pr("Torpedo hit %s for %d damage.\n", prsub(&vship), dam);
	    if (!(mchr[vship.shp_type].m_flags & M_SUB)) {
		if (mchr[sub.shp_type].m_flags & M_SUB)
		    nreport(vshipown, N_TORP_SHIP, 0, 1);
		else
		    nreport(vshipown, N_SHIP_TORP, player->cnum, 1);
	    }
	    shipdamage(&vship, dam);
	    if (vship.shp_effic < SHIP_MINEFF)
		pr("%s sunk!\n", prsub(&vship));
	    if (vship.shp_rflags & RET_TORPED)
		retreat_ship(&vship, vshipown, 't');
	    putship(vship.shp_uid, &vship);
	} else {
	    pr("Missed\n");
	    if (vshipown != 0 && vshipown != player->cnum)
		wu(0, vshipown, "Torpedo sighted @ %s by %s\n",
		   xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship));
	}

	if (sub_mcp->m_flags & M_SUB)
	    anti_torp(sub.shp_uid, ntorping, vshipown);
    }
    return RET_OK;
}
Пример #6
0
int
mobq(void)
{
    struct shpstr ship;
    char *cp, *oldmq;
    int good, mobquota, count = 0;
    struct nstr_item nstr;
    char buf[1024];

    if (!opt_SAIL) {
	pr("The SAIL option is not enabled, so this command is not valid.\n");
	return RET_FAIL;
    }
    if (!snxtitem(&nstr, EF_SHIP, player->argp[1], NULL))
	return RET_SYN;
    oldmq = player->argp[2];
    if (oldmq) {
	good = sscanf(oldmq, "%d", &mobquota);
	if (!good)
	    return RET_SYN;
	if (mobquota < 0 || mobquota > ship_mob_max) {
	    pr("Bad mobility quota value %d.\n", mobquota);
	    return RET_SYN;
	}
	if (mobquota + (ship_mob_scale * (float)etu_per_update) >
	    ship_mob_max) {
	    pr("warning: %d less than optimal\n", mobquota);
	}
    }
    while (nxtitem(&nstr, &ship)) {
	if (!player->owner)
	    continue;
	if (!oldmq)
	    pr("Ship #%d at %s.  Old value %d.\n", ship.shp_uid,
	       xyas(ship.shp_x, ship.shp_y, player->cnum),
	       ship.shp_mobquota);
	cp = getstarg(player->argp[2], "mobility quota? ", buf);
	if (!cp)
	    return RET_SYN;
	if (!check_ship_ok(&ship))
	    continue;
	good = sscanf(cp, "%d", &mobquota);
	if (!good) {
	    pr("Huh?\n");
	    continue;
	}
	if (!oldmq) {
	    if (mobquota < 0 || mobquota > ship_mob_max) {
		pr("Bad mobility quota value %d.\n", mobquota);
		continue;
	    }
	    if (mobquota + (ship_mob_scale * (float)etu_per_update) >
		ship_mob_max) {
		pr("warning: %d less than optimal\n", mobquota);
	    }
	}
	ship.shp_mobquota = mobquota;
	count++;
	putship(ship.shp_uid, &ship);
    }
    if (count == 0) {
	if (player->argp[1])
	    pr("%s: No ship(s)\n", player->argp[1]);
	else
	    pr("%s: No ship(s)\n", "");
	return RET_FAIL;
    } else
	pr("%d ship%s\n", count, splur(count));
    return RET_OK;
}