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, §); if (sect.sct_type == SCT_WATER) continue; look_at_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; }
struct option *getoptions(const char *sect_name) { struct sect *s = getsect(sect_name, NULL); if (s) return s->opts; return NULL; }
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, §); 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); } }
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, §); 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(§); } }
/* * 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; }
/* * 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; }
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, §); 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; }
int msl_abm_intercept(struct plnstr *msl, coord x, coord y, int sublaunch) { struct sctstr sect; struct emp_qelem irvlist; getsect(x, y, §); msl_sel(&irvlist, x, y, msl->pln_own, P_N, P_O, 0); return msl_intercept(msl, §, sublaunch, &irvlist, "warhead", "abm", sublaunch ? N_NUKE_SSTOP : N_NUKE_STOP); }
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; }
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); }
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, §); 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(§); putsect(§); } } }
int msl_asat_intercept(struct plnstr *msl, coord x, coord y) { struct sctstr sect; struct emp_qelem irvlist; getsect(x, y, §); 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, §, 0, &irvlist, "satellite", "a-sat missile", N_SAT_KILL); }
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], §); if (!sect.sct_coastal) { sect.sct_coastal = 1; putsect(§); } } return 1; }
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, §); 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); }
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, §); 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; } } }
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], §); c = update_coastal_flag(sect.sct_x, sect.sct_y, x, y); if (!sect.sct_coastal != !c) { sect.sct_coastal = c; putsect(§); } } return update_coastal_flag(x, y, x, y); }
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], §); 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; }
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, §); 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(§); }
/*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, §)) { /* 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, §)) 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; }
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, §); if (sect.sct_type == SCT_BSPAN && !bridge_support_at(§, DIR_BACK(i))) { knockdown(§); putsect(§); } } }
int check_lmines(coord x, coord y, double weight) { struct sctstr sect; int dam = 0; getsect(x, y, §); if (SCT_LANDMINES(§) > 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(§); pr("%d damage sustained.\n", dam); } return dam; }
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, §); 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; }
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 = §_hd; } while (o = s->opts) { s->opts = o->next; free(o); } if (sect_name[0]) free(s); else s->opts = NULL; }
/* * 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, §); 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; }
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, §) < 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); }
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); } }
/* * 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, §); 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; }
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, §); 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(§, 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(§); } 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; }
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, §); 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, §)) { 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, §)) { 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; }
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, §); 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"); }