Beispiel #1
0
int
do_look(int type)
{
    int i;
    struct nstr_item ni;
    union empobj_storage unit;
    struct sctstr sect;
    int x, y;
    unsigned char *bitmap;
    int changed = 0;

    if (CANT_HAPPEN(type != EF_LAND && type != EF_SHIP))
	type = EF_SHIP;

    if (!snxtitem(&ni, type, player->argp[1], NULL))
	return RET_SYN;
    bitmap = calloc((WORLD_SZ() + 7) / 8, 1);
    if (!bitmap) {
	logerror("malloc failed in do_look\n");
	pr("Memory error.  Tell the deity.\n");
	return RET_FAIL;
    }
    while (nxtitem(&ni, &unit)) {
	if (!player->owner)
	    continue;
	if (type == EF_LAND) {
	    if (unit.land.lnd_ship >= 0)
		continue;
	    if (unit.land.lnd_land >= 0)
		continue;
	    /* Spies don't need military to do a "llook".  Other
	       units do */
	    if ((unit.land.lnd_item[I_MILIT] <= 0) &&
		!(lchr[(int)unit.land.lnd_type].l_flags & L_SPY))
		continue;
	    look_land(&unit.land);
	} else
	    look_ship(&unit.ship);
	for (i = 0; i <= 6; i++) {
	    x = diroff[i][0] + unit.gen.x;
	    y = diroff[i][1] + unit.gen.y;
	    if (emp_getbit(x, y, bitmap))
		continue;
	    emp_setbit(x, y, bitmap);
	    getsect(x, y, &sect);
	    if (sect.sct_type == SCT_WATER)
		continue;
	    look_at_sect(&sect, 10);
	    changed += map_set(player->cnum, x, y,
			       dchr[sect.sct_type].d_mnem, 0);
	    if (opt_HIDDEN) {
		setcont(player->cnum, sect.sct_own, FOUND_LOOK);
	    }
	}
    }
    if (changed)
	writemap(player->cnum);
    free(bitmap);
    return RET_OK;
}
Beispiel #2
0
struct option *getoptions(const char *sect_name)
{
	struct sect *s = getsect(sect_name, NULL);
	if (s)
		return s->opts;
	return NULL;
}
Beispiel #3
0
static void
unit_view(struct emp_qelem *list)
{
    struct sctstr sect;
    struct emp_qelem *qp;
    struct emp_qelem *next;
    struct ulist *ulp;

    for (qp = list->q_back; qp != list; qp = next) {
	next = qp->q_back;
	ulp = (struct ulist *)qp;
	if (CANT_HAPPEN(!(ef_flags(ulp->unit.gen.ef_type) & EFF_XY)))
	    continue;
	getsect(ulp->unit.gen.x, ulp->unit.gen.y, &sect);
	if (ulp->unit.gen.ef_type == EF_SHIP) {
	    if (mchr[ulp->unit.ship.shp_type].m_flags & M_FOOD)
		pr("[fert:%d] ", sect.sct_fertil);
	    if (mchr[ulp->unit.ship.shp_type].m_flags & M_OIL)
		pr("[oil:%d] ", sect.sct_oil);
	}
	pr("%s @ %s %d%% %s\n", unit_nameof(&ulp->unit.gen),
	   xyas(ulp->unit.gen.x, ulp->unit.gen.y, player->cnum),
	   sect.sct_effic, dchr[sect.sct_type].d_name);
    }
}
Beispiel #4
0
void
pln_mine(struct emp_qelem *list, coord tx, coord ty)
{
    struct emp_qelem *qp;
    struct plist *plp;
    int amt;
    struct sctstr sect;

    amt = 0;
    for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
	plp = (struct plist *)qp;
	amt += plp->load;

    }
    if (amt > 0) {
	getsect(tx, ty, &sect);
	if (sect.sct_type != SCT_WATER) {
	    pr("Your seamines have no effect here.\n");
	    return;
	}
	sect.sct_mines = MIN(sect.sct_mines + amt, MINES_MAX);
	pr("%d mines laid in %s.\n", amt, xyas(tx, ty, player->cnum));
	if (map_set(player->cnum, tx, ty, 'X', 0))
	    writemap(player->cnum);
	putsect(&sect);
    }
}
Beispiel #5
0
/*
 * Get assembly point argument.
 * If INPUT is not empty, use it, else prompt for more input using PROMPT.
 * If this yields a valid assembly point, read it into *AP_SECT and
 * return AP_SECT.
 * Else complain and return NULL.
 * *AP_SECT and BUF[1024] may be modified in either case.
 */
struct sctstr *
get_assembly_point(char *input, struct sctstr *ap_sect, char *buf)
{
    char *p;
    coord x, y;
    struct nstr_item ni;
    struct shpstr ship;

    p = getstarg(input, "assembly point? ", buf);
    if (!p || *p == 0)
	return NULL;
    if (!sarg_xy(p, &x, &y) || !getsect(x, y, ap_sect))
	return NULL;

    /* over own or allied sector is fine */
    if (relations_with(ap_sect->sct_own, player->cnum) == ALLIED)
	return ap_sect;

    /* over own or allied ship is fine */
    snxtitem_xy(&ni, EF_SHIP, x, y);
    while (nxtitem(&ni, &ship)) {
	if (ship.shp_effic < SHIP_MINEFF || ship.shp_own == 0)
	    continue;
	if (relations_with(ship.shp_own, player->cnum) == ALLIED)
	    return ap_sect;
    }

    pr("Assembly point not owned by you or an ally!\n");
    return NULL;
}
Beispiel #6
0
/*
 * Find out whether planes can fly one-way to X,Y.
 * Offer the player any carriers there.  If he chooses one, read it
 * into TARGET->ship.  Else read the target sector into TARGET->sect.
 * If planes can land there, set required plane flags in *FLAGSP, and
 * return 0.  Else return -1.
 */
