Beispiel #1
0
/*
 * Range of a radar with @eff efficiency, @tlev tech, and @spy power.
 */
static int
rad_range(int eff, double tlev, int spy)
{
    int range;

    range = (int)techfact(tlev, spy);
    range = (int)(range * (eff / 100.0));
    if (range < 1)
	range = 1;
    return range;
}
Beispiel #2
0
int
sate(void)
{
    static int sct_shp_or_lnd[] = { EF_SECTOR, EF_SHIP, EF_LAND, EF_BAD };
    double tech;
    int pln_uid;
    struct plnstr plane;
    int type = EF_BAD;

    if (!player->argp[1] ||
	!*player->argp[1] ||
	!isdigit(*player->argp[1]) ||
	(pln_uid = atoi(player->argp[1])) < 0)
	return RET_SYN;

    if (!getplane(pln_uid, &plane)) {
	pr("No such plane\n");
	return RET_FAIL;
    }

    if (plane.pln_own != player->cnum && !player->god) {
	pr("You don't own plane #%d\n", pln_uid);
	return RET_FAIL;
    }

    if (!pln_is_in_orbit(&plane)) {
	pr("%s isn't in orbit\n", prplane(&plane));
	return RET_FAIL;
    }
    if (plane.pln_mobil < plane_mob_max) {
	pr("%s doesn't have enough mobility (needs %d)\n",
	   prplane(&plane), plane_mob_max);
	return RET_FAIL;
    }
    if (player->argp[2]) {
	type = ef_byname_from(player->argp[2], sct_shp_or_lnd);
	if (type < 0) {
	    return RET_SYN;
	}
    }

    if (plchr[(int)plane.pln_type].pl_flags & P_S)
	pr("Satellite Spy Report:\n");
    else
	pr("Satellite Map Report:\n");
    pr("%s at ", prplane(&plane));
    tech = techfact(plane.pln_tech, 20.0);
    return satmap(plane.pln_x, plane.pln_y, plane.pln_effic,
		  (int)tech, plchr[(int)plane.pln_type].pl_flags, type);
}
Beispiel #3
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;
}
Beispiel #4
0
void
plane_sona(struct emp_qelem *plane_list, int x, int y,
	   struct shiplist **head)
{
    struct plnstr *pp;
    struct plchrstr *pcp;
    struct mchrstr *tmcp;
    struct shpstr *targ, s;
    struct natstr *natp;
    struct emp_qelem *qp;
    struct emp_qelem *next;
    struct plist *ip;
    struct sctstr sect;
    int found = 0;
    int range, i, vis;
    int pingrange;
    int vrange;
    int dist;

