Пример #1
0
/*
 * Dump @val prefixed with @sep to @xd, in machine readable format.
 * @val must be evaluated.
 * Return " ".
 */
static char *
xdprval_nosym(struct xdstr *xd, struct valstr *val, char *sep)
{
    if (CANT_HAPPEN(val->val_cat != NSC_VAL)) {
	xd->pr("%snil", sep);
	return " ";
    }

    switch (val->val_type) {
    case NSC_LONG:
	xd->pr("%s%ld", sep, val->val_as.lng);
	break;
    case NSC_DOUBLE:
	xd->pr("%s%#g", sep, val->val_as.dbl);
	break;
    case NSC_STRING:
	if (val->val_as.str.base) {
	    xd->pr("%s\"", sep);
	    xdpresc(xd, val->val_as.str.base, val->val_as.str.maxsz);
	    xd->pr("\"");
	} else
	    xd->pr("%snil", sep);
	break;
    default:
	CANT_REACH();
	xd->pr("%snil", sep);
    }
    return " ";
}
Пример #2
0
/*
 * Wipe orders and such from @unit.
 */
void
unit_wipe_orders(struct empobj *unit)
{
    struct shpstr *sp;
    struct plnstr *pp;
    struct lndstr *lp;

    unit->group = 0;
    unit->opx = unit->opy = 0;
    unit->mission = 0;
    unit->radius = 0;

    switch (unit->ef_type) {
    case EF_SHIP:
	sp = (struct shpstr *)unit;
	sp->shp_rflags = 0;
	sp->shp_rpath[0] = 0;
	break;
    case EF_PLANE:
	pp = (struct plnstr *)unit;
	pp->pln_range = pln_range_max(pp);
	break;
    case EF_LAND:
	lp = (struct lndstr *)unit;
	lp->lnd_retreat = morale_base;
	lp->lnd_rflags = 0;
	lp->lnd_rpath[0] = 0;
	break;
    case EF_NUKE:
	break;
    default:
	CANT_REACH();
    }
}
Пример #3
0
static void
takeover_unit(struct empobj *unit, natid newown)
{
    struct shpstr *sp;
    struct plnstr *pp;
    struct lndstr *lp;
    struct nukstr *np;
    int type;
    struct nstr_item ni;
    union empobj_storage cargo;

    unit->own = newown;
    if (opt_MARKET)
	trdswitchown(unit->ef_type, unit, newown);
    unit_wipe_orders(unit);

    switch (unit->ef_type) {
    case EF_SHIP:
	sp = (struct shpstr *)unit;
	sp->shp_off = 1;
	break;
    case EF_PLANE:
	pp = (struct plnstr *)unit;
	if (pp->pln_mobil > 0)
	    pp->pln_mobil = 0;
	pp->pln_off = 1;
	break;
    case EF_LAND:
	lp = (struct lndstr *)unit;
	if (lp->lnd_mobil > 0)
	    lp->lnd_mobil = 0;
	lp->lnd_off = 1;
	lp->lnd_harden = 0;
	break;
    case EF_NUKE:
	np = (struct nukstr *)unit;
	np->nuk_off = 1;
	break;
    default:
	CANT_REACH();
    }

    put_empobj(unit->ef_type, unit->uid, unit);

    for (type = EF_PLANE; type <= EF_NUKE; type++) {
	snxtitem_cargo(&ni, type, unit->ef_type, unit->uid);
	while (nxtitem(&ni, &cargo)) {
	    if (cargo.gen.own == newown)
		continue;
	    if (type == EF_PLANE)
		cargo.plane.pln_effic = PLANE_MINEFF;
	    takeover_unit(&cargo.gen, newown);
	}
    }
}
Пример #4
0
static int
cons_decline(struct ltcomstr *ltcp)
{
    switch (ltcp->type) {
    case EF_LOAN:
	return loan_decline(ltcp);
    default:
	CANT_REACH();
	return RET_FAIL;
    }
}
Пример #5
0
static int
cons_display(struct ltcomstr *ltcp)
{
    switch (ltcp->type) {
    case EF_LOAN:
	return disloan(ltcp->num, &ltcp->u.l);
    default:
	CANT_REACH();
	return 0;
    }
}
Пример #6
0
/*
 * Post-processing after successful acceptance of loan.
 * Notify the press, and the folks involved.
 * (Weird spelling is to avoid accept(2)).
 */
