Example #1
0
void
bsanct(void)
{
    int count;
    struct sctstr s;
    struct nstr_sect nstr;

    if (player->god)
	return;
    count = 0;
    snxtsct_all(&nstr);
    while (nxtsct(&nstr, &s)) {
	if (!player->owner)
	    continue;
	if (s.sct_type != SCT_SANCT)
	    continue;
	pr("%s is no longer a sanctuary.\n",
	   xyas(s.sct_x, s.sct_y, player->cnum));
	if (s.sct_newtype == SCT_SANCT)
	    s.sct_newtype = SCT_CAPIT;
	s.sct_type = s.sct_newtype;
	game_tick_to_now(&s.sct_access);
	(void)putsect(&s);
	count++;
    }
    if (count > 0) {
	game_note_bsanct();
	nreport(player->cnum, N_BROKE_SANCT, 0, 1);
    }
}
Example #2
0
static void
starv_sects(char *range)
{
    struct nstr_sect nstr;
    struct sctstr sect;
    int nsect = 0;
    int s, save;

    if (!snxtsct(&nstr, range))
        return;
    while (nxtsct(&nstr, &sect)) {
        if (!player->owner)
            continue;
        if (sect.sct_type == SCT_SANCT)
            continue;

        /*
         * Check for starvation.  Suppress complaints about tiny
         * population without food by adding 1f just for the check.
         * That's okay because growfood() will grow at least that much
         * anyway.
         */
        save = sect.sct_item[I_FOOD];
        if (sect.sct_item[I_FOOD] == 0)
            sect.sct_item[I_FOOD] = 1;
        s = famine_victims(sect.sct_item, etu_per_update);
        sect.sct_item[I_FOOD] = save;
        if (s == 0)
            continue;

        if (nsect++ == 0)
            sect_hdr();
        if (player->god)
            pr("%3d ", sect.sct_own);
        prxy("%4d,%-4d", nstr.x, nstr.y);
        pr(" %c", dchr[sect.sct_type].d_mnem);
        pr(" %c", sect.sct_own != sect.sct_oldown ? '*' : ' ');
        if (sect.sct_newtype != sect.sct_type)
            pr("%c", dchr[sect.sct_newtype].d_mnem);
        else
            pr(" ");
        pr("%4d%%", sect.sct_effic);
        starv_people(sect.sct_item, s);
    }
    if (nsect == 0) {
        if (player->argp[1])
            pr("%s: No sector(s)\n", player->argp[1]);
        else
            pr("%s: No sector(s)\n", "");
        return;
    } else
        pr("%d sector%s\n", nsect, splur(nsect));
    return;
}
Example #3
0
/*
 * threshold <COMM> <SECTS> <THRESH>
 */
int
thre(void)
{
    struct sctstr sect;
    struct nstr_sect nstr;
    int val;
    struct ichrstr *ip;
    char *p;
    int thresh;
    i_type type;
    char prompt[128];
    char buf[128];

    if (!(ip = whatitem(player->argp[1], "What commodity? ")))
	return RET_SYN;
    if (!snxtsct(&nstr, player->argp[2]))
	return RET_SYN;
    type = ip->i_uid;
    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	val = sect.sct_dist[type];
	if (val > 0)
	    sprintf(prompt, "%s %s  old threshold %d new? ",
		    xyas(nstr.x, nstr.y, player->cnum),
		    dchr[sect.sct_type].d_name, val);
	else
	    sprintf(prompt, "%s %s  threshold? ",
		    xyas(nstr.x, nstr.y, player->cnum),
		    dchr[sect.sct_type].d_name);
	if (!(p = getstarg(player->argp[3], prompt, buf)))
	    return RET_FAIL;
	if (!*p)
	    continue;
	if (!check_sect_ok(&sect))
	    return RET_FAIL;
	thresh = atoi(p);
	if (thresh < 0)
	    return RET_FAIL;
	if (thresh > ITEM_MAX)
	    thresh = ITEM_MAX;
	if ((val > 0) && (val == thresh)) {
	    pr("%s threshold unchanged (left at %d)\n",
	       xyas(nstr.x, nstr.y, player->cnum), val);
	    continue;
	}
	if (val > 0 && player->argp[3] && *player->argp[3])
	    pr("%s old threshold %d\n",
	       xyas(nstr.x, nstr.y, player->cnum), val);
	sect.sct_dist[type] = thresh;
	putsect(&sect);
    }
    return RET_OK;
}
Example #4
0
void
bitinit2(struct nstr_sect *np, unsigned char *bitmap, int country)
{
    struct sctstr sect;
    int eff;

    while (nxtsct(np, &sect)) {
	if (sect.sct_own != country)
	    continue;
	eff = sect.sct_effic / 20;
	if (eff > 4)
	    eff = 4;
	emp_setbitmap(np->x, np->y, bitmap, bitmaps[eff]);
    }
    snxtsct_rewind(np);
}
Example #5
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);
}
Example #6
0
int
wipe(void)
{
    struct sctstr sect;
    struct nstr_sect nstr;

    if (!snxtsct(&nstr, player->argp[1]))
	return RET_SYN;
    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	memset(sect.sct_dist, 0, sizeof(sect.sct_dist));
	pr("Distribution thresholds wiped from %s\n",
	   xyas(nstr.x, nstr.y, player->cnum));
	putsect(&sect);
    }
    return RET_OK;
}
Example #7
0
/*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;
}
Example #8
0
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;
}
Example #9
0
int
newe(void)
{
    struct natstr *natp;
    struct sctstr sect;
    struct nstr_sect nstr;
    double work, lcms, hcms;
    int nsect;
    int civs = 0;
    int uws = 0;
    int bwork;
    int twork;
    int type;
    int eff;
    int maxpop;

    if (!snxtsct(&nstr, player->argp[1]))
	return RET_SYN;
    player->simulation = 1;
    prdate();
    nsect = 0;
    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	if (!sect.sct_off) {
	    civs = (1.0 + obrate * etu_per_update) * sect.sct_item[I_CIVIL];
	    uws = (1.0 + uwbrate * etu_per_update) * sect.sct_item[I_UW];
	    natp = getnatp(sect.sct_own);
	    maxpop = max_pop(natp->nat_level[NAT_RLEV], &sect);
	    work = new_work(&sect,
			    total_work(sect.sct_work, etu_per_update,
				       civs, sect.sct_item[I_MILIT], uws,
				       maxpop));
	    bwork = work / 2;

	    type = sect.sct_type;
	    eff = sect.sct_effic;
	    if (sect.sct_newtype != type) {
		twork = (eff + 3) / 4;
		if (twork > bwork) {
		    twork = bwork;
		}
		bwork -= twork;
		eff -= twork * 4;
		if (eff <= 0) {
		    type = sect.sct_newtype;
		    eff = 0;
		}

		twork = 100 - eff;
		if (twork > bwork) {
		    twork = bwork;
		}
		if (dchr[type].d_lcms > 0) {
		    lcms = sect.sct_item[I_LCM];
		    lcms = (int)(lcms / dchr[type].d_lcms);
		    if (twork > lcms)
			twork = lcms;
		}
		if (dchr[type].d_hcms > 0) {
		    hcms = sect.sct_item[I_HCM];
		    hcms = (int)(hcms / dchr[type].d_hcms);
		    if (twork > hcms)
			twork = hcms;
		}
		eff += twork;
	    } else if (eff < 100) {
		twork = 100 - eff;
		if (twork > bwork) {
		    twork = bwork;
		}
		if (dchr[type].d_lcms > 0) {
		    lcms = sect.sct_item[I_LCM];
		    lcms = (int)(lcms / dchr[type].d_lcms);
		    if (twork > lcms)
			twork = lcms;
		}
		if (dchr[type].d_hcms > 0) {
		    hcms = sect.sct_item[I_HCM];
		    hcms = (int)(hcms / dchr[type].d_hcms);
		    if (twork > hcms)
			twork = hcms;
		}
		eff += twork;
	    }
	} else {
	    eff = sect.sct_effic;
	    type = sect.sct_type;
	}
	if (nsect++ == 0) {
	    pr("EFFICIENCY SIMULATION\n");
	    pr("   sect  des    projected eff\n");
	}
	prxy("%4d,%-4d", nstr.x, nstr.y);
	pr(" %c", dchr[type].d_mnem);
	pr("    %3d%%\n", eff);
    }
    player->simulation = 0;
    if (nsect == 0) {
	if (player->argp[1])
	    pr("%s: No sector(s)\n", player->argp[1]);
	else
	    pr("%s: No sector(s)\n", "");
	return RET_FAIL;
    } else
	pr("%d sector%s\n", nsect, splur(nsect));
    return RET_OK;
}
Example #10
0
int
cens(void)
{
    struct sctstr sect;
    int nsect;
    int n;
    struct nstr_sect nstr;
    char dirstr[20];

    if (!snxtsct(&nstr, player->argp[1]))
	return RET_SYN;
    prdate();
    for (n = 1; n <= 6; n++)
	dirstr[n] = dirch[n];
    dirstr[0] = '.';
    dirstr[7] = '$';
    dirstr[8] = '\0';
    nsect = 0;
    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	if (nsect++ == 0)
	    cens_hdr();
	if (player->god)
	    pr("%3d ", sect.sct_own);
	prxy("%4d,%-4d", nstr.x, nstr.y);
	pr(" %c", dchr[sect.sct_type].d_mnem);
	if (sect.sct_newtype != sect.sct_type)
	    pr("%c", dchr[sect.sct_newtype].d_mnem);
	else
	    pr(" ");
	pr("%4d%%", sect.sct_effic);
	if (sect.sct_off)
	    pr(" no ");
	else
	    pr("    ");
	pr("%4d", sect.sct_mobil);

	pr(" %c", dirstr[sect.sct_del[I_UW] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_FOOD] & 0x7]);

	n = sect.sct_dist[I_UW] % 1000;
	pr(" %c", n == 0 ? '.' : '0' + (n / 100));
	n = sect.sct_dist[I_FOOD] % 1000;
	pr("%c ", n == 0 ? '.' : '0' + (n / 100));
	if (sect.sct_own != sect.sct_oldown)
	    pr("%3d",  sect.sct_oldown);
	else
	    pr("   ");

	pr("%5d", sect.sct_item[I_CIVIL]);
	pr("%5d", sect.sct_item[I_MILIT]);
	pr("%5d", sect.sct_item[I_UW]);
	pr("%5d", sect.sct_item[I_FOOD]);
	pr("%4d%%", sect.sct_work);
	pr("%5d", sect.sct_avail);
	if (!player->god) {
	    if (sect.sct_terr)
		pr("%4d", sect.sct_terr);
	    else
		pr("    ");
	}
	pr("%5d", opt_FALLOUT ? sect.sct_fallout : 0);
	if (sect.sct_coastal)
	    pr("%4d", sect.sct_coastal);
	pr("\n");
    }
    if (nsect == 0) {
	if (player->argp[1])
	    pr("%s: No sector(s)\n", player->argp[1]);
	else
	    pr("%s: No sector(s)\n", "");
	return RET_FAIL;
    } else
	pr("%d sector%s\n", nsect, splur(nsect));
    return 0;
}
Example #11
0
/*
 * format: coastwatch [<SECTS>]
 */
