コード例 #1
0
/*
 * Update @owner's bmap for radar at @cx,@cy.
 * @eff is the radar's efficiency, @tlev its tech level, @spy its power.
 */
void
rad_map_set(natid owner, int cx, int cy, int eff, double tlev, int spy)
{
    struct nstr_sect ns;
    struct sctstr sect;
    int range = rad_range(eff, tlev, spy);
    int changed = 0;
    char ch;

    snxtsct_dist(&ns, cx, cy, range);
    while (nxtsct(&ns, &sect)) {
	ch = rad_char(&sect, ns.curdist, range, owner);
	changed += map_set(owner, ns.x, ns.y, ch, 0);
    }
    if (changed)
	writemap(owner);
}
コード例 #2
0
ファイル: move.c プロジェクト: fstltna/empserver
/*ARGSUSED*/
static int
move_map(coord curx, coord cury, char *arg)
{
    struct nstr_sect ns;
    struct sctstr sect;
    char view[7];
    int i;
    int changed = 0;

    snxtsct_dist(&ns, curx, cury, 1);
    i = 0;
    while (i < 7 && nxtsct(&ns, &sect)) {
	/* Nasty: this relies on the iteration order */
	view[i] = dchr[sect.sct_type].d_mnem;
	switch (sect.sct_type) {
	case SCT_WATER:
	case SCT_RURAL:
	case SCT_MOUNT:
	case SCT_WASTE:
	case SCT_PLAINS:
	    break;
	default:
	    if (sect.sct_own != player->cnum && !player->god)
		view[i] = '?';
	    break;
	}
	changed += map_set(player->cnum, ns.x, ns.y, view[i], 0);
	i++;
    }
    if (changed)
	writemap(player->cnum);
    if (!getsect(curx, cury, &sect))
	return RET_FAIL;
    pr("    %c %c      eff   mob   civ  mil   uw food  work  avail\n",
       view[0], view[1]);
    pr("   %c %c %c     %3d   %3d  %4d %4d %4d %4d   %3d   %3d\n",
       view[2], view[3], view[4],
       sect.sct_effic, sect.sct_mobil,
       sect.sct_item[I_CIVIL], sect.sct_item[I_MILIT], sect.sct_item[I_UW],
       sect.sct_item[I_FOOD], sect.sct_work, sect.sct_avail);
    pr("    %c %c\n", view[5], view[6]);
    return RET_OK;
}
コード例 #3
0
/*
 * setup the nstr_sect structure for sector selection.
 * can select on either NS_ALL, NS_AREA, or NS_DIST
 * iterate thru the "condarg" string looking
 * for arguments to compile into the nstr.
 * Using this function for anything but command arguments is usually
 * incorrect, because it respects conditionals.  Use the snxtsct_FOO()
 * instead.
 */
