Пример #1
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);
}
Пример #2
0
int
unit_move(struct emp_qelem *list)
{
    struct empobj *leader = get_leader(list);
    int leader_uid = leader->uid;
    int type = leader->ef_type;
    int moved, suppress_map, dir, stopping;
    char *cp;
    char path[1024];

    unit_rad_map_set(list);

    pr("%s is %s\n",
	type == EF_SHIP ? "Flagship" : "Leader",
	unit_nameof(leader));

    cp = "";
    if (player->argp[2]) {
	strcpy(path, player->argp[2]);
	cp = unit_move_route(leader, path, sizeof(path));
	if (!cp)
	    cp = "";
    }

    moved = suppress_map = 0;
    for (;;) {
	/*
	 * Invariants:
	 * - shp_may_nav() true for all ships
	 * - lnd_may_mar() true for all land units
	 * - leader is up-to-date
	 * Implies all are in the same sector
	 */
	if (!*cp) {
	    cp = unit_move_getpath(list, suppress_map, path);
	    if (!cp) {
		if (type == EF_SHIP) {
		    shp_nav_stay_behind(list, player->cnum);
		    shp_nav_put(list, player->cnum);
		} else {
		    lnd_mar_stay_behind(list, player->cnum);
		    lnd_mar_put(list, player->cnum);
		}
		return RET_FAIL;
	    }
	    cp = unit_move_route(leader, path, sizeof(path));
	    if (!cp || !*cp)
		cp = "h";
	    suppress_map = 0;
	} else if ((dir = chkdir(*cp, DIR_STOP, DIR_LAST)) >= 0) {
	    cp++;
	    if (type == EF_SHIP)
		stopping = shp_nav_dir(list, dir, player->cnum)
		    || shp_nav_gauntlet(list, 1, player->cnum);
	    else {
		if (!moved && !lnd_abandon_askyn(list)) {
		    lnd_mar_put(list, player->cnum);
		    return RET_FAIL;
		}
		stopping = lnd_mar_dir(list, dir, player->cnum)
		    || lnd_mar_gauntlet(list, 1, player->cnum);
	    }
	    if (dir == DIR_STOP) {
		CANT_HAPPEN(!QEMPTY(list));
		return RET_OK;
	    }
	    moved = 1;
	    if (stopping)
		cp = "";
	} else {
	    cp = unit_move_non_dir(list, cp, &suppress_map);
	    if (!cp) {
		direrr("`%c' to stop", ", `%c' to view", NULL);
		pr(", `i' to list %s, `f' to change %s,\n",
		   type == EF_SHIP ? "ships" : "units",
		   type == EF_SHIP ? "flagship" : "leader");
		pr("`r' to radar, %s`l' to look, `M' to map, `B' to bmap,\n",
		   type == EF_SHIP ? "`s' to sonar, " : "");
		pr("`d' to drop mines, and `m' to minesweep\n");
		cp = "";
	    }
	}

	if (type == EF_SHIP)
	    shp_nav_stay_behind(list, player->cnum);
	else
	    lnd_mar_stay_behind(list, player->cnum);

	if (QEMPTY(list)) {
	    pr("No %s left\n", type == EF_SHIP ? "ships" : "lands");
	    return RET_OK;
	}

	leader = get_leader(list);
	if (leader->uid != leader_uid) {
	    leader_uid = leader->uid;
	    pr("Changing %s to %s\n",
	       leader->ef_type == EF_SHIP ? "flagship" : "leader",
	       unit_nameof(leader));
	}
	unit_rad_map_set(list);
    }
}