int
coas(void)
{
    struct sctstr sect;
    struct nstr_sect nstr;
    struct coast *cp;
    struct coast *list[TSIZE];
    int i, n;
    int vrange, see;
    int x, y, dx, dy, dxmax;
    int nship = 0;
    double tech;
    struct nstr_item ni;

    if (!snxtsct(&nstr, player->argp[1]))
	return RET_SYN;
    for (i = 0; i < TSIZE; i++)
	list[i] = NULL;
    cp = malloc(sizeof(*cp));
    snxtitem_all(&ni, EF_SHIP);
    while (nxtitem(&ni, &cp->c_shp)) {
	if (cp->c_shp.shp_own == 0 || cp->c_shp.shp_own == player->cnum)
	    continue;
	/*
	 * don't bother putting subs in the table...
	 * unless they're in a sector you own (harbor or such)
	 */
	getsect(cp->c_shp.shp_x, cp->c_shp.shp_y, &sect);
	if ((mchr[(int)cp->c_shp.shp_type].m_flags & M_SUB) &&
	    (sect.sct_own != player->cnum))
	    continue;
	n = scthash(cp->c_shp.shp_x, cp->c_shp.shp_y, TSIZE);
	cp->c_spotted = 0;
	cp->c_number = i;
	cp->c_next = list[n];
	list[n] = cp;
	cp = malloc(sizeof(*cp));
	nship++;
    }
    /* get that last one! */
    free(cp);
    pr("- = [ Coastwatch report for %s ] = -\n", cname(player->cnum));
    pr("  Country            Ship          Location\n");
    tech = tfact(player->cnum, 1.0);
    while (nxtsct(&nstr, &sect) && nship) {
	if (sect.sct_own != player->cnum)
	    continue;
	see = sect.sct_type == SCT_RADAR ? 14 : 4;
	vrange = (int)(sect.sct_effic / 100.0 * see * tech);
	if (vrange < 1)
	    vrange = 1;
	for (dy = -vrange; dy <= vrange; dy++) {
	    y = ynorm(sect.sct_y + dy);
	    dxmax = 2 * vrange - abs(dy);
	    for (dx = -dxmax; dx <= dxmax; dx += 2) {
		x = xnorm(sect.sct_x + dx);
		n = scthash(x, y, TSIZE);
		if (!list[n])
		    continue;
		nship -= showship(&list[n], x, y);
	    }
	}
    }
    /* free up the coast structs calloc'ed above */
    for (i = 0; i < TSIZE; i++) {
	while (NULL != (cp = list[i])) {
	    list[i] = cp->c_next;
	    free(cp);
	}
    }
    return RET_OK;
}
Example #12
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;
}
Example #13
0
int
desi(void)
{
    int n;
    char *p;
    int des;
    struct nstr_sect nstr;
    struct sctstr sect;
    struct natstr *natp;
    char prompt[128];
    char buf[1024];
    int changed = 0;
    int rc = RET_OK;

    if (!snxtsct(&nstr, player->argp[1]))
	return RET_SYN;
    natp = getnatp(player->cnum);
    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	if (!player->god && dchr[sect.sct_type].d_cost < 0)
	    continue;
	sprintf(prompt, "%s %d%% %s  desig? ",
		xyas(sect.sct_x, sect.sct_y, player->cnum),
		sect.sct_effic, dchr[sect.sct_type].d_name);
	if (!(p = getstarg(player->argp[2], prompt, buf))) {
	    rc = RET_FAIL;
	    break;
	}

	if (!check_sect_ok(&sect))
	    continue;

	des = sct_typematch(p);
	if (des < 0) {
	    pr("No such designation\n"
	       "See \"info Sector-types\" for possible designations\n");
	    rc = RET_FAIL;
	    break;
	}
	if (!player->god) {
	    if (des == SCT_WASTE) {
		pr("Only a nuclear device (or %s) can make a %s!\n",
		   cname(0), dchr[des].d_name);
		rc = RET_FAIL;
		break;
	    }
	    if (dchr[des].d_cost < 0) {
		pr("Only %s can designate a %s!\n",
		   cname(0), dchr[des].d_name);
		rc = RET_FAIL;
		break;
	    }
	    if (dchr[des].d_terrain != dchr[sect.sct_type].d_terrain) {
		pr("You can't change a %s into a %s\n",
		   dchr[sect.sct_type].d_name, dchr[des].d_name);
		continue;
	    }
	}
	if (sect.sct_type == des && sect.sct_newtype == des)
	    continue;
	if ((des == SCT_HARBR || des == SCT_BHEAD) && !sect.sct_coastal) {
	    pr("%s does not border on water.\n",
	       xyas(nstr.x, nstr.y, player->cnum));
	    if (player->god)
		pr("But if it's what you want ...\n");
	    else
		continue;
	}
	if (sect.sct_type == SCT_SANCT && !player->god)
	    continue;
	n = sect.sct_type;
	if ((sect.sct_newtype != des) && (sect.sct_type != des)
	    && dchr[des].d_cost > 0) {
	    if (natp->nat_money < player->dolcost + dchr[des].d_cost) {
		pr("You can't afford a %s!\n", dchr[des].d_name);
		rc = RET_FAIL;
		break;
	    }
	    player->dolcost += dchr[des].d_cost;
	}
	if (sect.sct_type != des && (sect.sct_effic < 5 || player->god)) {
	    if (player->god)
		set_coastal(&sect, sect.sct_type, des);
	    sect.sct_type = des;
	    sect.sct_effic = 0;
	    changed += map_set(player->cnum, sect.sct_x, sect.sct_y,
			       dchr[des].d_mnem, 0);
	}
	sect.sct_newtype = des;
	putsect(&sect);
	if (!player->god
	    && sect.sct_x == natp->nat_xcap && sect.sct_y == natp->nat_ycap
	    && des != SCT_CAPIT && des != SCT_SANCT && des != SCT_MOUNT)
	    pr("You have redesignated your capital!\n");
	if (opt_EASY_BRIDGES == 0) {	/* may cause a bridge fall */
	    if (n != SCT_BHEAD)
		continue;
	    bridgefall(&sect);
	}
    }
    if (changed)
	writemap(player->cnum);
    return rc;
}
Example #14
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");
}
Example #15
0
int
rout(void)
{
    struct ichrstr *ip;
    struct nstr_sect ns;
    struct natstr *natp;
    struct sctstr sect;
    struct nscstr cond[NS_NCOND];
    int ncond;
    struct range relrange;
    int row;
    int y;
    int ry;
    i_type i_del;
    int dir;
    char *p;
    /* Note this is not re-entrant anyway, so we keep the buffers
       around */
    static char *mapbuf = NULL;
    static char **map = NULL;
    int i;

    if (!(ip = whatitem(player->argp[1], "What item? ")))
	return RET_SYN;
    i_del = ip->i_uid;;
    if (!snxtsct(&ns, player->argp[2]))
	return RET_SYN;
    if (!mapbuf)
	mapbuf = malloc(WORLD_Y * MAPWIDTH(3));
    if (!map) {
	map = malloc(WORLD_Y * sizeof(char *));
	if (map && mapbuf) {
	    for (i = 0; i < WORLD_Y; i++)
		map[i] = &mapbuf[MAPWIDTH(3) * i];
	} else if (map) {
	    free(map);
	    map = NULL;
	}
    }
    if (!mapbuf || !map) {
	pr("Memory error, tell the deity.\n");
	logerror("malloc failed in rout\n");
	return RET_FAIL;
    }
    ncond = ns.ncond;
    memcpy(cond, ns.cond, sizeof(struct nscstr) * ncond);
    ns.ncond = 0;

    natp = getnatp(player->cnum);
    xyrelrange(natp, &ns.range, &relrange);
    blankfill(mapbuf, &ns.range, 3);
    border(&relrange, "     ", " ");

    while (nxtsct(&ns, &sect)) {
	if (!player->owner)
	    continue;
	p = &map[ns.dy][ns.dx * 2];
	dir = sect.sct_del[i_del] & 0x7;
	if (dir && nstr_exec(cond, ncond, &sect))
	    memcpy(p, routech[dir], 3);
	p[1] = dchr[sect.sct_type].d_mnem;
    }
    for (row = 0, y = ns.range.ly; row < ns.range.height; y++, row++) {
	ry = yrel(natp, y);
	pr("%4d %s %-4d\n", ry, map[row], ry);
	if (y >= WORLD_Y)
	    y -= WORLD_Y;
    }
    border(&relrange, "     ", " ");
    return RET_OK;
}
Example #16
0
/*
 * survey type <sarg> ?cond
 *
 */