int
pln_where_to_land(coord x, coord y,
		  union empobj_storage *target, int *flagsp)
{
    int nships;
    int cno;
    int fl;
    char buf[1024];
    char *p;

    /* offer carriers */
    nships = carriersatxy(x, y, player->cnum);
    if (nships) {
	for (;;) {
	    p = getstring("Carrier #? ", buf);
	    if (!p)
		return -1;
	    if (!*p)
		break;
	    cno = atoi(p);
	    if (!getship(cno, &target->ship)
		|| (!player->owner
		    && (relations_with(target->ship.shp_own, player->cnum)
			!= ALLIED))) {
		pr("Not yours\n");
		continue;
	    }
	    if (target->ship.shp_x != x || target->ship.shp_y != y) {
		pr("Ship #%d not in %s\n", cno, xyas(x, y, player->cnum));
		continue;
	    }
	    fl = carrier_planes(&target->ship, 0);
	    if (fl == 0) {
		pr("Can't land on %s.\n", prship(&target->ship));
		continue;
	    }
	    /* clear to land on ship#CNO */
	    pr("landing on carrier %d\n", cno);
	    *flagsp |= fl;
	    return 0;
	}
    }

    /* try to land at sector */
    getsect(x, y, &target->sect);
    if (relations_with(target->sect.sct_own, player->cnum) != ALLIED) {
	pr("Nowhere to land at sector %s!\n", xyas(x, y, player->cnum));
	return -1;
    }
    if (target->sect.sct_type == SCT_MOUNT) {
	pr("Nowhere to land at sector %s!\n", xyas(x, y, player->cnum));
	return -1;
    }
    /* clear to land at sector */
    if (target->sect.sct_type != SCT_AIRPT || target->sect.sct_effic < 60)
	*flagsp |= P_V;
    return 0;
}
Beispiel #7
0
static char *
unit_move_route(struct empobj *unit, char *buf, size_t bufsz)
{
    coord destx;
    coord desty;
    struct sctstr sect;
    size_t len;
    double c;
    int mtype;

    if (CANT_HAPPEN(unit->ef_type != EF_LAND && unit->ef_type != EF_SHIP))
	return NULL;

    if (!sarg_xy(buf, &destx, &desty))
	return buf;
    if (unit->ef_type == EF_SHIP) {
	c = path_find(unit->x, unit->y, destx, desty,
		      player->cnum, MOB_SAIL);
	if (c < 0 || unit->mobil <= 0) {
	    pr("Can't get to '%s' right now.\n",
	       xyas(destx, desty, player->cnum));
	    return NULL;
	}
    } else {
	getsect(unit->x, unit->y, &sect);
	mtype = lnd_mobtype((struct lndstr *)unit);
	/*
	 * Note: passing sect.sct_own for actor is funny, but works:
	 * its only effect is to confine the search to that nation's
	 * land.  It doesn't affect mobility costs.  The real actor is
	 * different for marching in allied land, and passing it would
	 * break path finding there.
	 */
	c = path_find(unit->x, unit->y, destx, desty, sect.sct_own, mtype);
	if (c < 0) {
	    pr("No owned %s from %s to %s!\n",
	       mtype == MOB_RAIL ? "railway" : "path",
	       xyas(unit->x, unit->y, player->cnum),
	       xyas(destx, desty, player->cnum));
	    return NULL;
	}
    }
    len = path_find_route(buf, bufsz, unit->x, unit->y, destx, desty);
    if (len == 0 || unit->ef_type == EF_LAND) {
	if (len + 1 < bufsz)
	    strcpy(buf + len, "h");
	len++;
    }
    if (len >= bufsz) {
	pr("Can't handle path to %s, it's too long, sorry\n",
	   xyas(destx, desty, player->cnum));
	return NULL;
    }
    pr("Using path '%s'\n", buf);
    return buf;
}
Beispiel #8
0
int
msl_abm_intercept(struct plnstr *msl, coord x, coord y, int sublaunch)
{
    struct sctstr sect;
    struct emp_qelem irvlist;

    getsect(x, y, &sect);
    msl_sel(&irvlist, x, y, msl->pln_own, P_N, P_O, 0);
    return msl_intercept(msl, &sect, sublaunch,
			 &irvlist, "warhead", "abm",
			 sublaunch ? N_NUKE_SSTOP : N_NUKE_STOP);
}
Beispiel #9
0
struct sect *addsect(const char *name)
{
	struct sect *s = getsect(name, NULL);
	if (!s) {
		s = malloc(sizeof(struct sect));
		strcpy(s->name, name);
		s->opts = NULL;
		s->next = sect_hd.next;
		sect_hd.next = s;
	}
	return s;
}
Beispiel #10
0
void unsetoption(const char *sect_name, const char *key)
{
	struct sect *s = getsect(sect_name, NULL);
	struct option *o;
	if (!s || !s->opts)
		return;
	o = s->opts;
	if (!strcmp(key, opt_key(o))) {
		s->opts = o->next;
		free(o);
	} else
		rmopt(key, o);
}
Beispiel #11
0
void
bridgefall(struct sctstr *sp)
{
    int i;
    int j;
    struct sctstr sect;
    struct sctstr bh_sect;
    int nx;
    int ny;
    int nnx;
    int nny;

    if (CANT_HAPPEN(opt_EASY_BRIDGES))
	return;

    for (i = 1; i <= 6; i++) {
	nx = sp->sct_x + diroff[i][0];
	ny = sp->sct_y + diroff[i][1];
	getsect(nx, ny, &sect);
	if (sect.sct_type != SCT_BSPAN)
	    continue;
	for (j = 1; j <= 6; j++) {
	    nnx = nx + diroff[j][0];
	    nny = ny + diroff[j][1];
	    if (nnx == sp->sct_x && nny == sp->sct_y)
		continue;
	    getsect(nnx, nny, &bh_sect);
	    if (bh_sect.sct_type == SCT_BHEAD &&
		bh_sect.sct_newtype == SCT_BHEAD)
		break;
	    if (bh_sect.sct_type == SCT_BTOWER)
		break;
	}
	if (j > 6) {
	    knockdown(&sect);
	    putsect(&sect);
	}
    }
}
Beispiel #12
0
int
msl_asat_intercept(struct plnstr *msl, coord x, coord y)
{
    struct sctstr sect;
    struct emp_qelem irvlist;

    getsect(x, y, &sect);
    mpr(sect.sct_own, "%s has positioned a satellite over %s\n",
	cname(msl->pln_own), xyas(x, y, sect.sct_own));
    msl_sel(&irvlist, x, y, msl->pln_own, P_O, 0, 0);
    return msl_intercept(msl, &sect, 0,
			 &irvlist, "satellite", "a-sat missile",
			 N_SAT_KILL);
}
Beispiel #13
0
static int
coastal_land_to_sea(coord x, coord y)
{
    int n;
    struct sctstr sect;

    for (n = 1; n <= 6; ++n) {	/* Directions */
	getsect(x + diroff[n][0], y + diroff[n][1], &sect);
	if (!sect.sct_coastal) {
	    sect.sct_coastal = 1;
	    putsect(&sect);
	}
    }

    return 1;
}
Beispiel #14
0
void
pln_put1(struct plist *plp)
{
    struct plnstr *pp;
    struct shpstr ship;
    struct sctstr sect;

    pp = &plp->plane;

    if (CANT_HAPPEN((pp->pln_flags & PLN_LAUNCHED)
		    && (plchr[pp->pln_type].pl_flags & P_M)
		    && pp->pln_effic >= PLANE_MINEFF))
	pp->pln_effic = 0;   /* bug: missile launched but not used up */

    if (!(pp->pln_flags & PLN_LAUNCHED))
	;			/* never took off */
    else if (pp->pln_effic < PLANE_MINEFF) {
	;			/* destroyed */
    } else if (pp->pln_ship >= 0) {
	/* It is landing on a carrier */
	getship(pp->pln_ship, &ship);
	/* We should do more, like make sure it's really
	   a carrier, etc. but for now just make sure it's
	   not sunk. */
	if (ship.shp_effic < SHIP_MINEFF) {
	    mpr(pp->pln_own,
		"Ship #%d has been sunk, plane #%d has nowhere to land, and\n"
		"splashes into the sea.\n",
		pp->pln_ship, pp->pln_uid);
	    pp->pln_effic = 0;
	}
    } else {
	/* Presume we are landing back in a sector. */
	getsect(pp->pln_x, pp->pln_y, &sect);
	if (sect.sct_type == SCT_WATER || sect.sct_type == SCT_WASTE) {
	    mpr(pp->pln_own,
		"Nowhere to land at %s, plane #%d crashes and burns...\n",
		xyas(pp->pln_x, pp->pln_y, pp->pln_own), pp->pln_uid);
	    pp->pln_effic = 0;
	}
    }
    pp->pln_flags &= ~PLN_LAUNCHED;
    putplane(pp->pln_uid, pp);
    emp_remque(&plp->queue);
    free(plp);
}
Beispiel #15
0
void
pln_newlanding(struct emp_qelem *list, coord tx, coord ty, int cno)
{
    struct emp_qelem *qp;
    struct plist *plp;
    struct shpstr ship;
    struct sctstr sect;

    if (cno >= 0)
	getship(cno, &ship);
    for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
	plp = (struct plist *)qp;
	if (cno >= 0) {
	    if (!could_be_on_ship(&plp->plane, &ship))
		pr("\t%s cannot land on ship #%d! %s aborts!\n",
		   prplane(&plp->plane), cno, prplane(&plp->plane));
	    else if (!put_plane_on_ship(&plp->plane, &ship))
		pr("\tNo room on ship #%d! %s aborts!\n",
		   cno, prplane(&plp->plane));
	    else {
		if (plp->plane.pln_own != ship.shp_own) {
		    wu(0, ship.shp_own, "%s %s lands on your %s\n",
		       cname(player->cnum), prplane(&plp->plane),
		       prship(&ship));
		}
		if (plp->pcp->pl_crew && plp->pstage == PLG_INFECT
		    && ship.shp_pstage == PLG_HEALTHY)
		    ship.shp_pstage = PLG_EXPOSED;
	    }
	} else {
	    plp->plane.pln_x = tx;
	    plp->plane.pln_y = ty;
	    getsect(tx, ty, &sect);
	    if (plp->plane.pln_own != sect.sct_own) {
		wu(0, sect.sct_own,
		   "%s %s lands at your sector %s\n",
		   cname(player->cnum),
		   prplane(&plp->plane), xyas(tx, ty, sect.sct_own));
	    }
	    if (plp->pcp->pl_crew && plp->pstage == PLG_INFECT
		&& sect.sct_pstage == PLG_HEALTHY)
		sect.sct_pstage = PLG_EXPOSED;
	    plp->plane.pln_ship = cno;
	}
    }
}
Beispiel #16
0
static int
coastal_sea_to_land(coord x, coord y)
{
    int n, c;
    struct sctstr sect;

    for (n = 1; n <= 6; n++) {	/* Directions */
	getsect(x + diroff[n][0], y + diroff[n][1], &sect);
	c = update_coastal_flag(sect.sct_x, sect.sct_y, x, y);
	if (!sect.sct_coastal != !c) {
	    sect.sct_coastal = c;
	    putsect(&sect);
	}
    }

    return update_coastal_flag(x, y, x, y);
}
Beispiel #17
0
static int
update_coastal_flag(coord x, coord y, coord ign_x, coord ign_y)
{
    int n;
    struct sctstr sect;

    for (n = 1; n <= 6; n++) {	/* Directions */
	getsect(x + diroff[n][0], y + diroff[n][1], &sect);
	if (sect.sct_x == ign_x && sect.sct_y == ign_y)
	    continue;
	if (sect.sct_type == SCT_WATER || sect.sct_type == SCT_BTOWER ||
	    sect.sct_type == SCT_BSPAN)
	    return 1;
    }

    return 0;
}
Beispiel #18
0
void
plane_sweep(struct emp_qelem *plane_list, coord x, coord y)
{
    struct plnstr *pp;
    struct plchrstr *pcp;
    struct emp_qelem *qp;
    struct emp_qelem *next;
    struct plist *ip;
    struct sctstr sect;
    int mines_there;
    int found = 0;

    getsect(x, y, &sect);
    mines_there = sect.sct_mines;

    if (mines_there == 0)
	return;

    if (sect.sct_type != SCT_WATER)
	return;

    for (qp = plane_list->q_forw; ((qp != plane_list) && (mines_there));
	 qp = next) {
	next = qp->q_forw;
	ip = (struct plist *)qp;
	pp = &ip->plane;
	pcp = ip->pcp;
	if (!(pcp->pl_flags & P_SWEEP))	/* if it isn't an sweep plane */
	    continue;

	if (chance((100.0 - pln_acc(pp)) / 100.0)) {
	    pr("Sweep! in %s\n",
	       xyas(sect.sct_x, sect.sct_y, player->cnum));
	    mines_there--;
	    found = 1;
	}
    }

    if (found && map_set(player->cnum, sect.sct_x, sect.sct_y, 'X', 0))
	writemap(player->cnum);
    sect.sct_mines = mines_there;
    putsect(&sect);
}
Beispiel #19
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;
}
Beispiel #20
0
void
bridgefall(struct sctstr *sp)
{
    int i;
    struct sctstr sect;
    int nx;
    int ny;

    for (i = 1; i <= 6; i++) {
	nx = sp->sct_x + diroff[i][0];
	ny = sp->sct_y + diroff[i][1];
	getsect(nx, ny, &sect);
	if (sect.sct_type == SCT_BSPAN
	    && !bridge_support_at(&sect, DIR_BACK(i))) {
	    knockdown(&sect);
	    putsect(&sect);
	}
    }
}
Beispiel #21
0
int
check_lmines(coord x, coord y, double weight)
{
    struct sctstr sect;
    int dam = 0;

    getsect(x, y, &sect);
    if (SCT_LANDMINES(&sect) > 0 &&
	sect.sct_oldown != player->cnum &&
	chance(DMINE_LHITCHANCE(sect.sct_mines)) && chance(weight / 100.0)) {
	pr_beep();
	pr("Blammo! Landmines detected! in %s  ",
	   xyas(sect.sct_x, sect.sct_y, player->cnum));
	dam = roll(20);
	--sect.sct_mines;
	putsect(&sect);
	pr("%d damage sustained.\n", dam);
    }
    return dam;
}
Beispiel #22
0
void
move_sat(struct plnstr *pp)
{
    coord x1, y1, x2, y2;
    coord dx, dy;
    float newtheta;
    struct sctstr sect;

    newtheta = pp->pln_theta + .05;

    if (newtheta >= 1.0) {
	newtheta -= 1.0;
    }

    x1 = (coord)(2 * pp->pln_theta * WORLD_X);
    x1 = xnorm(x1);
    y1 = (coord)(sin(6 * PI * pp->pln_theta) * (WORLD_Y / 4));
    x2 = (coord)(2 * newtheta * WORLD_X);
    x2 = xnorm(x2);
    y2 = (coord)(sin(6 * PI * newtheta) * (WORLD_Y / 4));
    dx = x1 - pp->pln_x;
    dy = y1 - pp->pln_y;
    x2 -= dx;
    y2 -= dy;

    if ((x2 + y2) & 1) {
	x2++;
    }

    pp->pln_x = xnorm(x2);
    pp->pln_y = ynorm(y2);
    pp->pln_theta = newtheta;
    getsect(pp->pln_x, pp->pln_y, &sect);
    if (sect.sct_own)
	if (pp->pln_own != sect.sct_own)
	    wu(0, sect.sct_own, "%s satellite spotted over %s\n",
	       cname(pp->pln_own), xyas(pp->pln_x, pp->pln_y,
					sect.sct_own));
    return;
}
Beispiel #23
0
void freeoptions(const char *sect_name)
{
	struct sect *s, *p;
	struct option *o;
	if (sect_name[0]) {
		s = getsect(sect_name, &p);
		if (!s)
			return;
		p->next = s->next;
	} else {
		while (sect_hd.next)
			freeoptions(sect_hd.next->name);
		s = &sect_hd;
	}
	while (o = s->opts) {
		s->opts = o->next;
		free(o);
	}
	if (sect_name[0])
		free(s);
	else
		s->opts = NULL;
}
Beispiel #24
0
/*
 * Is there support for a bridge at @sp?
 * Ignore support coming from direction @ignore_dir.
 */