    getsect(x, y, &sect);
    if ((sect.sct_type != SCT_WATER) && (sect.sct_type != SCT_HARBR))
	return;
    for (qp = plane_list->q_forw; qp != plane_list; qp = next) {
	next = qp->q_forw;
	ip = (struct plist *)qp;
	pp = &ip->plane;
	pcp = ip->pcp;
	if (!(pcp->pl_flags & P_A))	/* if it isn't an ASW plane */
	    continue;
	range = (int)techfact(pp->pln_tech, (100.0 - pln_acc(pp)) / 10.0);
	for (i = 0; getship(i, &s); i++) {
	    targ = &s;
	    if (targ->shp_own == pp->pln_own || targ->shp_own == 0)
		continue;
	    if (on_shiplist(targ->shp_uid, *head))
		continue;
	    tmcp = &mchr[(int)targ->shp_type];
	    if (!(tmcp->m_flags & M_SUB))
		continue;
	    if (!pct_chance(pln_identchance(pp, shp_hardtarget(targ),
					    EF_SHIP)))
		continue;
	    vis = shp_visib(targ);
	    pingrange = MAX(vis, 10) * range / 10;
	    vrange = pingrange * (pp->pln_effic / 200.0);
	    dist = mapdist(targ->shp_x, targ->shp_y, x, y);
	    pingrange = (MAX(pingrange, 2) * targ->shp_effic);
	    pingrange = roundavg(pingrange / 100.0);
	    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(x, y, targ->shp_own), prship(targ));
	    }
	    if ((dist > vrange))
		continue;
	    add_shiplist(targ->shp_uid, head);
	    if (!found) {
		pr("Sonar contact in %s\n", xyas(x, y, player->cnum));
		found = 1;
	    }
	    if (relations_with(targ->shp_own, pp->pln_own) < FRIENDLY &&
		!pct_chance(pln_identchance(pp, shp_hardtarget(targ),
					    EF_SHIP)))
		if (!pct_chance(pln_identchance(pp, shp_hardtarget(targ),
						EF_SHIP)))
		    pr("sub #%d %s\n", targ->shp_uid,
		       xyas(targ->shp_x, targ->shp_y, player->cnum));
		else
		    pr("%s %s\n", prship(targ),
		       xyas(targ->shp_x, targ->shp_y, player->cnum));
	    else
		pr("%s %s @ %s\n", cname(targ->shp_own), prship(targ),
		   xyas(targ->shp_x, targ->shp_y, player->cnum));
	}
    }
    if (found)
	pr("\n");
}
Beispiel #5
0
double
speed_factor(double effspd, int tech)
{
    return 480.0 / (effspd + techfact(tech, effspd));
}
Beispiel #6
0
int
msl_launch(struct plnstr *pp, int type, char *what, coord x, coord y,
	   natid victim, int *sublaunchp)
{
    struct shpstr ship;
    struct nukstr nuke;
    int sublaunch = 0;
    char *base, *in_or_at, *from;

    mpr(pp->pln_own, "Preparing to launch %s at %s %s %s%s\n",
	prplane(pp),
	cname(victim),
	what,
	type != EF_SECTOR ? "in " : "",
	xyas(x, y, pp->pln_own));
    if (pp->pln_ship >= 0) {
	getship(pp->pln_ship, &ship);
	base = prship(&ship);
	in_or_at = " in ";
	if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
	    sublaunch = 1;
	    from = "in hatch";
	} else
	    from = "on deck";
    } else {
	if (pp->pln_harden > 0) {
	    base = "missile silo";
	    in_or_at = " at ";
	    from = "in silo";
	} else {
	    base = in_or_at = "";
	    from = "on launch pad";
	}
    }
    mpr(pp->pln_own, "\tLaunching from %s%s%s\n",
	base, in_or_at, xyas(pp->pln_x, pp->pln_y, pp->pln_own));

    CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED);
    pp->pln_flags |= PLN_LAUNCHED;
    putplane(pp->pln_uid, pp);

    if (chance((0.05 + (100 - pp->pln_effic) / 100.0)
	       * (1 - techfact(pp->pln_tech, 1.0)))) {
	mpr(pp->pln_own, "KABOOOOM!  Missile explodes %s!\n", from);
	if (getnuke(nuk_on_plane(pp), &nuke)) {
	    mpr(pp->pln_own, "%s lost!\n", prnuke(&nuke));
	    nuke.nuk_effic = 0;
	    putnuke(nuke.nuk_uid, &nuke);
	}
#if 0
	/*
	 * Disabled for now, because it breaks callers that call
	 * msl_launch() for each member of a list of planes, created
	 * by msl_sel() or perform_mission().  Damage to the base can
	 * damage other planes.  Any copies of them in the list become
	 * stale.  When msl_launch() modifies and writes back such a
	 * stale copy, the damage gets wiped out, triggering a seqno
	 * oops.
	 */
	if (chance(0.33)) {
	    struct sctstr sect;
	    int dam;

	    dam = pln_damage(pp, 'p', NULL) / 2;
	    if (pp->pln_ship >= 0) {
		shipdamage(&ship, dam);
		putship(ship.shp_uid, &ship);
	    } else {
		mpr(pp->pln_own, "Explosion damages %s %d%%\n",
		    xyas(pp->pln_x, pp->pln_y, pp->pln_own), dam);
		getsect(pp->pln_x, pp->pln_y, &sect);
		sectdamage(&sect, dam);
		putsect(&sect);
	    }
	}
#endif
	return -1;
    }

    mpr(pp->pln_own, "\tSHWOOOOOSH!  Missile launched!\n");

    if (type != EF_PLANE)
	mpr(victim, "Incoming %s missile sighted at %s...\n",
	    sublaunch ? "sub-launched" : cname(pp->pln_own),
	    xyas(x, y, victim));

    if (type == EF_SECTOR || type == EF_LAND) {
	if (msl_abm_intercept(pp, x, y, sublaunch))
	    return -1;
    }
    if (type == EF_SHIP) {
	if (shp_missile_defense(x, y, pp->pln_own, pln_def(pp))) {
	    return -1;
	}
    }

    if (sublaunchp)
	*sublaunchp = sublaunch;
    return 0;
}
Beispiel #7
0
static void
look_land(struct lndstr *lookland)
{
    struct plnstr *pp;
    struct lndstr *lp;
    double drange;
    int range;
    int vrange;
    int i;
    int dist;

    drange = techfact(lookland->lnd_tech, lchr[lookland->lnd_type].l_spy);
    drange *= lookland->lnd_effic / 100.0;
    range = ldround(drange, 1);

    if (range == 0)
	return;

    for (i = 0; NULL != (lp = getlandp(i)); i++) {
	if (lp->lnd_own == player->cnum || lp->lnd_own == 0)
	    continue;
	if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
	    continue;
	/* Don't always see spies */
	if (lchr[(int)lp->lnd_type].l_flags & L_SPY) {
	    /* If it's on a ship or unit, assume it's hidden
	       enough not to be seen */
	    if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
		continue;
	    if (!(chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic))))
		continue;
	}
	vrange = ldround((lnd_vis(lp) * range) / 20.0, 1);
	dist = mapdist(lp->lnd_x, lp->lnd_y,
		       lookland->lnd_x, lookland->lnd_y);
	if (dist > vrange)
	    continue;

	pr("%s %s (approx %d mil) @ %s\n",
	   prnatid(lp->lnd_own), prland(lp),
	   roundintby(lp->lnd_item[I_MILIT], 20),
	   xyas(lp->lnd_x, lp->lnd_y, player->cnum));
	if (opt_HIDDEN)
	    setcont(player->cnum, lp->lnd_own, FOUND_LOOK);
    }
    for (i = 0; NULL != (pp = getplanep(i)); i++) {
	if (pp->pln_own == player->cnum || pp->pln_own == 0)
	    continue;
	if (pp->pln_ship >= 0 || pp->pln_land >= 0)
	    continue;
	if (pp->pln_flags & PLN_LAUNCHED)
	    continue;
	vrange = ldround((10 * range) / 20.0, 1);
	dist = mapdist(pp->pln_x, pp->pln_y,
		       lookland->lnd_x, lookland->lnd_y);
	if (dist > vrange)
	    continue;

	pr("%s %s @ %s\n",
	   prnatid(pp->pln_own), prplane(pp),
	   xyas(pp->pln_x, pp->pln_y, player->cnum));
	if (opt_HIDDEN)
	    setcont(player->cnum, pp->pln_own, FOUND_LOOK);
    }
}
Beispiel #8
0
static void
look_ship(struct shpstr *lookship)
{
    struct shpstr *sp;
    struct mchrstr *smcp;
    struct mchrstr *tmcp;
    struct sctstr sect;
    int range;
    int vrange;
    int i;
    int dist;

    range = (int)techfact(lookship->shp_tech,
			  mchr[(int)lookship->shp_type].m_vrnge);
    range = range * (lookship->shp_effic / 100.0);
    smcp = &mchr[(int)lookship->shp_type];
    if (smcp->m_flags & M_SUB)
	range = MIN(range, 1);
    for (i = 0; NULL != (sp = getshipp(i)); i++) {
	if (sp->shp_own == player->cnum || sp->shp_own == 0)
	    continue;
	dist = mapdist(sp->shp_x, sp->shp_y,
		       lookship->shp_x, lookship->shp_y);
	if (dist > ship_max_interdiction_range)
	    continue;
	tmcp = &mchr[(int)sp->shp_type];
	if (smcp->m_flags & M_SUB)
	    vrange = (int)(shp_visib(sp) * range / 30.0);
	else
	    vrange = (int)(shp_visib(sp) * range / 20.0);
	getsect(sp->shp_x, sp->shp_y, &sect);
	if (sect.sct_type != SCT_WATER)
	    vrange = MAX(1, vrange);
	if (dist > vrange)
	    continue;
	if (smcp->m_flags & M_SUB) {
	    if (tmcp->m_flags & M_SONAR && dist < 2) {
		if (sp->shp_own != 0)
		    wu(0, sp->shp_own,
		       "%s detected surfacing noises in %s.\n",
		       prship(sp),
		       xyas(lookship->shp_x, lookship->shp_y,
			    sp->shp_own));
	    }
	    if (dist == 0 && (tmcp->m_flags & M_SUB) == 0)
		if (sp->shp_own != 0)
		    wu(0, sp->shp_own,
		       "Periscope spotted in %s by %s\n",
		       xyas(lookship->shp_x, lookship->shp_y,
			    sp->shp_own), prship(sp));
	}
	/* subs at sea only seen by sonar */
	if (tmcp->m_flags & M_SUB && sect.sct_type == SCT_WATER)
	    continue;
	pr("%s %s @ %s\n",
	   prnatid(sp->shp_own), prship(sp),
	   xyas(sp->shp_x, sp->shp_y, player->cnum));
	if (opt_HIDDEN)
	    setcont(player->cnum, sp->shp_own, FOUND_LOOK);
    }
}