int
surv(void)
{
    int nsect;
    struct nstr_sect nstr;
    int y;
    struct valstr val;
    struct natstr *np;
    struct sctstr sect;
    struct range range;
    char *ptr;
    struct nscstr cond[NS_NCOND];
    int ncond;
    int i;
    char buf[1024];
    /* Note this is not re-entrant anyway, so we keep the buffers
       around */
    static char *mapbuf = NULL;
    static char **map = NULL;

    nsect = 0;
    ptr = getstarg(player->argp[1], "commodity or variable? ", buf);
    if (!ptr || !*ptr)
	return RET_SYN;
    ptr = nstr_comp_val(ptr, &val, EF_SECTOR);
    if (!ptr)
	return RET_SYN;
    if (val.val_cat != NSC_OFF || nstr_promote(val.val_type) != NSC_LONG) {
	pr("Can't survey this\n");
	return RET_SYN;
    }
    for (; isspace(*ptr); ++ptr) ;
    if (*ptr)
	return RET_SYN;
    if (!snxtsct(&nstr, player->argp[2]))
	return RET_SYN;
    if (!mapbuf)
	mapbuf = malloc(WORLD_Y * MAPWIDTH(1));
    if (!map) {
	map = malloc(WORLD_Y * sizeof(char *));
	if (map && mapbuf) {
	    for (i = 0; i < WORLD_Y; i++)
		map[i] = &mapbuf[MAPWIDTH(1) * i];
	} else if (map) {
	    free(map);
	    map = NULL;
	}
    }
    if (!mapbuf || !map) {
	pr("Memory error, tell the deity.\n");
	logerror("malloc failed in sect\n");
	return RET_FAIL;
    }
    ncond = nstr.ncond;
    memcpy(cond, nstr.cond, sizeof(struct nscstr) * ncond);
    nstr.ncond = 0;
    np = getnatp(player->cnum);
    xyrelrange(np, &nstr.range, &range);
    border(&range, "     ", "");
    blankfill(mapbuf, &nstr.range, 1);
    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	ptr = &map[nstr.dy][nstr.dx];
	if (nstr_exec(cond, ncond, &sect)) {
	    ++nsect;
	    *ptr = 0x80 | code_char(val, &sect);
	} else {
	    *ptr = dchr[sect.sct_type].d_mnem;
	}
    }
    for (y = nstr.range.ly, i = 0; i < nstr.range.height; y++, i++) {
	int yval;

	yval = yrel(np, y);
	pr("%4d %s %4d\n", yval, map[i], yval);
	if (y >= WORLD_Y)
	    y -= WORLD_Y;
    }
    border(&range, "     ", "");
    if (nsect > 0)
	pr("\n%d sector%s.\n", nsect, splur(nsect));
    return RET_OK;
}
Example #17
0
int
enli(void)
{
    struct nstr_sect nstr;
    struct sctstr sect;
    struct natstr *natp;
    int civ;
    int mil;
    int newmil;
    int milwant;
    int totalmil;
    int reserve;
    char *p;
    int quota;
    char prompt[128];
    char buf[1024];

    if (!snxtsct(&nstr, player->argp[1]))
	return RET_SYN;
    natp = getnatp(player->cnum);
    newmil = 500;
    sprintf(prompt, "Number to enlist (max %d) : ", newmil);
    if (!(p = getstarg(player->argp[2], prompt, buf)))
	return RET_SYN;
    if ((milwant = atoi(p)) > newmil)
	milwant = newmil;
    if (0 != (quota = (milwant < 0)))
	milwant = -milwant;
    totalmil = 0;
    reserve = natp->nat_reserve;
    if (reserve <= 0) {
	pr("No military reserves left\n");
	return RET_OK;
    }
    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	if (sect.sct_oldown != player->cnum)
	    continue;
	civ = sect.sct_item[I_CIVIL];
	if (civ == 0)
	    continue;
	if (sect.sct_loyal > 70) {
	    pr("civilians refuse to report in %s!\n",
	       xyas(sect.sct_x, sect.sct_y, player->cnum));
	    continue;
	}
	if (sect.sct_mobil <= 0) {
	    pr("%s is out of mobility!\n",
	       xyas(sect.sct_x, sect.sct_y, player->cnum));
	}
	mil = sect.sct_item[I_MILIT];
	newmil = civ * 0.5;
	if (quota) {
	    if (newmil > milwant - mil)
		newmil = milwant - mil;
	    if (newmil > 500)
		newmil = 500;
	} else if (newmil > milwant)
	    newmil = milwant;
	if (newmil > 999 - mil)
	    newmil = 999 - mil;
	if (newmil <= 0)
	    continue;
	if (newmil > reserve)
	    newmil = reserve;
	sect.sct_item[I_MILIT] = newmil + mil;
	reserve -= newmil;
	totalmil += newmil;
	sect.sct_item[I_CIVIL] = civ - newmil;
	pr("%3d enlisted in %s (%d)\n", newmil,
	   xyas(sect.sct_x, sect.sct_y, player->cnum), mil + newmil);
	if (sect.sct_mobil > 0)
	    sect.sct_mobil *= 1.0 - (double)newmil / (double)civ;
	putsect(&sect);
	if (totalmil >= 10000) {
	    pr("Rioting in induction center interrupts enlistment\n");
	    break;
	}
	if (reserve == 0) {
	    pr("Military reserve exhausted\n");
	    break;
	}
    }
    pr("Total new enlistment : %d\n", totalmil);
    pr("Military reserves stand at %d\n", reserve);
    if (totalmil) {
	natp->nat_reserve -= totalmil;
	putnat(natp);
    }
    if ((player->btused += roundavg(totalmil * 0.02)) > 0)
	pr("Paperwork at recruiting stations ... %d\n", player->btused);
    return RET_OK;
}
Example #18
0
static void
gen_power(struct powstr *powbuf, int save)
{
    float upower[MAXNOC];
    float *f_ptr;
    float *f_pt2;
    struct powstr *pow;
    int i, maxpop;
    struct sctstr sect;
    struct dchrstr *dcp;
    struct plnstr plane;
    struct plchrstr *pcp;
    struct shpstr ship;
    struct mchrstr *mcp;
    struct lndstr land;
    struct lchrstr *lcp;
    struct nukstr nuke;
    struct nchrstr *ncp;
    struct nstr_item ni;
    struct nstr_sect ns;
    struct natstr *natp;

    player->btused += 10;
    memset(powbuf, 0, MAXNOC * sizeof(*powbuf));
    memset(upower, 0, sizeof(upower));
    snxtsct_all(&ns);
    while (nxtsct(&ns, &sect)) {
	if (sect.sct_own == 0)
	    continue;
	dcp = &dchr[sect.sct_type];
	natp = getnatp(sect.sct_own);
	pow = &powbuf[sect.sct_own];
	pow->p_sects += 1.0;
	pow->p_effic += sect.sct_effic;
	addtopow(sect.sct_item, pow);
	pow->p_power += empobj_power(sect.sct_effic,
				     dcp->d_mat, dcp->d_cost);
	maxpop = max_pop(natp->nat_level[NAT_RLEV], &sect);
	pow->p_power += (1.0 + maxpop / 1000.0 * 8) * sect.sct_effic / 100.0;
    }
    snxtitem_all(&ni, EF_LAND);
    while (nxtitem(&ni, &land)) {
	if (land.lnd_own == 0)
	    continue;
	lcp = &lchr[land.lnd_type];
	pow = &powbuf[land.lnd_own];
	addtopow(land.lnd_item, pow);
	upower[land.lnd_own] += empunit_power(land.lnd_effic,
					      land.lnd_tech,
					      lcp->l_mat, lcp->l_cost);
	if (!(lcp->l_flags & L_SPY))
	    pow->p_units += 1.0;
    }
    snxtitem_all(&ni, EF_SHIP);
    while (nxtitem(&ni, &ship)) {
	if (ship.shp_own == 0)
	    continue;
	mcp = &mchr[ship.shp_type];
	pow = &powbuf[ship.shp_own];
	addtopow(ship.shp_item, pow);
	upower[ship.shp_own] += empunit_power(ship.shp_effic,
					      ship.shp_tech,
					      mcp->m_mat, mcp->m_cost);
	pow->p_ships += 1.0;
    }
    snxtitem_all(&ni, EF_PLANE);
    while (nxtitem(&ni, &plane)) {
	if (plane.pln_own == 0)
	    continue;
	pcp = &plchr[plane.pln_type];
	pow = &powbuf[plane.pln_own];
	upower[plane.pln_own] += empunit_power(plane.pln_effic,
					       plane.pln_tech,
					       pcp->pl_mat, pcp->pl_cost);
	pow->p_planes += 1.0;
    }
    snxtitem_all(&ni, EF_NUKE);
    while (nxtitem(&ni, &nuke)) {
	if (nuke.nuk_own == 0)
	    continue;
	ncp = &nchr[nuke.nuk_type];
	upower[nuke.nuk_own] += empunit_power(nuke.nuk_effic,
					      nuke.nuk_tech,
					      ncp->n_mat, ncp->n_cost);
    }
    for (i = 1; NULL != (natp = getnatp(i)); i++) {
	pow = &powbuf[i];
	pow->p_nation = i;
	if (natp->nat_stat != STAT_ACTIVE) {
	    pow->p_power = 0.;
	    continue;
	}
	pow->p_money = natp->nat_money;
	pow->p_power += money_power(natp->nat_money);
	pow->p_power *= power_tech_factor(natp->nat_level[NAT_TLEV]);
	pow->p_power += upower[i];
	/* ack.  add this vec to the "world power" element */
	f_pt2 = &powbuf[0].p_sects;
	f_ptr = &pow->p_sects;
	while (f_ptr <= &pow->p_power) {
	    *f_pt2 += *f_ptr;
	    f_pt2++;
	    f_ptr++;
	}
    }
    qsort(&powbuf[1], MAXNOC - 1, sizeof(*powbuf), powcmp);
    if (!save)
	return;
    for (i = 0; i < MAXNOC; i++)
	putpower(i, &powbuf[i]);
#ifdef _WIN32
    /*
     * At least some versions of Windows fail to update mtime on
     * write(), they delay it until the write actually hits the disk.
     * Bad, because `power' displays that time.  Force it.
     */
    _commit(empfile[EF_POWER].fd);
#endif
}
Example #19
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;
}
Example #20
0
int
dump(void)
{
    struct sctstr sect;
    char dirstr[20];
    int nsect;
    int n, i;
    struct nstr_sect nstr;
    int field[128];
    struct natstr *np;
    time_t now;

    if (!snxtsct(&nstr, player->argp[1]))
	return RET_SYN;
    prdate();
    (void)strcpy(dirstr, ".      $");
    for (n = 1; n <= 6; n++)
	dirstr[n] = dirch[n];
    nsect = 0;
    np = getnatp(player->cnum);

    if (!player->argp[2]) {
	for (n = 1; n <= 80; n++)
	    field[n - 1] = n;
	field[n - 1] = 0;
    } else {
	n = 2;
	i = 0;
	while (player->argp[n]) {
	    if (!strcmp("des", player->argp[n])) {
		field[i++] = 1;
	    } else if (!strcmp("sdes", player->argp[n])) {
		field[i++] = 2;
	    } else if (!strcmp("eff", player->argp[n])) {
		field[i++] = 3;
	    } else if (!strcmp("mob", player->argp[n])) {
		field[i++] = 4;
	    } else if (!strcmp("*", player->argp[n])) {
		field[i++] = 5;
	    } else if (!strcmp("off", player->argp[n])) {
		field[i++] = 6;
	    } else if (!strcmp("min", player->argp[n])) {
		field[i++] = 7;
	    } else if (!strcmp("gold", player->argp[n])) {
		field[i++] = 8;
	    } else if (!strcmp("fert", player->argp[n])) {
		field[i++] = 9;
	    } else if (!strcmp("ocontent", player->argp[n])) {
		field[i++] = 10;
	    } else if (!strcmp("uran", player->argp[n])) {
		field[i++] = 11;
	    } else if (!strcmp("work", player->argp[n])) {
		field[i++] = 12;
	    } else if (!strcmp("avail", player->argp[n])) {
		field[i++] = 13;
	    } else if (!strcmp("terr", player->argp[n])) {
		field[i++] = 14;
	    } else if (!strcmp("civ", player->argp[n])) {
		field[i++] = 15;
	    } else if (!strcmp("mil", player->argp[n])) {
		field[i++] = 16;
	    } else if (!strcmp("uw", player->argp[n])) {
		field[i++] = 17;
	    } else if (!strcmp("food", player->argp[n])) {
		field[i++] = 18;
	    } else if (!strcmp("shell", player->argp[n])) {
		field[i++] = 19;
	    } else if (!strcmp("gun", player->argp[n])) {
		field[i++] = 20;
	    } else if (!strcmp("pet", player->argp[n])) {
		field[i++] = 21;
	    } else if (!strcmp("iron", player->argp[n])) {
		field[i++] = 22;
	    } else if (!strcmp("dust", player->argp[n])) {
		field[i++] = 23;
	    } else if (!strcmp("bar", player->argp[n])) {
		field[i++] = 24;
	    } else if (!strcmp("oil", player->argp[n])) {
		field[i++] = 25;
	    } else if (!strcmp("lcm", player->argp[n])) {
		field[i++] = 26;
	    } else if (!strcmp("hcm", player->argp[n])) {
		field[i++] = 27;
	    } else if (!strcmp("rad", player->argp[n])) {
		field[i++] = 28;
	    } else if (!strcmp("u_del", player->argp[n])) {
		field[i++] = 29;
	    } else if (!strcmp("f_del", player->argp[n])) {
		field[i++] = 30;
	    } else if (!strcmp("s_del", player->argp[n])) {
		field[i++] = 31;
	    } else if (!strcmp("g_del", player->argp[n])) {
		field[i++] = 32;
	    } else if (!strcmp("p_del", player->argp[n])) {
		field[i++] = 33;
	    } else if (!strcmp("i_del", player->argp[n])) {
		field[i++] = 34;
	    } else if (!strcmp("d_del", player->argp[n])) {
		field[i++] = 35;
	    } else if (!strcmp("b_del", player->argp[n])) {
		field[i++] = 36;
	    } else if (!strcmp("o_del", player->argp[n])) {
		field[i++] = 37;
	    } else if (!strcmp("l_del", player->argp[n])) {
		field[i++] = 38;
	    } else if (!strcmp("h_del", player->argp[n])) {
		field[i++] = 39;
	    } else if (!strcmp("r_del", player->argp[n])) {
		field[i++] = 40;
	    } else if (!strcmp("u_cut", player->argp[n])) {
		field[i++] = 41;
	    } else if (!strcmp("f_cut", player->argp[n])) {
		field[i++] = 42;
	    } else if (!strcmp("s_cut", player->argp[n])) {
		field[i++] = 43;
	    } else if (!strcmp("g_cut", player->argp[n])) {
		field[i++] = 44;
	    } else if (!strcmp("p_cut", player->argp[n])) {
		field[i++] = 45;
	    } else if (!strcmp("i_cut", player->argp[n])) {
		field[i++] = 46;
	    } else if (!strcmp("d_cut", player->argp[n])) {
		field[i++] = 47;
	    } else if (!strcmp("b_cut", player->argp[n])) {
		field[i++] = 48;
	    } else if (!strcmp("o_cut", player->argp[n])) {
		field[i++] = 49;
	    } else if (!strcmp("l_cut", player->argp[n])) {
		field[i++] = 50;
	    } else if (!strcmp("h_cut", player->argp[n])) {
		field[i++] = 51;
	    } else if (!strcmp("r_cut", player->argp[n])) {
		field[i++] = 52;
	    } else if (!strcmp("dist_x", player->argp[n])) {
		field[i++] = 53;
	    } else if (!strcmp("dist_y", player->argp[n])) {
		field[i++] = 54;
	    } else if (!strcmp("c_dist", player->argp[n])) {
		field[i++] = 55;
	    } else if (!strcmp("m_dist", player->argp[n])) {
		field[i++] = 56;
	    } else if (!strcmp("u_dist", player->argp[n])) {
		field[i++] = 57;
	    } else if (!strcmp("f_dist", player->argp[n])) {
		field[i++] = 58;
	    } else if (!strcmp("s_dist", player->argp[n])) {
		field[i++] = 59;
	    } else if (!strcmp("g_dist", player->argp[n])) {
		field[i++] = 60;
	    } else if (!strcmp("p_dist", player->argp[n])) {
		field[i++] = 61;
	    } else if (!strcmp("i_dist", player->argp[n])) {
		field[i++] = 62;
	    } else if (!strcmp("d_dist", player->argp[n])) {
		field[i++] = 63;
	    } else if (!strcmp("b_dist", player->argp[n])) {
		field[i++] = 64;
	    } else if (!strcmp("o_dist", player->argp[n])) {
		field[i++] = 65;
	    } else if (!strcmp("l_dist", player->argp[n])) {
		field[i++] = 66;
	    } else if (!strcmp("h_dist", player->argp[n])) {
		field[i++] = 67;
	    } else if (!strcmp("r_dist", player->argp[n])) {
		field[i++] = 68;
	    } else if (!strcmp("road", player->argp[n])) {
		field[i++] = 69;
	    } else if (!strcmp("rail", player->argp[n])) {
		field[i++] = 70;
	    } else if (!strcmp("defense", player->argp[n])) {
		field[i++] = 71;
	    } else if (!strcmp("fallout", player->argp[n])) {
		field[i++] = 72;
	    } else if (!strcmp("coast", player->argp[n])) {
		field[i++] = 73;
	    } else if (!strcmp("c_del", player->argp[n])) {
		field[i++] = 74;
	    } else if (!strcmp("m_del", player->argp[n])) {
		field[i++] = 75;
	    } else if (!strcmp("c_cut", player->argp[n])) {
		field[i++] = 76;
	    } else if (!strcmp("m_cut", player->argp[n])) {
		field[i++] = 77;
	    } else if (!strcmp("terr1", player->argp[n])) {
		field[i++] = 78;
	    } else if (!strcmp("terr2", player->argp[n])) {
		field[i++] = 79;
	    } else if (!strcmp("terr3", player->argp[n])) {
		field[i++] = 80;
	    } else {
		pr("Unrecognized field %s\n", player->argp[n]);
	    }
	    if (n++ > 100) {
		pr("Too many fields\n");
		return RET_FAIL;
	    }
	}
	field[i] = 0;
    }

    if (player->god)
	pr("   ");
    time(&now);
    pr("DUMP SECTOR %ld\n", (long)now);
    if (player->god)
	pr("own ");
    pr("x y");
    n = 0;
    while (field[n]) {
	pr(" ");
	switch (field[n]) {
	case 1:
	    pr("des");
	    break;
	case 2:
	    pr("sdes");
	    break;
	case 3:
	    pr("eff");
	    break;
	case 4:
	    pr("mob");
	    break;
	case 5:
	    pr("*");
	    break;
	case 6:
	    pr("off");
	    break;
	case 7:
	    pr("min");
	    break;
	case 8:
	    pr("gold");
	    break;
	case 9:
	    pr("fert");
	    break;
	case 10:
	    pr("ocontent");
	    break;
	case 11:
	    pr("uran");
	    break;
	case 12:
	    pr("work");
	    break;
	case 13:
	    pr("avail");
	    break;
	case 14:
	    pr("terr");
	    break;
	case 15:
	    pr("civ");
	    break;
	case 16:
	    pr("mil");
	    break;
	case 17:
	    pr("uw");
	    break;
	case 18:
	    pr("food");
	    break;
	case 19:
	    pr("shell");
	    break;
	case 20:
	    pr("gun");
	    break;
	case 21:
	    pr("pet");
	    break;
	case 22:
	    pr("iron");
	    break;
	case 23:
	    pr("dust");
	    break;
	case 24:
	    pr("bar");
	    break;
	case 25:
	    pr("oil");
	    break;
	case 26:
	    pr("lcm");
	    break;
	case 27:
	    pr("hcm");
	    break;
	case 28:
	    pr("rad");
	    break;
	case 29:
	    pr("u_del");
	    break;
	case 30:
	    pr("f_del");
	    break;
	case 31:
	    pr("s_del");
	    break;
	case 32:
	    pr("g_del");
	    break;
	case 33:
	    pr("p_del");
	    break;
	case 34:
	    pr("i_del");
	    break;
	case 35:
	    pr("d_del");
	    break;
	case 36:
	    pr("b_del");
	    break;
	case 37:
	    pr("o_del");
	    break;
	case 38:
	    pr("l_del");
	    break;
	case 39:
	    pr("h_del");
	    break;
	case 40:
	    pr("r_del");
	    break;
	case 41:
	    pr("u_cut");
	    break;
	case 42:
	    pr("f_cut");
	    break;
	case 43:
	    pr("s_cut");
	    break;
	case 44:
	    pr("g_cut");
	    break;
	case 45:
	    pr("p_cut");
	    break;
	case 46:
	    pr("i_cut");
	    break;
	case 47:
	    pr("d_cut");
	    break;
	case 48:
	    pr("b_cut");
	    break;
	case 49:
	    pr("o_cut");
	    break;
	case 50:
	    pr("l_cut");
	    break;
	case 51:
	    pr("h_cut");
	    break;
	case 52:
	    pr("r_cut");
	    break;
	case 53:
	    pr("dist_x");
	    break;
	case 54:
	    pr("dist_y");
	    break;
	case 55:
	    pr("c_dist");
	    break;
	case 56:
	    pr("m_dist");
	    break;
	case 57:
	    pr("u_dist");
	    break;
	case 58:
	    pr("f_dist");
	    break;
	case 59:
	    pr("s_dist");
	    break;
	case 60:
	    pr("g_dist");
	    break;
	case 61:
	    pr("p_dist");
	    break;
	case 62:
	    pr("i_dist");
	    break;
	case 63:
	    pr("d_dist");
	    break;
	case 64:
	    pr("b_dist");
	    break;
	case 65:
	    pr("o_dist");
	    break;
	case 66:
	    pr("l_dist");
	    break;
	case 67:
	    pr("h_dist");
	    break;
	case 68:
	    pr("r_dist");
	    break;
	case 69:
	    pr("road");
	    break;
	case 70:
	    pr("rail");
	    break;
	case 71:
	    pr("defense");
	    break;
	case 72:
	    pr("fallout");
	    break;
	case 73:
	    pr("coast");
	    break;
	case 74:
	    pr("c_del");
	    break;
	case 75:
	    pr("m_del");
	    break;
	case 76:
	    pr("c_cut");
	    break;
	case 77:
	    pr("m_cut");
	    break;
	case 78:
	    pr("terr1");
	    break;
	case 79:
	    pr("terr2");
	    break;
	case 80:
	    pr("terr3");
	    break;
	}
	n++;
    }
    pr("\n");

    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	nsect++;

/* census */
	if (player->god)
	    pr("%d ", sect.sct_own);
	pr("%d %d", xrel(np, nstr.x), yrel(np, nstr.y));

	n = 0;
	while (field[n]) {
	    pr(" ");
	    switch (field[n++]) {
	    case 1:
		pr("%c", dchr[sect.sct_type].d_mnem);
		break;
	    case 2:
		if (sect.sct_newtype != sect.sct_type)
		    pr("%c", dchr[sect.sct_newtype].d_mnem);
		else
		    pr("_");
		break;
	    case 3:
		pr("%d", sect.sct_effic);
		break;
	    case 4:
		pr("%d", sect.sct_mobil);
		break;
	    case 5:
		pr("%c", sect.sct_own != sect.sct_oldown ? '*' : '.');
		break;
	    case 6:
		pr("%d", sect.sct_off);
		break;
	    case 7:
		pr("%d", sect.sct_min);
		break;
	    case 8:
		pr("%d", sect.sct_gmin);
		break;
	    case 9:
		pr("%d", sect.sct_fertil);
		break;
	    case 10:
		pr("%d", sect.sct_oil);
		break;
	    case 11:
		pr("%d", sect.sct_uran);
		break;
	    case 12:
		pr("%d", sect.sct_work);
		break;
	    case 13:
		pr("%d", sect.sct_avail);
		break;
	    case 14:
		pr("%d", sect.sct_terr);
		break;
	    case 15:
		pr("%d", sect.sct_item[I_CIVIL]);
		break;
	    case 16:
		pr("%d", sect.sct_item[I_MILIT]);
		break;
	    case 17:
		pr("%d", sect.sct_item[I_UW]);
		break;
	    case 18:
		pr("%d", sect.sct_item[I_FOOD]);
		break;
/* commodity */
	    case 19:
		pr("%d", sect.sct_item[I_SHELL]);
		break;
	    case 20:
		pr("%d", sect.sct_item[I_GUN]);
		break;
	    case 21:
		pr("%d", sect.sct_item[I_PETROL]);
		break;
	    case 22:
		pr("%d", sect.sct_item[I_IRON]);
		break;
	    case 23:
		pr("%d", sect.sct_item[I_DUST]);
		break;
	    case 24:
		pr("%d", sect.sct_item[I_BAR]);
		break;
	    case 25:
		pr("%d", sect.sct_item[I_OIL]);
		break;
	    case 26:
		pr("%d", sect.sct_item[I_LCM]);
		break;
	    case 27:
		pr("%d", sect.sct_item[I_HCM]);
		break;
	    case 28:
		pr("%d", sect.sct_item[I_RAD]);
		break;
/* cutoff */
	    case 29:
		pr("%c", dirstr[sect.sct_del[I_UW] & 0x7]);
		break;
	    case 30:
		pr("%c", dirstr[sect.sct_del[I_FOOD] & 0x7]);
		break;
	    case 31:
		pr("%c", dirstr[sect.sct_del[I_SHELL] & 0x7]);
		break;
	    case 32:
		pr("%c", dirstr[sect.sct_del[I_GUN] & 0x7]);
		break;
	    case 33:
		pr("%c", dirstr[sect.sct_del[I_PETROL] & 0x7]);
		break;
	    case 34:
		pr("%c", dirstr[sect.sct_del[I_IRON] & 0x7]);
		break;
	    case 35:
		pr("%c", dirstr[sect.sct_del[I_DUST] & 0x7]);
		break;
	    case 36:
		pr("%c", dirstr[sect.sct_del[I_BAR] & 0x7]);
		break;
	    case 37:
		pr("%c", dirstr[sect.sct_del[I_OIL] & 0x7]);
		break;
	    case 38:
		pr("%c", dirstr[sect.sct_del[I_LCM] & 0x7]);
		break;
	    case 39:
		pr("%c", dirstr[sect.sct_del[I_HCM] & 0x7]);
		break;
	    case 40:
		pr("%c", dirstr[sect.sct_del[I_RAD] & 0x7]);
		break;
	    case 41:
		pr("%d", sect.sct_del[I_UW] & ~0x7);
		break;
	    case 42:
		pr("%d", sect.sct_del[I_FOOD] & ~0x7);
		break;
	    case 43:
		pr("%d", sect.sct_del[I_SHELL] & ~0x7);
		break;
	    case 44:
		pr("%d", sect.sct_del[I_GUN] & ~0x7);
		break;
	    case 45:
		pr("%d", sect.sct_del[I_PETROL] & ~0x7);
		break;
	    case 46:
		pr("%d", sect.sct_del[I_IRON] & ~0x7);
		break;
	    case 47:
		pr("%d", sect.sct_del[I_DUST] & ~0x7);
		break;
	    case 48:
		pr("%d", sect.sct_del[I_BAR] & ~0x7);
		break;
	    case 49:
		pr("%d", sect.sct_del[I_OIL] & ~0x7);
		break;
	    case 50:
		pr("%d", sect.sct_del[I_LCM] & ~0x7);
		break;
	    case 51:
		pr("%d", sect.sct_del[I_HCM] & ~0x7);
		break;
	    case 52:
		pr("%d", sect.sct_del[I_RAD] & ~0x7);
		break;
/* level */
	    case 53:
		pr("%d", xrel(getnatp(player->cnum), sect.sct_dist_x));
		break;
	    case 54:
		pr("%d", yrel(getnatp(player->cnum), sect.sct_dist_y));
		break;
	    case 55:
		pr("%d", sect.sct_dist[I_CIVIL]);
		break;
	    case 56:
		pr("%d", sect.sct_dist[I_MILIT]);
		break;
	    case 57:
		pr("%d", sect.sct_dist[I_UW]);
		break;
	    case 58:
		pr("%d", sect.sct_dist[I_FOOD]);
		break;
	    case 59:
		pr("%d", sect.sct_dist[I_SHELL]);
		break;
	    case 60:
		pr("%d", sect.sct_dist[I_GUN]);
		break;
	    case 61:
		pr("%d", sect.sct_dist[I_PETROL]);
		break;
	    case 62:
		pr("%d", sect.sct_dist[I_IRON]);
		break;
	    case 63:
		pr("%d", sect.sct_dist[I_DUST]);
		break;
	    case 64:
		pr("%d", sect.sct_dist[I_BAR]);
		break;
	    case 65:
		pr("%d", sect.sct_dist[I_OIL]);
		break;
	    case 66:
		pr("%d", sect.sct_dist[I_LCM]);
		break;
	    case 67:
		pr("%d", sect.sct_dist[I_HCM]);
		break;
	    case 68:
		pr("%d", sect.sct_dist[I_RAD]);
		break;
	    case 69:
		pr("%d", sect.sct_road);
		break;
	    case 70:
		pr("%d", sect.sct_rail);
		break;
	    case 71:
		pr("%d", SCT_DEFENSE(&sect));
		break;
	    case 72:
		if (opt_FALLOUT)
		    pr("%d", sect.sct_fallout);
		else
		    pr("0");
		break;
	    case 73:
		pr("%d", sect.sct_coastal);
		break;
	    case 74:
		pr("%c", dirstr[sect.sct_del[I_CIVIL] & 0x7]);
		break;
	    case 75:
		pr("%c", dirstr[sect.sct_del[I_MILIT] & 0x7]);
		break;
	    case 76:
		pr("%d", sect.sct_del[I_CIVIL] & ~0x7);
		break;
	    case 77:
		pr("%d", sect.sct_del[I_MILIT] & ~0x7);
		break;
	    case 78:
		pr("%d", sect.sct_terr1);
		break;
	    case 79:
		pr("%d", sect.sct_terr2);
		break;
	    case 80:
		pr("%d", sect.sct_terr3);
		break;
	    }
	}
	pr("\n");
    }
    if (nsect == 0) {
	if (player->argp[1])
	    pr("%s: No sector(s)\n", player->argp[1]);
	else
	    pr("%s: No sector(s)\n", "");
	return RET_FAIL;
    } else
	pr("%d sector%s\n", nsect, splur(nsect));
    return RET_OK;
}
Example #21
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);
}
Example #22
0
/*
 * format: skywatch [<SECTS>]
 */