int
bridge_support_at(struct sctstr *sp, int ignore_dir)
{
    int i, nx, ny;
    struct sctstr sect;

    for (i = 1; i <= 6; i++) {
	if (i == ignore_dir)
	    continue;
	nx = sp->sct_x + diroff[i][0];
	ny = sp->sct_y + diroff[i][1];
	getsect(nx, ny, &sect);
	if (opt_EASY_BRIDGES
	    && sect.sct_type != SCT_WATER && sect.sct_type != SCT_BSPAN)
	    return 1;
	if (sect.sct_effic < SCT_MINEFF)
	    continue;
	if (sect.sct_type == SCT_BHEAD && sect.sct_newtype == SCT_BHEAD)
	    return 1;
	if (sect.sct_type == SCT_BTOWER)
	    return 1;
    }
    return 0;
}
Beispiel #25
0
int
move_ground(struct sctstr *start, struct sctstr *end,
	    double weight, char *path,
	    int (*map)(coord, coord, char *, char *),
	    int exploring, int *dam)
{
    struct sctstr sect;
    struct sctstr next;
    coord curx, cury, oldx, oldy;
    coord tmpx, tmpy;
    coord dx, dy;
    char *movstr;
    double sect_mcost;
    double total_mcost;
    double mv_cost;
    size_t len;
    double mobility = start->sct_mobil;
    int dir;
    char scanspace[1024];
    char *argp[128];
    int takedam = *dam;
    int out = 0;
    char prompt[128];
    char buf[1024];

    *end = *start;
    if (mobility <= 0.0)
	return -1;
    *dam = 0;
    if (path && sarg_xy(path, &dx, &dy)) {
	if (dx == start->sct_x && dy == start->sct_y) {
	    pr("Start sector is ending sector!\n");
	    return -1;
	}
	pr("Looking for best path to %s\n", path);
	total_mcost = path_find(start->sct_x, start->sct_y, dx, dy,
				player->cnum, MOB_MOVE);
	path = NULL;
	if (total_mcost < 0)
	    pr("No owned path exists!\n");
	else {
	    len = path_find_route(buf, sizeof(buf),
				  start->sct_x, start->sct_y, dx, dy);
	    if (!exploring) {
		if (len < sizeof(buf))
		    strcpy(buf + len, "h");
		len++;
	    }
	    if (len >= sizeof(buf))
		pr("Can't handle path to %s, it's too long, sorry.\n",
		   xyas(dx, dy, player->cnum));
	    else {
		path = buf;
		pr("Using best path '%s', movement cost %1.3f\n",
		   path, total_mcost);
		if (total_mcost * weight > mobility) {
		    pr("Not enough mobility to go all the way."
		       " Nothing moved.\n");
		    return -1;
		}
	    }
	}
    }
    movstr = path;
    curx = start->sct_x;
    cury = start->sct_y;
    total_mcost = 0.0;
    if (getsect(curx, cury, &sect) < 0) {
	logerror("move_path: getsect %d,%d", curx, cury);
	return -1;
    }
    for (;;) {
	oldx = curx;
	oldy = cury;
	if (!movstr || *movstr == 0) {
	    if (exploring) {
		map(curx, cury, NULL, NULL);
	    } else {
		move_map(curx, cury, NULL);
	    }
	    sprintf(prompt, "<%.1f: %c %s> ", mobility,
		    dchr[sect.sct_type].d_mnem,
		    xyas(sect.sct_x, sect.sct_y, player->cnum));
	    movstr = getstring(prompt, buf);
	}
	if (movstr && sarg_xy(movstr, &dx, &dy)) {
	    mv_cost = path_find(sect.sct_x, sect.sct_y, dx, dy,
				player->cnum, MOB_MOVE);
	    if (mv_cost < 0) {
		pr("Can't get to %s from here!\n",
		   xyas(dx, dy, player->cnum));
		movstr = NULL;
	    } else {
		len = path_find_route(buf, sizeof(buf),
				      sect.sct_x, sect.sct_y, dx, dy);
		if (len < sizeof(buf))
		    strcpy(buf + len, "h");
		len++;
		if (len >= sizeof(buf)) {
		    pr("Can't handle path to %s, it's too long, sorry.\n",
		       xyas(dx, dy, player->cnum));
		    movstr = NULL;
		} else {
		    if ((mv_cost * weight) > mobility) {
			pr("Not enough mobility to go all the way. Nothing moved.\n");
			movstr = NULL;
		    } else {
			movstr = buf;
			pr("Using best path '%s', movement cost %1.3f\n",
			   movstr, mv_cost);
		    }
		}
	    }
	}
	if (!movstr || *movstr == 0) {
	    buf[0] = dirch[DIR_STOP];
	    buf[1] = 0;
	    movstr = buf;
	}
	if ((dir = chkdir(*movstr, DIR_STOP, DIR_MAP)) < 0) {
	    pr("\"%c\" is not legal...", *movstr);
	    direrr("'%c' to stop ", "'%c' to view ", "& '%c' to map\n");
	    *movstr = 0;
	    continue;
	}
	if (dir == DIR_MAP) {
	    parse(movstr, scanspace, argp, NULL, NULL, NULL);
	    if (argp[0][1]) {
		pr("Use of '%c' without a space before its argument is deprecated.\n"
		   "Support for it will go away in a future release\n",
		   *movstr);
		argp[2] = argp[1];
		argp[1] = argp[0] + 1;
	    }
	    if (!exploring)
		map(curx, cury, argp[1], argp[2]);
	    *movstr = 0;
	    continue;
	}
	movstr++;
	if (dir == DIR_STOP)
	    break;
	if (dir == DIR_VIEW) {
	    pr("%d%% %s with %d civilians.\n", sect.sct_effic,
	       dchr[sect.sct_type].d_name, sect.sct_item[I_CIVIL]);
	    continue;
	}
	/*
	 * now see if we can move into the
	 * next sector.  Mobility, terrain,
	 * or ownership may prevent us.
	 */
	tmpx = curx + diroff[dir][0];
	tmpy = cury + diroff[dir][1];
	if (getsect(tmpx, tmpy, &next) < 0) {
	    pr("You can't go there...\n");
	    *movstr = 0;
	    continue;
	}
	if (!player->god) {
	    if ((next.sct_type == SCT_SANCT) &&
		(next.sct_own != player->cnum)) {
		pr("Converts, huh?\n");
		*movstr = 0;
		continue;
	    }
	    sect_mcost = sector_mcost(&next, MOB_MOVE);
	    if ((!player->owner && (!exploring
				    || next.sct_item[I_MILIT]
				    || next.sct_item[I_CIVIL]))
		|| sect_mcost == -1.0) {
		/* already-owned, or prohibited terrain */
		pr("You can't go there...\n");
		*movstr = 0;
		continue;
	    }
	    sect_mcost *= weight;
	    if (sect_mcost > mobility) {
		pr("Not enough mobility.  ");
		pr("You can't go there...\n");
		*movstr = 0;
		continue;
	    }
	    mobility -= sect_mcost;
	    total_mcost += sect_mcost;
	}
	curx = next.sct_x;
	cury = next.sct_y;
	if (cury != start->sct_y)
	    out = 1;
	if (curx != start->sct_x)
	    out = 1;

	sect = next;

	if (takedam)
	    *dam += check_lmines(sect.sct_x, sect.sct_y, weight);
	if (*dam >= 100)
	    break;
	/*
	 * Check and see if anyone will interdict us
	 */
	if (takedam && chance(weight / 100.0) &&
	    ((curx != oldx) || (cury != oldy)))
	    *dam += ground_interdict(curx, cury, player->cnum,
				     "commodities");
	if (*dam >= 100)
	    break;
    }
    *end = sect;
    if ((start->sct_x == end->sct_x) && (start->sct_y == end->sct_y)
	&& !out)
	return -1;

    return roundavg(total_mcost);
}
Beispiel #26
0
void jump(unsigned short addr)
{
        if (swtpc) {
                pc = addr;
                return;
        } else {
                switch (addr) {
/* Too many programs access ACIA directly */
#if 0
                        case 0xF9CF: case 0xF9DC: /* Output a character */ {
                                term_out(acca);
                                /* putchar(acca); fflush(stdout); */
                                c_flag = 0; /* Carry is error status */
                                break;
                        }
#endif
                        case 0xFA8B: /* Input a character */ {
                                acca = term_in();
                                if (!mem[0xFF53]) { /* Echo */
                                        term_out(acca);
                                        /* putchar(c);
                                        fflush(stdout); */
                                } else {
                                        mem[0xFF53] = 0;
                                }
                                c_flag = 0; /* No error */
                                break;
                        }
                        case 0xE800: /* OSLOAD (no modified parms) */ {
                                printf("\nOSLOAD...\n");
                                getsect(0, 0x0020, 23, 128);
                                getsect(0, 0x0020 + 0x0080, 24, 128);
                                pc = 0x0020;
                                sp = 0x00FF;
                                return;
                        } case 0xE822: /* FDINIT (no modified parms) */ {
                                c_flag = 0;
                                break;
                        } 
#if 0
                          case 0xF853: /* CHKERR */ {
                                break;
                        } case 0xE85A: /* PRNTER */ {
                                break;
                        } 
#endif
                          case 0xE869: /* READSC (read full sectors) */ {
                                mem[LSCTLN] = 128;
                        } case 0xE86D: /* READPS (read partial sectors) (FDSTAT, carry, sides) */ {
                                int x;
                                int n = mem[CURDRV];
                                int first = (mem[STRSCT] << 8) + mem[STRSCT + 1];
                                int num = (mem[NUMSCT] << 8) + mem[NUMSCT + 1];
                                int addr = (mem[CURADR] << 8) + mem[CURADR + 1];
                                int last = mem[LSCTLN];
                                if (trace_disk) printf("Read sectors: drive=%d, first=%d, number=%d, addr=%x, size of last=%d\n", n, first, num,
                                       addr, last);
                                if (check_drive(n))
                                        break;
                                for (x = 0; x != num; ++x) {
                                        if (check_sect(n, first + x))
                                                goto oops;
                                        getsect(n, addr + 128 * x, first + x, ((x + 1 == num) ? mem[LSCTLN] : 128));
                                }
                                mem[FDSTAT] = ER_NON;
                                if (drive[n].tracks == 77)
                                        mem[SIDES] = 0x80;
                                else
                                        mem[SIDES] = 0;
                                c_flag = 0;
                                oops: break;
                        } case 0xE86F: /* RDCRC */ {
                                if (trace_disk) printf("RDCRC\n");
                                int x;
                                int n = mem[CURDRV];
                                int first = (mem[STRSCT] << 8) + mem[STRSCT + 1];
                                int num = (mem[NUMSCT] << 8) + mem[NUMSCT + 1];
                                int addr = (mem[CURADR] << 8) + mem[CURADR + 1];
                                int last = mem[LSCTLN];
                                if (trace_disk) printf("RDCRC: drive=%d, first=%d, number=%d, addr=%x, size of last=%d\n", n, first, num,
                                       addr, last);
                                if (check_drive(n))
                                        break;
                                for (x = 0; x != num; ++x) {
                                        if (check_sect(n, first + x))
                                                goto oops;
                                }
                                mem[FDSTAT] = ER_NON;
                                if (drive[n].tracks == 77)
                                        mem[SIDES] = 0x80;
                                else
                                        mem[SIDES] = 0;
                                c_flag = 0;
                                break;
                        } case 0xE875: /* RESTOR */ {
                                int n = mem[CURDRV];
                                if (trace_disk) printf("RESTOR\n");
                                if (check_drive(n))
                                        break;
                                mem[FDSTAT] = ER_NON;
                                if (drive[n].tracks == 77)
                                        mem[SIDES] = 0x80;
                                else
                                        mem[SIDES] = 0;
                                c_flag = 0;
                                break;
                        } case 0xE878: /* SEEK */ {
                                int n = mem[CURDRV];
                                int first = (mem[STRSCT] << 8) + mem[STRSCT + 1];
                                if (trace_disk) printf("SEEK\n");
                                if (check_drive(n))
                                        break;
                                if (check_sect(n, first))
                                        break;
                                if (drive[n].tracks == 77)
                                        mem[SIDES] = 0x80;
                                else
                                        mem[SIDES] = 0;
                                c_flag = 0;
                                break;
                        } case 0xE872: /* RWTEST */ {
                                if (trace_disk) printf("RWTEST\n");
                        } case 0xE87B: /* WRTEST */ {
                                unsigned char buf[128];
                                int x;
                                int n = mem[CURDRV];
                                int first = (mem[STRSCT] << 8) + mem[STRSCT + 1];
                                int num = (mem[NUMSCT] << 8) + mem[NUMSCT + 1];
                                int addr = (mem[CURADR] << 8) + mem[CURADR + 1];
                                int last = mem[LSCTLN];
                                if (trace_disk) printf("WRTEST\n");
                                if (check_drive(n))
                                        break;
                                for (x = 0; x != 128; x += 2) {
                                        buf[x] = mem[addr];
                                        buf[x + 1] = mem[addr + 1];
                                }
                                for(x=0; x != num; ++x) {
                                        if (check_sect(n, first + x))
                                                goto oops;
                                        if (trace_disk) printf("Wrtest sector %d drive %d\n", first + x, n);
                                        fseek(drive[n].f, (first + x) * 128, SEEK_SET);
                                        fwrite(buf, 128, 1, drive[n].f);
                                        fflush(drive[n].f);
                                }
                                c_flag = 0;
                                if (drive[n].tracks == 77)
                                        mem[SIDES] = 0x80;
                                else
                                        mem[SIDES] = 0;
                                mem[FDSTAT] = ER_NON;
                                break;
                        } case 0xE87E: /* WRDDAM */ {
                                int n = mem[CURDRV];
                                printf("\r\nFloppy error: we do not support WRDDAM\n");
                                c_flag = 1;
                                if (drive[n].tracks == 77)
                                        mem[SIDES] = 0x80;
                                else
                                        mem[SIDES] = 0;
                                mem[FDSTAT] = ER_WRT;
                                break;
                        } case 0xE884: /* WRITSC */ {
                                if (trace_disk) printf("WRITSC\n");
                        } case 0xE881: /* WRVERF */ {
                                int x;
                                int n = mem[CURDRV];
                                int first = (mem[STRSCT] << 8) + mem[STRSCT + 1];
                                int num = (mem[NUMSCT] << 8) + mem[NUMSCT + 1];
                                int addr = (mem[CURADR] << 8) + mem[CURADR + 1];
                                int last = mem[LSCTLN];
                                if (trace_disk) printf("WRVERF: drive=%d, first=%d, number=%d, addr=%x, size of last=%d\n", n, first, num,
                                       addr, last);
                                if (check_drive(n))
                                        break;
                                for(x=0; x != num; ++x) {
                                        if (check_sect(n, first + x))
                                                goto oops;
                                        putsect(n, addr + 128 * x, first + x, 128);
                                }
                                if (drive[n].tracks == 77)
                                        mem[SIDES] = 0x80;
                                else
                                        mem[SIDES] = 0;
                                mem[FDSTAT] = ER_NON;
                                c_flag = 0;
                                break;
                        } case 0xE887: /* CLOCK */ {
                                printf("Floppy: Someone called CLOCK?\n");
                                c_flag = 0;
                                break;
                        } case 0xEBC0: /* LPINIT */ {
                                if (trace_disk) printf("LPINIT\n");
                                c_flag = 0;
                                break;
                        } case 0xEBCC: /* LIST */ {
                                if (trace_disk) printf("LIST\n");
                                term_out(acca);
                                /* putchar(acca); fflush(stdout); */
                                c_flag = 0;
                                break;
                        } case 0xEBE4: /* LDATA */ {
                                if (trace_disk)printf("LDATA\n");
                                while (mem[ix] != 4) {
                                        term_out(mem[ix]);
                                        /* putchar(mem[ix]); */
                                        ++ix;
                                }
                                term_out('\r');
                                term_out('\n');
                                /* printf("\n"); */
                                c_flag = 0;
                                break;
                        } case 0xEBF2: /* LDATA1 */ {
                                if (trace_disk) printf("LDATA1\n");
                                while (mem[ix] != 4) {
                                        /* putchar(mem[ix]); */
                                        term_out(mem[ix]);
                                        ++ix;
                                }
                                /* fflush(stdout); */
                                c_flag = 0;
                                break;
                        } default: {
                                pc = addr;
                                return;
                        }
                }
                simulated(addr);
                addr = pull2();
                jump(addr);
        }
}
Beispiel #27
0
/*
 * Describe an item up for sale.  "tgp" is a union containing
 * the details of the generic item.
 * Return 1 on success, 0 on error
 */