static void
accpt(struct ltcomstr *ltcp)
{
    switch (ltcp->type) {
    case EF_LOAN:
	nreport(ltcp->proposer, N_MAKE_LOAN, player->cnum, 1);
	break;
    default:
	CANT_REACH();
    }
    wu(0, ltcp->mailee, "%s #%d accepted by %s\n",
       ltcp->Name, ltcp->num, cname(player->cnum));
}
Пример #7
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";
}
Пример #8
0
double
sector_mcost(struct sctstr *sp, int mobtype)
{
    double base, cost;

    base = dchr[sp->sct_type].d_mob0;
    if (base < 0)
	return -1.0;

    if (mobtype == MOB_RAIL && opt_RAILWAYS) {
	if (!SCT_HAS_RAIL(sp))
	    return -1;
	mobtype = MOB_MARCH;
    }

    /* linear function in eff, d_mob0 at 0%, d_mob1 at 100% */
    base += (dchr[sp->sct_type].d_mob1 - base) * sp->sct_effic / 100;
    if (CANT_HAPPEN(base < 0))
	base = 0;

    if (mobtype == MOB_MOVE || mobtype == MOB_MARCH) {
	/* linear function in road, base at 0%, base/10 at 100% */
	cost = base;
	if (intrchr[INT_ROAD].in_enable)
	    cost -= base * 0.009 * sp->sct_road;
    } else if (mobtype == MOB_RAIL) {
	if (!intrchr[INT_RAIL].in_enable || sp->sct_rail <= 0)
	    return -1.0;
	/* linear function in rail, base at 0%, base/100 at 100% */
	cost = base - base * 0.0099 * sp->sct_rail;
    } else {
	CANT_REACH();
	cost = base;
    }
    if (CANT_HAPPEN(cost < 0))
	cost = 0;

    if (mobtype == MOB_MOVE)
	return MAX(cost, 0.001);
    if (sp->sct_own != sp->sct_oldown && sp->sct_mobil <= 0)
	/* slow down land units in newly taken sectors */
	return cost + 0.2;
    return MAX(cost, 0.02);
}
Пример #9
0
/*
 * Evaluate compiled conditions in array @np[@ncond].
 * Return non-zero iff they are all true.
 * @ptr points to a context object of the type that was used to compile
 * the conditions.
 */