int
skyw(void)
{
    struct sctstr sect;
    struct nstr_sect nstr;
    struct sky *skyp;
    struct sky *list[TSIZE];
    int i, n;
    int vrange, see;
    int x, y, dx, dy, dxmax;
    int nsat = 0;
    double tech;
    struct nstr_item ni;

    if (!snxtsct(&nstr, player->argp[1]))
	return RET_SYN;
    for (i = 0; i < TSIZE; i++)
	list[i] = NULL;
    skyp = malloc(sizeof(*skyp));
    snxtitem_all(&ni, EF_PLANE);
    while (nxtitem(&ni, &skyp->s_sat)) {
	if (!skyp->s_sat.pln_own)
	    continue;
	if (!pln_is_in_orbit(&skyp->s_sat))
	    continue;
	getsect(skyp->s_sat.pln_x, skyp->s_sat.pln_y, &sect);
	n = scthash(skyp->s_sat.pln_x, skyp->s_sat.pln_y, TSIZE);
	skyp->s_spotted = 0;
	skyp->s_next = list[n];
	list[n] = skyp;
	skyp = malloc(sizeof(*skyp));
	nsat++;
    }
    /* get that last one! */
    free(skyp);
    pr("- = [ Skywatch report for %s ] = -\n", cname(player->cnum));
    pr("  Country            Satellite     Location\n");
    tech = tfact(player->cnum, 1.0);
    while (nxtsct(&nstr, &sect) && nsat) {
	if (sect.sct_own != player->cnum)
	    continue;
	see = sect.sct_type == SCT_RADAR ? 14 : 4;
	vrange = (int)(sect.sct_effic / 100.0 * see * tech);
	if (vrange < 1)
	    vrange = 1;
	for (dy = -vrange; dy <= vrange; dy++) {
	    y = ynorm(sect.sct_y + dy);
	    dxmax = 2 * vrange - abs(dy);
	    for (dx = -dxmax; dx <= dxmax; dx += 2) {
		x = xnorm(sect.sct_x + dx);
		n = scthash(x, y, TSIZE);
		if (!list[n])
		    continue;
		nsat -= showsat(&list[n], x, y);
	    }
	}
    }
    /* free up the sky structs calloc'ed above */
    for (i = 0; i < TSIZE; i++) {
	while (NULL != (skyp = list[i])) {
	    list[i] = skyp->s_next;
	    free(skyp);
	}
    }
    return RET_OK;
}
Example #23
0
int
cuto(void)
{
    struct sctstr sect;
    int nsect;
    int n;
    struct nstr_sect nstr;
    char dirstr[12];

    if (!snxtsct(&nstr, player->argp[1]))
	return RET_SYN;
    prdate();
    (void)strcpy(dirstr, ".      $");
    for (n = 1; n <= 6; n++)
	dirstr[n] = dirch[n];
    nsect = 0;
    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	if (nsect++ == 0) {
	    pr("DELIVERY CUTOFF LEVELS\n");
	    if (player->god)
		pr("own");
	    pr("   sect   cmufsgpidbolhr civ mil  uw food sh gun pet irn dst bar oil lcm hcm rad\n");
	}
	if (player->god)
	    pr("%3d", sect.sct_own);
	prxy("%3d,%-3d", nstr.x, nstr.y); /* FIXME too narrow */
	pr(" %c ", dchr[sect.sct_type].d_mnem);
	pr("%c", dirstr[sect.sct_del[I_CIVIL] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_MILIT] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_UW] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_FOOD] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_SHELL] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_GUN] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_PETROL] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_IRON] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_DUST] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_BAR] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_OIL] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_LCM] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_HCM] & 0x7]);
	pr("%c", dirstr[sect.sct_del[I_RAD] & 0x7]);
	pr("%4d", sect.sct_del[I_CIVIL] & ~0x7);
	pr("%4d", sect.sct_del[I_MILIT] & ~0x7);
	pr("%4d", sect.sct_del[I_UW] & ~0x7);
	pr("%4d", sect.sct_del[I_FOOD] & ~0x7);
	pr("%4d", sect.sct_del[I_SHELL] & ~0x7);
	pr("%4d", sect.sct_del[I_GUN] & ~0x7);
	pr("%4d", sect.sct_del[I_PETROL] & ~0x7);
	pr("%4d", sect.sct_del[I_IRON] & ~0x7);
	pr("%4d", sect.sct_del[I_DUST] & ~0x7);
	pr("%4d", sect.sct_del[I_BAR] & ~0x7);
	pr("%4d", sect.sct_del[I_OIL] & ~0x7);
	pr("%4d", sect.sct_del[I_LCM] & ~0x7);
	pr("%4d", sect.sct_del[I_HCM] & ~0x7);
	pr("%4d", sect.sct_del[I_RAD] & ~0x7);
	pr("\n");
    }
    if (nsect == 0) {
	if (player->argp[1])
	    pr("%s: No sector(s)\n", player->argp[1]);
	else
	    pr("%s: No sector(s)\n", "");
	return RET_FAIL;
    } else
	pr("%d sector%s\n", nsect, splur(nsect));
    return RET_OK;
}
Example #24
0
int
grin(void)
{
    struct nstr_sect nstr;
    struct sctstr sect;
    char *p;
    int prd, i, n, qty;
    char buf[1024];
    double grind_eff = 0.8;
    struct pchrstr *pp;
    i_type ctype;
    unsigned camt;

    prd = dchr[SCT_BANK].d_prd;
    if (prd < 0 || pchr[prd].p_type < 0) {
	pr("Grinding is disabled.\n");
	return RET_FAIL;
    }
    pp = &pchr[prd];

    if (!(p = getstarg(player->argp[1], "Sectors? ", buf)))
	return RET_SYN;
    if (!snxtsct(&nstr, p))
	return RET_SYN;
    p = getstarg(player->argp[2], "amount :  ", buf);
    if (!p || !*p)
	return RET_SYN;
    qty = atoi(p);
    if (qty < 0)
	return RET_SYN;

    while (nxtsct(&nstr, &sect)) {
	if (!player->owner)
	    continue;
	if (sect.sct_effic < 60 || sect.sct_own != player->cnum)
	    continue;

	/* materials limit */
	n = MIN(qty, sect.sct_item[pp->p_type]);
	/* work limit */
	n = MIN(n, sect.sct_avail / 5);
	/* space limit */
	for (i = 0; i < MAXPRCON; i++) {
	    ctype = pp->p_ctype[i];
	    camt = pp->p_camt[i];
	    if (!camt)
		continue;
	    if (CANT_HAPPEN(ctype <= I_NONE || ctype > I_MAX))
		continue;
	    n = MIN(n,
		    (double)(ITEM_MAX - sect.sct_item[ctype])
		    / (camt * grind_eff));
	}

	if (n > 0) {
	    pr("%d bars ground up in %s\n", n,
	       xyas(sect.sct_x, sect.sct_y, player->cnum));
	    sect.sct_item[I_BAR] -= n;
	    for (i = 0; i < MAXPRCON; i++) {
		ctype = pp->p_ctype[i];
		camt = pp->p_camt[i];
		if (!camt)
		    continue;
		if (CANT_HAPPEN(ctype <= I_NONE || ctype > I_MAX))
		    continue;
		sect.sct_item[ctype] += n * camt * grind_eff;
	    }
	    sect.sct_avail -= n * 5;
	    putsect(&sect);
	}
    }
    return RET_OK;
}