int
trade_desc(struct empobj *tgp)
{
    i_type it;
    struct sctstr sect;
    struct nukstr *np;
    struct shpstr *sp;
    struct plnstr *pp;
    struct lndstr *lp;
    struct nstr_item ni;
    struct plnstr plane;
    struct lndstr land;
    struct nukstr nuke;

    switch (tgp->ef_type) {
    case EF_NUKE:
	np = (struct nukstr *)tgp;
	pr("(%3d)  tech %d %d%% %s #%d",
	   np->nuk_own, np->nuk_tech, np->nuk_effic,
	   nchr[(int)np->nuk_type].n_name, np->nuk_uid);
	break;
    case EF_SHIP:
	sp = (struct shpstr *)tgp;
	pr("(%3d)  tech %d %d%% %s [",
	   sp->shp_own, sp->shp_tech, sp->shp_effic, prship(sp));

	for (it = I_NONE + 1; it <= I_MAX; ++it) {
	    if (sp->shp_item[it])
		pr("%c:%d ", ichr[it].i_mnem, sp->shp_item[it]);
	}
	pr("] #%d", sp->shp_uid);
	snxtitem_cargo(&ni, EF_PLANE, EF_SHIP, sp->shp_uid);
	while (nxtitem(&ni, &plane)) {
	    pr("\n\t\t\t\t    tech %3d %3d%% %s #%d",
	       plane.pln_tech,
	       plane.pln_effic,
	       plchr[(int)plane.pln_type].pl_name, plane.pln_uid);
	    if (getnuke(nuk_on_plane(&plane), &nuke))
		pr("(%s)", nchr[nuke.nuk_type].n_name);
	}
	snxtitem_cargo(&ni, EF_LAND, EF_SHIP, sp->shp_uid);
	while (nxtitem(&ni, &land)) {
	    pr("\n\t\t\t\t    tech %3d %3d%% %s #%d",
	       land.lnd_tech,
	       land.lnd_effic,
	       lchr[(int)land.lnd_type].l_name, land.lnd_uid);
	    if (pln_first_on_land(&land) >= 0) {
		snxtitem_cargo(&ni, EF_PLANE, EF_LAND, land.lnd_uid);
		while (nxtitem(&ni, &plane)) {
		    pr("\n\t\t\t\t    tech %3d %3d%% %s #%d",
		       plane.pln_tech,
		       plane.pln_effic,
		       plchr[(int)plane.pln_type].pl_name,
		       plane.pln_uid);
		    if (getnuke(nuk_on_plane(&plane), &nuke))
			pr("(%s)", nchr[nuke.nuk_type].n_name);
		}
	    }
	}
	getsect(sp->shp_x, sp->shp_y, &sect);
	if (sect.sct_type != SCT_WATER)
	    pr(" in a %s %s",
	       cname(sect.sct_own), dchr[sect.sct_type].d_name);
	else
	    pr(" at sea");
	break;
    case EF_LAND:
	lp = (struct lndstr *)tgp;
	pr("(%3d)  tech %d %d%% %s [",
	   lp->lnd_own,
	   lp->lnd_tech, lp->lnd_effic, lchr[(int)lp->lnd_type].l_name);
	for (it = I_NONE + 1; it <= I_MAX; ++it) {
	    if (lp->lnd_item[it])
		pr("%c:%d ", ichr[it].i_mnem, lp->lnd_item[it]);
	}
	pr("] #%d", lp->lnd_uid);
	break;
    case EF_PLANE:
	pp = (struct plnstr *)tgp;
	pr("(%3d)  tech %d %d%% %s #%d",
	   pp->pln_own,
	   pp->pln_tech,
	   pp->pln_effic,
	   plchr[(int)pp->pln_type].pl_name, pp->pln_uid);
	if (getnuke(nuk_on_plane(pp), &nuke))
	    pr("(%s)", nchr[nuke.nuk_type].n_name);
	break;
    default:
	pr("flaky unit type %d", tgp->uid);
	break;
    }
    return 1;
}
Beispiel #28
0
int
work(void)
{
    int nunits;
    struct nstr_item ni;
    struct sctstr sect;
    struct lndstr land;
    int work_amt, eff_amt, w;
    char *p;
    char buf[1024];
    double cost;
    struct natstr *natp = getnatp(player->cnum);

    if (!snxtitem(&ni, EF_LAND, player->argp[1], NULL))
	return RET_SYN;
    p = getstarg(player->argp[2], "Amount: ", buf);
    if (!p || !*p)
	return RET_SYN;
    work_amt = atoi(p);
    if ((work_amt < 0) || (work_amt > land_mob_max)) {
	pr("Mobility used must be from 0 to %d\n", land_mob_max);
	return RET_FAIL;
    }
    nunits = 0;
    while (nxtitem(&ni, &land)) {
	if (!player->owner || land.lnd_own == 0)
	    continue;
	if (!(lchr[(int)land.lnd_type].l_flags & L_ENGINEER))
	    continue;
	if (land.lnd_mobil <= 0) {
	    pr("%s has no mobility!\n", prland(&land));
	    continue;
	}
	getsect(land.lnd_x, land.lnd_y, &sect);
	if (sect.sct_effic >= 100 && sect.sct_type == sect.sct_newtype) {
	    pr("Nothing to do for %s in %s\n",
	       prland(&land), xyas(sect.sct_x, sect.sct_y, player->cnum));
	    continue;
	}
	eff_amt = MIN(land.lnd_mobil, work_amt);
	w = (eff_amt * land.lnd_effic) / 600;
	if (w < 1) {
	    pr("%s doesn't work enough to change efficiency (try increasing amount)\n",
	       prland(&land));
	    continue;
	}
	cost = 0.0;
	w = buildeff(&sect, w, &cost);
	if (w == 0) {
	    pr("%s can't change efficiency in %s\n",
	       prland(&land), xyas(land.lnd_x, land.lnd_y, player->cnum));
	    continue;
	}
	if (player->dolcost + cost > natp->nat_money) {
	    pr("You can't afford to work that much in %s!\n",
	       xyas(land.lnd_x, land.lnd_y, player->cnum));
	    break;
	}
	player->dolcost += cost;
	land.lnd_mission = 0;
	land.lnd_mobil -= roundavg(w * 600.0 / land.lnd_effic);
	nunits++;
	pr("%s %s efficiency at %s to %d\n",
	   prland(&land),
	   sect.sct_type == sect.sct_newtype ? "raised" : "lowered",
	   xyas(land.lnd_x, land.lnd_y, player->cnum),
	   sect.sct_effic);
	putland(land.lnd_uid, &land);
	putsect(&sect);
    }
    if (nunits == 0) {
	if (player->argp[1])
	    pr("%s: No unit(s)\n", player->argp[1]);
	else
	    pr("%s: No unit(s)\n", "");
	return RET_FAIL;
    } else
	pr("%d unit%s\n", nunits, splur(nunits));
    return RET_OK;
}
Beispiel #29
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 #30
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");
}