int
nstr_exec(struct nscstr *np, int ncond, void *ptr)
{
    int i, op, cmp;
    enum nsc_type optype;
    struct valstr lft, rgt;

    for (i = 0; i < ncond; ++i) {
	op = np[i].operator;
	optype = np[i].optype;
	if (np[i].lft.val_cat == NSC_NOCAT || np[i].rgt.val_cat == NSC_NOCAT)
	    return 0;
	lft = np[i].lft;
	nstr_eval(&lft, player->cnum, ptr, optype);
	rgt = np[i].rgt;
	nstr_eval(&rgt, player->cnum, ptr, optype);
	if (CANT_HAPPEN(lft.val_type != optype || rgt.val_type != optype))
	    return 0;
	switch (optype) {
	case NSC_LONG:
	    if (!EVAL(op, lft.val_as.lng, rgt.val_as.lng))
		return 0;
	    break;
	case NSC_DOUBLE:
	    if (!EVAL(op, lft.val_as.dbl, rgt.val_as.dbl))
		return 0;
	    break;
	case NSC_STRING:
	    cmp = strnncmp(lft.val_as.str.base, lft.val_as.str.maxsz,
			   rgt.val_as.str.base, rgt.val_as.str.maxsz);
	    if (!EVAL(op, cmp, 0))
		return 0;
	    break;
	default:
	    CANT_REACH();
	    return 0;
	}
    }

    return 1;
}
Пример #10
0
void WINAPI
service_main(DWORD argc, LPTSTR *argv)
{
    int sig;

    service_status.dwServiceType	= SERVICE_WIN32;
    service_status.dwCurrentState	= SERVICE_START_PENDING;
    service_status.dwControlsAccepted	= SERVICE_ACCEPT_STOP;
    service_status.dwWin32ExitCode	= 0;
    service_status.dwServiceSpecificExitCode = 0;
    service_status.dwCheckPoint		= 0;
    service_status.dwWaitHint		= 0;

    service_status_handle = RegisterServiceCtrlHandler(
	DEFAULT_SERVICE_NAME, service_ctrl_handler);

    if (service_status_handle == (SERVICE_STATUS_HANDLE)0) {
	logerror("RegisterServiceCtrlHandler failed %lu\n", GetLastError());
	finish_server();
	return;
    }

    start_server(0);

    /* Initialization complete - report running status. */
    service_status.dwCurrentState	= SERVICE_RUNNING;
    service_status.dwCheckPoint		= 0;
    service_status.dwWaitHint		= 0;

    if (!SetServiceStatus (service_status_handle, &service_status)) {
	logerror("SetServiceStatus error %ld\n", GetLastError());
    }

    sig = empth_wait_for_signal();

    shutdwn(sig);

    CANT_REACH();
    finish_server();
}
Пример #11
0
int
cons(void)
{
    int rv;
    struct ltcomstr ltc;

    rv = cons_choose(&ltc);
    if (rv != RET_OK)
	return rv;

    switch (ltc.op) {
    case 'a':
	return cons_accept(&ltc);
    case 'd':
	return cons_decline(&ltc);
    case 'p':
	return cons_postpone(&ltc);
    default:
	CANT_REACH();
	return RET_SYN;
    }
}
Пример #12
0
int
powe(void)
{
    struct natstr *natp;
    int i;
    time_t pow_time;
    struct nstr_item ni;
    int save = 1;
    int num = MAXNOC;
    int power_generated = 0;
    struct natstr nat;
    struct powstr powbuf[MAXNOC];
    int targets[MAXNOC];
    int use_targets = 0;
    int no_numbers = 0;

    memset(targets, 0, sizeof(targets));

    i = 1;
    if (player->argp[1]) {
	switch (player->argp[1][0]) {
	case 'u':
	    if (player->god)
		save = 0;
	    /* fall through */
	case 'n':
	    i++;
	    natp = getnatp(player->cnum);
	    if (natp->nat_btu < 1)
		pr("\n  Insufficient BTUs, using the last report.\n\n");
	    else if (opt_AUTO_POWER && save)
		pr("\n  power new is disabled, using the last report.\n\n");
	    else {
		gen_power(powbuf, save);
		pow_time = time(NULL);
		power_generated = 1;
	    }
	}
    }

    if (player->argp[i]) {
	if (player->argp[i][0] == 'c') {
	    if (!snxtitem(&ni, EF_NATION, player->argp[i + 1], NULL))
		return RET_SYN;
	    while (nxtitem(&ni, &nat)) {
		if (nat.nat_stat == STAT_UNUSED)
		    continue;
		if (!player->god && nat.nat_stat != STAT_ACTIVE)
		    continue;
		targets[nat.nat_cnum] = 1;
	    }
	    use_targets = 1;
	} else
	    num = atoi(player->argp[i]);
    }

    if (num < 0) {
	if (!player->god)
	    return RET_SYN;
	num = -num;
	no_numbers = 1;
    }

    if (!power_generated) {
	pow_time = ef_mtime(EF_POWER);
	snxtitem_all(&ni, EF_POWER);
	if (!nxtitem(&ni, &powbuf[0])) {
	    pr("Power for this game has not been built yet.%s\n",
	       opt_AUTO_POWER ? "" : "  Type 'power new' to build it.");
	    return RET_FAIL;
	}
	for (i = 1; i < MAXNOC; i++) {
	    if (!nxtitem(&ni, &powbuf[i])) {
		CANT_REACH();
		memset(&powbuf[i], 0, sizeof(powbuf[i]));
	    }
	}
    }

    pr("     - = [   Empire Power Report   ] = -\n");
    pr("      as of %s\n         sects  eff civ", ctime(&pow_time));
    pr("  mil  shell gun pet  iron dust oil  pln ship unit money\n");
    for (i = 1; i < MAXNOC && num > 0; i++) {
	if (opt_HIDDEN) {
	    if (!player->god && powbuf[i].p_nation != player->cnum)
		continue;
	}
	if (use_targets && !targets[powbuf[i].p_nation])
	    continue;
	if (!use_targets && powbuf[i].p_power <= 0.0)
	    continue;
	prpower(cname(powbuf[i].p_nation), &powbuf[i],
		powbuf[i].p_nation != player->cnum && !player->god);
	if (player->god && !no_numbers)
	    pr("%9.2f\n", powbuf[i].p_power);
	num--;
    }
    if (!opt_HIDDEN || player->god) {
	pr("          ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----\n");
	prpower("worldwide", &powbuf[0], !player->god);
	pr("\n");
    }
    return RET_OK;
}
Пример #13
0
int
nxtitem(struct nstr_item *np, void *ptr)
{
    struct empobj *gp;
    int selected;

    if (np->sel == NS_UNDEF)
	return 0;
    gp = (struct empobj *)ptr;
    do {
	if (np->sel == NS_LIST) {
	    np->index++;
	    if (np->index >= np->size)
		return 0;
	    np->cur = np->list[np->index];
	} else if (np->sel == NS_CARGO) {
	    if (np->next < 0)
		return 0;
	    np->cur = np->next;
	    np->next = unit_cargo_next(np->type, np->next);
	} else {
	    np->cur++;
	}
	if (!ef_read(np->type, np->cur, ptr))
	    return 0;
	selected = 1;
	switch (np->sel) {
	case NS_LIST:
	case NS_CARGO:
	case NS_ALL:
	    break;
	case NS_DIST:
	    if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_XY)))
		return 0;
	    if (!xyinrange(gp->x, gp->y, &np->range)) {
		selected = 0;
		break;
	    }
	    np->curdist = mapdist(gp->x, gp->y, np->cx, np->cy);
	    if (np->curdist > np->dist)
		selected = 0;
	    break;
	case NS_AREA:
	    if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_XY)))
		return 0;
	    if (!xyinrange(gp->x, gp->y, &np->range))
		selected = 0;
	    break;
	case NS_XY:
	    if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_XY)))
		return 0;
	    if (xnorm(gp->x) != np->cx || ynorm(gp->y) != np->cy)
		selected = 0;
	    break;
	case NS_GROUP:
	    if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_GROUP)))
		return 0;
	    if (np->group != gp->group)
		selected = 0;
	    break;
	default:
	    CANT_REACH();
	    return 0;
	}
	if (selected && np->ncond) {
	    /* nstr_exec is expensive, so we do it last */
	    if (!nstr_exec(np->cond, np->ncond, ptr))
		selected = 0;
	}
    } while (!selected);
    return 1;
}
Пример #14
0
int
pln_airbase_ok(struct plnstr *pp, int oneway, int noisy)
{
    struct shpstr ship;
    struct lndstr land;
    struct sctstr sect;
    struct plchrstr *pcp = plchr + pp->pln_type;

    if (CANT_HAPPEN(noisy && pp->pln_own != player->cnum))
	noisy = 0;

    if (pp->pln_ship >= 0) {
	/* ship: needs to be own or allied, efficient */
	if (!getship(pp->pln_ship, &ship)) {
	    CANT_REACH();
	    return 0;
	}
	if (relations_with(ship.shp_own, pp->pln_own) != ALLIED) {
	    if (noisy)
		pr("(note) An ally does not own the ship %s is on\n",
		   prplane(pp));
	    return 0;
	}
	if (!(carrier_planes(&ship, pcp->pl_flags & P_M) & pcp->pl_flags))
	    return 0;

    } else if (pp->pln_land >= 0) {
	/* land: needs to be own or allied, efficient, not embarked */
	if (!getland(pp->pln_land, &land)) {
	    CANT_REACH();
	    return 0;
	}
	if (relations_with(land.lnd_own, pp->pln_own) != ALLIED) {
	    if (noisy)
		pr("(note) An ally does not own the unit %s is on\n",
		   prplane(pp));
	    return 0;
	}
	if (land.lnd_effic < LND_AIROPS_EFF || !(pcp->pl_flags & P_E))
	    return 0;
	if (land.lnd_ship >= 0 || land.lnd_land >= 0)
	    return 0;

    } else {
	/* sector: needs to be own or allied, efficient airfield */
	if (!getsect(pp->pln_x, pp->pln_y, &sect)) {
	    CANT_REACH();
	    return 0;
	}

	if (relations_with(sect.sct_own, pp->pln_own) != ALLIED) {
	    if (noisy)
		pr("(note) An ally does not own the sector %s is in\n",
		   prplane(pp));
	    return 0;
	}
	/* need airfield unless VTOL */
	if ((pcp->pl_flags & P_V) == 0) {
	    if (sect.sct_type != SCT_AIRPT) {
		if (noisy)
		    pr("%s not at airport\n", prplane(pp));
		return 0;
	    }
	    if (sect.sct_effic < 40) {
		if (noisy)
		    pr("%s is not 40%% efficient, %s can't take off from there.\n",
		       xyas(sect.sct_x, sect.sct_y, player->cnum),
		       prplane(pp));
		return 0;
	    }
	    if (!oneway && sect.sct_effic < 60) {
		if (noisy)
		    pr("%s is not 60%% efficient, %s can't land there.\n",
		       xyas(sect.sct_x, sect.sct_y, player->cnum),
		       prplane(pp));
		return 0;
	    }
	}
    }

    return 1;
}
Пример #15
0
/*ARGSUSED*/
void
player_accept(void *unused)
{
    static int conn_cnt;
    struct sockaddr *sap;
    struct player *np;
    socklen_t len;
    const char *p;
    int ns;
    int set = 1;
    int stacksize;
    char buf[128];
#ifdef RESOLVE_IPADDRESS
    struct hostent *hostp;
#endif

    /* auto sockaddr_storage would be simpler, but less portable */
    sap = malloc(player_addrlen);
    len = player_addrlen;
    if (getsockname(player_socket, sap, &len)) {
	logerror("getsockname() failed: %s", strerror(errno));
	p = NULL;
    } else {
	p = sockaddr_ntop(sap, buf, sizeof(buf));
	CANT_HAPPEN(!p);
    }
    logerror("Listening on %s", p ? buf : "unknown address");

    while (1) {
	empth_select(player_socket, EMPTH_FD_READ, NULL);
	len = player_addrlen;
	ns = accept(player_socket, sap, &len);
	/* FIXME accept() can block on some systems (RST after select() reports ready) */
	if (ns < 0) {
	    logerror("new socket accept");
	    continue;
	}
	(void)setsockopt(ns, SOL_SOCKET, SO_KEEPALIVE, &set, sizeof(set));
	np = player_new(ns);
	if (!np) {
	    logerror("can't create player for fd %d", ns);
	    close(ns);
	    continue;
	}
	if (!sockaddr_ntop(sap, np->hostaddr, sizeof(np->hostaddr))) {
	    CANT_REACH();
	    player_delete(np);
	    continue;
	}
	logerror("Connect from %s", np->hostaddr);
#ifdef RESOLVE_IPADDRESS
	hostp = gethostbyaddr(inaddr, player_addrlen, sap->sa_family);
	if (NULL != hostp)
	    strcpy(np->hostname, hostp->h_name);
#endif /* RESOLVE_IPADDRESS */
	/* FIXME ancient black magic; figure out true stack need */
	stacksize = 100000
/* budget */  + MAX(WORLD_SZ() * sizeof(int) * 7,
/* power */ MAXNOC * sizeof(struct powstr));
	sprintf(buf, "Conn%d", conn_cnt++);
	empth_create(player_login, stacksize, 0, buf, np);
    }
}
Пример #16
0
/*
 * Execute command named by player->argp[0].
 * BUF is the raw UTF-8 command line.  It should have been passed to
 * parse() to set up player->argp.
 * If REDIR is not null, it's the command's redirection, in UTF-8.
 * Return -1 if the command is not unique or doesn't exist, else 0.
 */