int
snxtsct(struct nstr_sect *np, char *str)
{
    struct range range;
    struct natstr *natp;
    coord cx, cy;
    int dist;
    char buf[1024];

    if (!str || !*str) {
	if (!(str = getstring("(sects)? ", buf)))
	    return 0;
    } else
	make_stale_if_command_arg(str);
    switch (sarg_type(str)) {
    case NS_AREA:
	if (!sarg_area(str, &range))
	    return 0;
	snxtsct_area(np, &range);
	break;
    case NS_DIST:
	if (!sarg_range(str, &cx, &cy, &dist))
	    return 0;
	snxtsct_dist(np, cx, cy, dist);
	break;
    case NS_ALL:
	/*
	 * Can't use snxtsct_all(), as it would disclose the real
	 * origin.  Use a world-sized area instead.
	 */
	natp = getnatp(player->cnum);
	range.lx = xabs(natp, -WORLD_X / 2);
	range.ly = yabs(natp, -WORLD_Y / 2);
	range.hx = xnorm(range.lx + WORLD_X - 1);
	range.hy = ynorm(range.ly + WORLD_Y - 1);
	xysize_range(&range);
	snxtsct_area(np, &range);
	break;
    default:
	return 0;
    }
    return snxtsct_use_condarg(np);
}
コード例 #4
0
ファイル: move.c プロジェクト: fstltna/empserver
int
fly_map(coord curx, coord cury)
{
    struct nstr_sect ns;
    struct sctstr sect;
    char view[7];
    int i;

    snxtsct_dist(&ns, curx, cury, 1);
    i = 0;
    while (i < 7 && nxtsct(&ns, &sect)) {
	/* Nasty: this relies on the iteration order */
	if (!(view[i] = player->bmap[sect.sct_uid]))
	    view[i] = ' ';
	i++;
    }

    pr("    %c %c\n", view[0], view[1]);
    pr("   %c %c %c\n", view[2], view[3], view[4]);
    pr("    %c %c\n", view[5], view[6]);
    return RET_OK;
}
コード例 #5
0
int
sona(void)
{
    struct nstr_item ni, nit;
    struct sctstr sect;
    struct shpstr ship;
    struct shpstr targ;
    struct natstr *natp;
    struct mchrstr *mcp;
    struct mchrstr *tmcp;
    struct nstr_sect ns;
    int range;
    int visib, pingrange;
    int srange;
    int vrange;
    int dist;
    int x, y;
    int cx, cy;
    int changed = 0;
    int row;
    /* Where these are used are non-re-entrant, so we keep 'em around */
    static char **rad = NULL;
    static char *radbuf = NULL;
    static signed char **vis = NULL;
    static signed char *visbuf = NULL;

    if (!snxtitem(&ni, EF_SHIP, player->argp[1], NULL))
	return RET_SYN;
    if (!radbuf)
	radbuf = malloc(WORLD_Y * MAPWIDTH(1));
    if (!visbuf)
	visbuf = malloc(WORLD_Y * MAPWIDTH(1));
    if (!rad && radbuf) {
	rad = malloc(WORLD_Y * sizeof(char *));
	if (rad) {
	    for (x = 0; x < WORLD_Y; x++) {
		rad[x] = &radbuf[(WORLD_X + 1) * x];
	    }
	}
    }
    if (!vis && visbuf) {
	vis = malloc(WORLD_Y * sizeof(signed char *));
	if (vis) {
	    for (x = 0; x < WORLD_Y; x++) {
		vis[x] = &visbuf[(WORLD_X + 1) * x];
	    }
	}
    }
    if (!radbuf || !visbuf || !rad || !vis) {
	pr("Memory error, tell the deity.\n");
	logerror("malloc failed in sona\n");
	return RET_FAIL;
    }
    while (nxtitem(&ni, &ship)) {
	if (!player->owner)
	    continue;
	mcp = &mchr[(int)ship.shp_type];
	if (!(mcp->m_flags & M_SONAR))
	    continue;
	getsect(ship.shp_x, ship.shp_y, &sect);
	if (sect.sct_type != SCT_WATER)
	    continue;
	range = (int)techfact(ship.shp_tech, mcp->m_vrnge);
	srange = MIN(7, 7 * range * ship.shp_effic / 200);
	pr("%s at %s efficiency %d%%, max range %d\n",
	   prship(&ship),
	   xyas(ship.shp_x, ship.shp_y, player->cnum),
	   ship.shp_effic, srange);
	snxtsct_dist(&ns, ship.shp_x, ship.shp_y, srange);
	blankfill(radbuf, &ns.range, 1);
	while (nxtsct(&ns, &sect)) {
	    if (player->owner || sect.sct_type == SCT_WATER)
		rad[ns.dy][ns.dx] = dchr[sect.sct_type].d_mnem;
	    else {
		rad[ns.dy][ns.dx] = '?';
	    }
	}
	snxtsct_dist(&ns, ship.shp_x, ship.shp_y, srange);
	cx = deltx(&ns.range, ship.shp_x);
	cy = delty(&ns.range, ship.shp_y);
	while (nxtsct(&ns, &sect)) {
	    if (!line_of_sight(rad, cx, cy, ns.dx, ns.dy)) {
		rad[ns.dy][ns.dx] = ' ';
		continue;
	    }
	    if (ship.shp_tech >= 310 && sect.sct_type == SCT_WATER) {
		if (sect.sct_mines) {
		    pr("Sonar detects %d mines in %s!\n",
		       sect.sct_mines,
		       xyas(sect.sct_x, sect.sct_y, player->cnum));
		    rad[ns.dy][ns.dx] = 'X';
		}
	    }
	    changed |= map_set(player->cnum, sect.sct_x, sect.sct_y,
			       rad[ns.dy][ns.dx], 0);

	}
	memset(visbuf, 0, (WORLD_Y * (WORLD_X + 1)));
	snxtitem_dist(&nit, EF_SHIP, ship.shp_x, ship.shp_y, range);
	while (nxtitem(&nit, &targ)) {
	    if (targ.shp_own == player->cnum || targ.shp_own == 0)
		continue;
	    tmcp = &mchr[(int)targ.shp_type];
	    visib = shp_visib(&targ);
	    pingrange = MIN(7, MAX(visib, 10) * range / 10);
	    vrange = pingrange * ship.shp_effic / 200;
	    dist = mapdist(targ.shp_x, targ.shp_y, ship.shp_x, ship.shp_y);
	    pingrange = (MAX(pingrange, 2) * targ.shp_effic) / 100;
	    if (dist > pingrange)
		continue;
	    if (tmcp->m_flags & M_SONAR && targ.shp_own) {
		natp = getnatp(targ.shp_own);
		if (natp->nat_flags & NF_SONAR)
		    wu(0, targ.shp_own,
		       "Sonar ping from %s detected by %s!\n",
		       xyas(ship.shp_x, ship.shp_y,
			    targ.shp_own), prship(&targ));
		if (targ.shp_rflags & RET_SONARED)
		    retreat_ship(&targ, targ.shp_own, 's');
	    }
	    if (dist > vrange)
		continue;
	    x = deltx(&ns.range, (int)targ.shp_x);
	    y = delty(&ns.range, (int)targ.shp_y);
	    if (rad[y][x] != dchr[SCT_WATER].d_mnem && rad[y][x] != 'X')
		continue;
	    if (tmcp->m_flags & M_SUB &&
		relations_with(targ.shp_own, player->cnum) < FRIENDLY) {
		if (mcp->m_vrnge + visib < 8)
		    pr("Sonar detects sub #%d @ %s\n",
		       targ.shp_uid,
		       xyas(targ.shp_x, targ.shp_y, player->cnum));
		else if (mcp->m_vrnge + visib < 10)
		    pr("Sonar detects %s @ %s\n",
		       prship(&targ),
		       xyas(targ.shp_x, targ.shp_y, player->cnum));
		else
		    pr("Sonar detects %s %s @ %s\n",
		       cname(targ.shp_own), prship(&targ),
		       xyas(targ.shp_x, targ.shp_y, player->cnum));
	    } else
		pr("Sonar detects %s %s @ %s\n",
		   cname(targ.shp_own), prship(&targ),
		   xyas(targ.shp_x, targ.shp_y, player->cnum));

	    if (visib > vis[y][x]) {
		vis[y][x] = visib;
		/* &~0x20 makes it a cap letter */
		rad[y][x] = (*mchr[(int)targ.shp_type].m_name) & ~0x20;
	    }
	}
	if (!player->argp[2]) {
	    rad[cy][cx] = '0';
	    for (row = 0; row < ns.range.height; row++)
		if (!blankrow(rad[row]))
		    pr("%s\n", rad[row]);
	}
	pr("\n");

    }
    if (changed)
	writemap(player->cnum);
    return RET_OK;
}
コード例 #6
0
/*
 * Draw a radar map for radar at @cx,@cy.
 * @eff is the radar's efficiency, @tlev its tech level, @spy its power.
 * Submarines are detected at fraction @seesub of the range.
 */