int
dispatch(char *buf, char *redir)
{
    struct natstr *np;
    struct cmndstr *command;
    int cmd;

    cmd = comtch(player->argp[0], player_coms, player->nstat);
    if (cmd < 0) {
	if (cmd == M_NOTUNIQUE)
	    pr("Command \"%s\" is ambiguous -- ", player->argp[0]);
	else if (cmd == M_IGNORE)
	    return 0;
	else
	    pr("\"%s\" is not a legal command\n", player->argp[0]);
	return -1;
    }
    command = &player_coms[cmd];
    np = getnatp(player->cnum);
    if (np->nat_btu < command->c_cost && command->c_cost > 0) {
	if (player->god || opt_BLITZ)
	    np->nat_btu = max_btus;
	else {
	    pr("You don't have the BTU's, bozo\n");
	    return 0;
	}
    }
    if (!command->c_addr) {
	pr("Command not implemented\n");
	return 0;
    }
    player->may_sleep = command->c_flags & C_MOD
	? PLAYER_SLEEP_ON_INPUT : PLAYER_SLEEP_FREELY;
    player->command = command;
    empth_rwlock_rdlock(update_lock);
    if (redir) {
	prredir(redir);
	uprnf(buf);
	pr("\n");
    }
    journal_command(command->c_form);
    switch (command->c_addr()) {
    case RET_OK:
	player->btused += command->c_cost;
	break;
    case RET_FAIL:
	pr("command failed\n");
	player->btused += command->c_cost;
	break;
    case RET_SYN:
	pr("Usage: %s\n", command->c_form);
	break;
    default:
	CANT_REACH();
	break;
    }
    empth_rwlock_unlock(update_lock);
    player->command = NULL;
    if (player->may_sleep != PLAYER_SLEEP_NEVER || !io_eof(player->iop))
	player->may_sleep = PLAYER_SLEEP_FREELY;
    /* else we're being kicked out */
    return 0;
}
Пример #17
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;
}
Пример #18
0
int
edit(void)
{
    union empobj_storage item;
    char *what;
    struct nstr_item ni;
    char *key, *ptr;
    struct natstr *np;
    int type, arg_index, ret;
    char buf[1024];

    what = getstarg(player->argp[1],
		    "Edit what (country, land, ship, plane, nuke, unit)? ",
		    buf);
    if (!what)
	return RET_SYN;
    switch (what[0]) {
    case 'l':
	type = EF_SECTOR;
	break;
    case 'p':
	type = EF_PLANE;
	break;
    case 's':
	type = EF_SHIP;
	break;
    case 'u':
	type = EF_LAND;
	break;
    case 'n':
	type = EF_NUKE;
	break;
    case 'c':
	type = EF_NATION;
	break;
    default:
	pr("huh?\n");
	return RET_SYN;
    }

    if (!snxtitem(&ni, type, player->argp[2], NULL))
	return RET_SYN;
    while (nxtitem(&ni, &item)) {
	if (!player->argp[3]) {
	    switch (type) {
	    case EF_SECTOR:
		print_sect(&item.sect);
		break;
	    case EF_SHIP:
		print_ship(&item.ship);
		break;
	    case EF_PLANE:
		print_plane(&item.plane);
		break;
	    case EF_LAND:
		print_land(&item.land);
		break;
	    case EF_NUKE:
		print_nuke(&item.nuke);
		break;
	    case EF_NATION:
		print_nat(&item.nat);
		break;
	    default:
		CANT_REACH();
	    }
	}

	arg_index = 3;
	for (;;) {
	    if (player->argp[arg_index]) {
		if (player->argp[arg_index+1]) {
		    key = player->argp[arg_index++];
		    ptr = player->argp[arg_index++];
		} else
		    return RET_SYN;
	    } else if (arg_index == 3) {
		key = getin(buf, &ptr);
		if (!key)
		    return RET_SYN;
		if (!*key)
		    break;
	    } else
		break;

	    if (!check_obj_ok(&item.gen))
		return RET_FAIL;
	    switch (type) {
	    case EF_NATION:
		/*
		 * edit_nat() may update the edited country by sending
		 * it bulletins.  Writing back item.nat would trigger
		 * a seqno mismatch oops.  Workaround: edit in-place.
		 */
		np = getnatp(item.nat.nat_cnum);
		ret = edit_nat(np, key, ptr);
		if (ret != RET_OK)
		    return ret;
		if (!putnat(np))
		    return RET_FAIL;
		item.nat = *np;
		continue;
	    case EF_SECTOR:
		ret = edit_sect(&item.sect, key, ptr);
		break;
	    case EF_SHIP:
		ret = edit_ship(&item.ship, key, ptr);
		break;
	    case EF_LAND:
		ret = edit_land(&item.land, key, ptr);
		break;
	    case EF_PLANE:
		ret = edit_plane(&item.plane, key, ptr);
		break;
	    case EF_NUKE:
		ret = edit_nuke(&item.nuke, key, ptr);
		break;
	    default:
		CANT_REACH();
	    }
	    if (ret != RET_OK)
		return ret;
	    if (!put_empobj(type, item.gen.uid, &item.gen))
		return RET_FAIL;
	}
    }

    return RET_OK;
}