void
radmap(int cx, int cy, int eff, double tlev, int spy, double seesub)
{
    int visib, rng;
    struct sctstr sect;
    struct shpstr ship;
    struct plnstr plane;
    struct nstr_sect ns;
    struct nstr_item ni;
    int x, y;
    int row;
    int n;
    int range = rad_range(eff, tlev, spy);
    int changed = 0;

    if (!radbuf)
	radbuf = malloc(WORLD_Y * MAPWIDTH(1));
    if (!visbuf)
	visbuf = malloc(WORLD_Y * MAPWIDTH(1));
    if (!rad) {
	rad = malloc(WORLD_Y * sizeof(char *));
	if (rad && radbuf) {
	    for (x = 0; x < WORLD_Y; x++)
		rad[x] = &radbuf[(WORLD_X + 1) * x];
	}
    }
    if (!vis) {
	vis = malloc(WORLD_Y * sizeof(signed char *));
	if (vis && visbuf) {
	    for (x = 0; x < WORLD_Y; x++)
		vis[x] = &visbuf[(WORLD_X + 1) * x];
	}
    }
    if (!radbuf || !visbuf || !rad || !vis) {
	pr("Memory error in radmap2, tell the deity.\n");
	return;
    }

    memset(visbuf, 0, (WORLD_Y * (WORLD_X + 1)));
    pr("%s efficiency %d%%, max range %d\n",
       xyas(cx, cy, player->cnum), eff, range);
    snxtsct_dist(&ns, cx, cy, range);
    blankfill(radbuf, &ns.range, 1);
    while (nxtsct(&ns, &sect)) {
	rad[ns.dy][ns.dx] = rad_char(&sect, ns.curdist, range,
				     player->cnum);
	changed += map_set(player->cnum, ns.x, ns.y, rad[ns.dy][ns.dx], 0);
    }
    if (changed)
	writemap(player->cnum);
    snxtitem_dist(&ni, EF_PLANE, cx, cy, range);
    while (nxtitem(&ni, &plane)) {
	if (plane.pln_own == 0)
	    continue;
	/* Used to have 'ghosts' when scanning whole world --ts */
	x = deltx(&ns.range, (int)plane.pln_x);
	y = delty(&ns.range, (int)plane.pln_y);

	if (pln_is_in_orbit(&plane) && plane.pln_own != player->cnum) {
	    vis[y][x] = 100;
	    rad[y][x] = '$';
	}
    }
    snxtitem_dist(&ni, EF_SHIP, cx, cy, range);
    while (nxtitem(&ni, &ship)) {
	if (ship.shp_own == 0)
	    continue;
	/* Used to have 'ghosts' when scanning whole world --ts */
	x = deltx(&ns.range, (int)ship.shp_x);
	y = delty(&ns.range, (int)ship.shp_y);

	visib = shp_visib(&ship);
	rng = (int)(range * visib / 20.0);
	if (ni.curdist > rng)
	    continue;
	if ((mchr[(int)ship.shp_type].m_flags & M_SUB) &&
	    ni.curdist > rng * seesub)
	    continue;
	if (visib > vis[y][x]) {
	    vis[y][x] = visib;
	    /* &~0x20 makes it a cap letter */
	    rad[y][x] = (*mchr[(int)ship.shp_type].m_name) & ~0x20;
	}
    }
    /*
     * make the center of the display 0
     * so ve et al can find it.
     */
    rad[delty(&ns.range, cy)][deltx(&ns.range, cx)] = '0';

    n = ns.range.height;
    for (row = 0; row < n; row++)
	pr("%s\n", rad[row]);
    pr("\n");
}
コード例 #7
0
ファイル: supply.c プロジェクト: gefla/empserver
/*
 * 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;
}
コード例 #8
0
ファイル: detonate.c プロジェクト: gefla/empserver
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);
}