void msl_sel(struct emp_qelem *list, coord x, coord y, natid victim, int wantflags, int nowantflags, int mission) { struct plchrstr *pcp; struct plnstr plane; struct plist *irv; struct nstr_item ni; emp_initque(list); snxtitem_all(&ni, EF_PLANE); while (nxtitem(&ni, &plane)) { if (!plane.pln_own) continue; pcp = &plchr[(int)plane.pln_type]; if (!(pcp->pl_flags & P_M)) continue; if (wantflags && (pcp->pl_flags & wantflags) != wantflags) continue; if (nowantflags && pcp->pl_flags & nowantflags) continue; if (mission && plane.pln_mission != mission) continue; if (mission && plane.pln_radius < mapdist(x, y, plane.pln_opx, plane.pln_opy)) continue; if (relations_with(plane.pln_own, victim) >= NEUTRAL) continue; /* missiles go one way, so we can use all the range */ if (plane.pln_range < mapdist(x, y, plane.pln_x, plane.pln_y)) continue; if (plane.pln_mobil <= 0) continue; if (plane.pln_effic < 100) continue; if (opt_MARKET) { if (ontradingblock(EF_PLANE, &plane)) continue; } if (!pln_airbase_ok(&plane, 1, 0)) continue; /* got a valid interceptor */ irv = malloc(sizeof(*irv)); irv->load = 0; irv->pstage = PLG_HEALTHY; irv->pcp = &plchr[(int)plane.pln_type]; irv->plane = plane; emp_insque(&irv->queue, list); } }
static int fire_torp(struct shpstr *sp, struct shpstr *targ, int ntargets) { int range, erange, dam; if ((mchr[targ->shp_type].m_flags & M_SUB) && (mchr[sp->shp_type].m_flags & M_SUBT) == 0) return 0; /* need sub-torp to torpedo a sub */ erange = roundrange(torprange(sp)); range = mapdist(sp->shp_x, sp->shp_y, targ->shp_x, targ->shp_y); if (range > erange) return 0; if (!line_of_sight(NULL, sp->shp_x, sp->shp_y, targ->shp_x, targ->shp_y)) return 0; dam = shp_torp(sp, 1); putship(sp->shp_uid, sp); if (dam < 0) return 0; pr("Captain! Torpedoes sighted!\n"); if (chance(shp_torp_hitchance(sp, range))) { pr("BOOM!...\n"); if (!(mchr[targ->shp_type].m_flags & M_SUB)) { if (mchr[sp->shp_type].m_flags & M_SUB) nreport(targ->shp_own, N_TORP_SHIP, 0, 1); else nreport(targ->shp_own, N_SHIP_TORP, sp->shp_own, 1); } if (sp->shp_own != 0) wu(0, sp->shp_own, "%s @ %s torpedoed %s\n", prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own), prsub(targ)); if (ntargets > 2) dam /= ntargets / 2; shipdamage(targ, dam); putship(targ->shp_uid, targ); } else { pr("Missed!\n"); if (sp->shp_own != 0) wu(0, sp->shp_own, "%s missed %s with a torpedo at %s\n", prship(sp), prsub(targ), xyas(sp->shp_x, sp->shp_y, sp->shp_own)); } return 1; }
/* How isolated is capital j? */ static int iso(int j, int newx, int newy) { int i, md, d = WORLD_X + WORLD_Y; for (i = 0; i < nc; ++i) { if (i == j) continue; md = mapdist(capx[i], capy[i], newx, newy); if (md < d) d = md; } return d; }
static void fire_dchrg(struct shpstr *sp, struct shpstr *targ, int ntargets) { int range, erange, dam; erange = roundrange(shp_fire_range(sp)); range = mapdist(sp->shp_x, sp->shp_y, targ->shp_x, targ->shp_y); if (range > erange) return; if ((mchr[(int)targ->shp_type].m_flags & M_SUB) == 0) { /* Return fire to a torpedo boat */ if (mchr[sp->shp_type].m_flags & M_SUB) return; /* sub deck gun can't return fire */ dam = shp_fire(sp); putship(sp->shp_uid, sp); if (dam < 0) return; if (ntargets > 2) dam /= ntargets / 2; pr_beep(); pr("Kaboom!!! Incoming shells!\n"); if (sp->shp_own != 0) wu(0, sp->shp_own, "%s fired at %s\n", prship(sp), prship(targ)); pr_beep(); pr("BLAM! %d damage!\n", dam); } else { /* Return fire to a submarine */ dam = shp_dchrg(sp); putship(sp->shp_uid, sp); if (dam < 0) return; if (ntargets > 2) dam /= ntargets / 2; pr("\nCAPTAIN! !!Depth charges!!...\n"); if (sp->shp_own != 0) wu(0, sp->shp_own, "%s depth charged %s\n", prship(sp), prsub(targ)); pr("click...WHAM! %d damage!\n", dam); } shipdamage(targ, dam); putship(targ->shp_uid, targ); }
int nxtitem(struct nstr_item *np, void *ptr) { struct empobj *gp; int selected; if (np->sel == NS_UNDEF) return 0; gp = (struct empobj *)ptr; do { if (np->sel == NS_LIST) { np->index++; if (np->index >= np->size) return 0; np->cur = np->list[np->index]; } else if (np->sel == NS_CARGO) { if (np->next < 0) return 0; np->cur = np->next; np->next = unit_cargo_next(np->type, np->next); } else { np->cur++; } if (!ef_read(np->type, np->cur, ptr)) return 0; selected = 1; switch (np->sel) { case NS_LIST: case NS_CARGO: case NS_ALL: break; case NS_DIST: if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_XY))) return 0; if (!xyinrange(gp->x, gp->y, &np->range)) { selected = 0; break; } np->curdist = mapdist(gp->x, gp->y, np->cx, np->cy); if (np->curdist > np->dist) selected = 0; break; case NS_AREA: if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_XY))) return 0; if (!xyinrange(gp->x, gp->y, &np->range)) selected = 0; break; case NS_XY: if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_XY))) return 0; if (xnorm(gp->x) != np->cx || ynorm(gp->y) != np->cy) selected = 0; break; case NS_GROUP: if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_GROUP))) return 0; if (np->group != gp->group) selected = 0; break; default: CANT_REACH(); return 0; } if (selected && np->ncond) { /* nstr_exec is expensive, so we do it last */ if (!nstr_exec(np->cond, np->ncond, ptr)) selected = 0; } } while (!selected); return 1; }
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"); }
int payo(void) { struct sctstr sect; int nships; struct nstr_item ni; struct shpstr ship; struct mchrstr *mp; int dist; float cash = 0.0; if (!snxtitem(&ni, EF_SHIP, player->argp[1], NULL)) return RET_SYN; nships = 0; while (nxtitem(&ni, &ship)) { if (!player->owner || ship.shp_own == 0) continue; mp = &mchr[(int)ship.shp_type]; if (!(mp->m_flags & M_TRADE)) continue; if (nships++ == 0) { if (player->god) pr("own "); pr("shp# ship type orig x,y x,y dist $$\n"); } if (player->god) pr("%3d ", ship.shp_own); pr("%4d ", ni.cur); pr("%-16.16s ", mchr[(int)ship.shp_type].m_name); if (ship.shp_own != ship.shp_orig_own && !player->god) { /* Don't disclose construction site to pirates! */ pr(" ? "); prxy("%4d,%-4d ", ship.shp_x, ship.shp_y); pr(" ? $ ?\n"); continue; } prxy("%4d,%-4d ", ship.shp_orig_x, ship.shp_orig_y); prxy("%4d,%-4d ", ship.shp_x, ship.shp_y); getsect(ship.shp_x, ship.shp_y, §); dist = mapdist(ship.shp_x, ship.shp_y, ship.shp_orig_x, ship.shp_orig_y); pr("%4d ", dist); if (dist < trade_1_dist) cash = 0; else if (dist < trade_2_dist) cash = 1.0 + trade_1 * dist; else if (dist < trade_3_dist) cash = 1.0 + trade_2 * dist; else cash = 1.0 + trade_3 * dist; cash *= mp->m_cost; cash *= ship.shp_effic / 100.0; if (sect.sct_own && (sect.sct_own != ship.shp_own)) cash *= (1.0 + trade_ally_bonus); pr("$%6.2f\n", cash); } if (nships == 0) { if (player->argp[1]) pr("%s: No ship(s)\n", player->argp[1]); else pr("%s: No ship(s)\n", ""); return RET_FAIL; } else pr("%d ship%s\n", nships, splur(nships)); return RET_OK; }
int torp(void) { natid vshipown; int range; int dam; int subno; int victno; int erange; double hitchance; struct shpstr vship; struct shpstr sub; struct mchrstr *sub_mcp; char *ptr; struct nstr_item nbst; char buf[1024]; int ntorping = 0; char prompt[128]; if (!snxtitem(&nbst, EF_SHIP, player->argp[1], "From ship(s)? ")) return RET_SYN; while (nxtitem(&nbst, &sub)) { if (sub.shp_own != player->cnum) continue; if ((mchr[(int)sub.shp_type].m_flags & M_TORP) == 0) continue; if (sub.shp_item[I_GUN] == 0 || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS) continue; if (sub.shp_item[I_MILIT] < 1) continue; if (sub.shp_effic < 60) continue; if (sub.shp_mobil <= 0) continue; ntorping++; } pr("%d ships are eligible to torpedo\n", ntorping); snxtitem_rewind(&nbst); while (nxtitem(&nbst, &sub)) { if (!sub.shp_own) continue; if (sub.shp_own != player->cnum) { continue; } sub_mcp = &mchr[sub.shp_type]; if (!(sub_mcp->m_flags & M_TORP)) { pr("Ship # %d: A %s can't fire torpedoes!\n", sub.shp_uid, sub_mcp->m_name); continue; } if (sub.shp_item[I_GUN] == 0 || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS) { pr("Ship #%d has insufficient armament\n", sub.shp_uid); continue; } if (sub.shp_item[I_MILIT] < 1) { pr("Ship #%d has insufficient crew\n", sub.shp_uid); continue; } if (sub.shp_effic < 60) { pr("Ship #%d torpedo tubes inoperative.\n", sub.shp_uid); continue; } if (sub.shp_mobil <= 0) { pr("Ship #%d has insufficient mobility\n", sub.shp_uid); continue; } subno = sub.shp_uid; sprintf(prompt, "Ship %d, target? ", sub.shp_uid); if (!(ptr = getstarg(player->argp[2], prompt, buf))) return RET_SYN; if (!check_ship_ok(&sub)) return RET_FAIL; if ((victno = atoi(ptr)) < 0) return RET_SYN; if (!getship(victno, &vship)) return RET_FAIL; if (!vship.shp_own) return RET_FAIL; vshipown = vship.shp_own; if (victno == subno) { pr("Shooting yourself, eh? How strange...\n"); continue; } if (mchr[(int)vship.shp_type].m_flags & M_SUB) { if (!(sub_mcp->m_flags & M_SUBT)) { pr("You can't torpedo a submarine!\n"); continue; } } dam = shp_torp(&sub, 1); sub.shp_mission = 0; putship(sub.shp_uid, &sub); if (CANT_HAPPEN(dam < 0)) { pr("Ship #%d has insufficient armament\n", sub.shp_uid); continue; } if (!(sub_mcp->m_flags & M_SUB)) { pr("Starting our attack run...\n"); anti_torp(sub.shp_uid, ntorping, vshipown); } getship(sub.shp_uid, &sub); if (sub.shp_own == 0) continue; erange = roundrange(torprange(&sub)); pr("Effective torpedo range is %d.0\n", erange); pr("Whooosh... "); getship(victno, &vship); vshipown = vship.shp_own; range = mapdist(sub.shp_x, sub.shp_y, vship.shp_x, vship.shp_y); hitchance = shp_torp_hitchance(&sub, range); if (range <= erange) { pr("Hitchance = %.0f%%\n", hitchance * 100); } if (range > erange) pr("Out of range\n"); else if (!line_of_sight(NULL, sub.shp_x, sub.shp_y, vship.shp_x, vship.shp_y)) { pr("BOOM!... Torpedo slams into land before reaching target.\n"); /* We only tell the victim if we were within range. */ if (vshipown != 0 && vshipown != player->cnum) wu(0, vshipown, "Torpedo sighted @ %s by %s\n", xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship)); } else if (chance(hitchance)) { pr("BOOM!...\n"); if (vshipown != 0 && vshipown != player->cnum) wu(0, vshipown, "%s in %s torpedoed %s for %d damage.\n", sub_mcp->m_flags & M_SUB ? "sub" : prship(&sub), xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship), dam); pr("Torpedo hit %s for %d damage.\n", prsub(&vship), dam); if (!(mchr[vship.shp_type].m_flags & M_SUB)) { if (mchr[sub.shp_type].m_flags & M_SUB) nreport(vshipown, N_TORP_SHIP, 0, 1); else nreport(vshipown, N_SHIP_TORP, player->cnum, 1); } shipdamage(&vship, dam); if (vship.shp_effic < SHIP_MINEFF) pr("%s sunk!\n", prsub(&vship)); if (vship.shp_rflags & RET_TORPED) retreat_ship(&vship, vshipown, 't'); putship(vship.shp_uid, &vship); } else { pr("Missed\n"); if (vshipown != 0 && vshipown != player->cnum) wu(0, vshipown, "Torpedo sighted @ %s by %s\n", xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship)); } if (sub_mcp->m_flags & M_SUB) anti_torp(sub.shp_uid, ntorping, vshipown); } return RET_OK; }
void pln_sel(struct nstr_item *ni, struct emp_qelem *list, struct sctstr *ap, int ap_to_target, int rangemult, int wantflags, int nowantflags) { struct plnstr plane; int range; struct plchrstr *pcp; struct plist *plp; emp_initque(list); while (nxtitem(ni, &plane)) { /* * It would be nice to let deities fly foreign planes, but * much of the code assumes that only the plane's owner can * fly it. */ if (!plane.pln_own || plane.pln_own != player->cnum) continue; if (plane.pln_mobil <= 0) continue; if (plane.pln_effic < 40) { pr("%s not efficient enough (must be 40%%)\n", prplane(&plane)); continue; } if (!pln_capable(&plane, wantflags, nowantflags)) continue; if (opt_MARKET) { if (ontradingblock(EF_PLANE, &plane)) { pr("plane #%d inelligible - it's for sale.\n", plane.pln_uid); continue; } } range = mapdist(plane.pln_x, plane.pln_y, ap->sct_x, ap->sct_y); if (range > 4) { pr("%s too far from assembly point\n", prplane(&plane)); continue; } range += ap_to_target; range *= rangemult; pcp = &plchr[(int)plane.pln_type]; if (plane.pln_range < range) { pr("%s out of range (%d:%d)\n", prplane(&plane), plane.pln_range, range); continue; } if (!pln_airbase_ok(&plane, rangemult != 2, 1)) continue; pr("%s standing by\n", prplane(&plane)); plane.pln_mission = 0; putplane(plane.pln_uid, &plane); plp = malloc(sizeof(struct plist)); plp->load = 0; plp->pstage = PLG_HEALTHY; plp->pcp = pcp; plp->plane = plane; emp_insque(&plp->queue, list); } }
static void look_land(struct lndstr *lookland) { struct plnstr *pp; struct lndstr *lp; double drange; int range; int vrange; int i; int dist; drange = techfact(lookland->lnd_tech, lchr[lookland->lnd_type].l_spy); drange *= lookland->lnd_effic / 100.0; range = ldround(drange, 1); if (range == 0) return; for (i = 0; NULL != (lp = getlandp(i)); i++) { if (lp->lnd_own == player->cnum || lp->lnd_own == 0) continue; if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) continue; /* Don't always see spies */ if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { /* If it's on a ship or unit, assume it's hidden enough not to be seen */ if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) continue; if (!(chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic)))) continue; } vrange = ldround((lnd_vis(lp) * range) / 20.0, 1); dist = mapdist(lp->lnd_x, lp->lnd_y, lookland->lnd_x, lookland->lnd_y); if (dist > vrange) continue; pr("%s %s (approx %d mil) @ %s\n", prnatid(lp->lnd_own), prland(lp), roundintby(lp->lnd_item[I_MILIT], 20), xyas(lp->lnd_x, lp->lnd_y, player->cnum)); if (opt_HIDDEN) setcont(player->cnum, lp->lnd_own, FOUND_LOOK); } for (i = 0; NULL != (pp = getplanep(i)); i++) { if (pp->pln_own == player->cnum || pp->pln_own == 0) continue; if (pp->pln_ship >= 0 || pp->pln_land >= 0) continue; if (pp->pln_flags & PLN_LAUNCHED) continue; vrange = ldround((10 * range) / 20.0, 1); dist = mapdist(pp->pln_x, pp->pln_y, lookland->lnd_x, lookland->lnd_y); if (dist > vrange) continue; pr("%s %s @ %s\n", prnatid(pp->pln_own), prplane(pp), xyas(pp->pln_x, pp->pln_y, player->cnum)); if (opt_HIDDEN) setcont(player->cnum, pp->pln_own, FOUND_LOOK); } }
static void look_ship(struct shpstr *lookship) { struct shpstr *sp; struct mchrstr *smcp; struct mchrstr *tmcp; struct sctstr sect; int range; int vrange; int i; int dist; range = (int)techfact(lookship->shp_tech, mchr[(int)lookship->shp_type].m_vrnge); range = range * (lookship->shp_effic / 100.0); smcp = &mchr[(int)lookship->shp_type]; if (smcp->m_flags & M_SUB) range = MIN(range, 1); for (i = 0; NULL != (sp = getshipp(i)); i++) { if (sp->shp_own == player->cnum || sp->shp_own == 0) continue; dist = mapdist(sp->shp_x, sp->shp_y, lookship->shp_x, lookship->shp_y); if (dist > ship_max_interdiction_range) continue; tmcp = &mchr[(int)sp->shp_type]; if (smcp->m_flags & M_SUB) vrange = (int)(shp_visib(sp) * range / 30.0); else vrange = (int)(shp_visib(sp) * range / 20.0); getsect(sp->shp_x, sp->shp_y, §); if (sect.sct_type != SCT_WATER) vrange = MAX(1, vrange); if (dist > vrange) continue; if (smcp->m_flags & M_SUB) { if (tmcp->m_flags & M_SONAR && dist < 2) { if (sp->shp_own != 0) wu(0, sp->shp_own, "%s detected surfacing noises in %s.\n", prship(sp), xyas(lookship->shp_x, lookship->shp_y, sp->shp_own)); } if (dist == 0 && (tmcp->m_flags & M_SUB) == 0) if (sp->shp_own != 0) wu(0, sp->shp_own, "Periscope spotted in %s by %s\n", xyas(lookship->shp_x, lookship->shp_y, sp->shp_own), prship(sp)); } /* subs at sea only seen by sonar */ if (tmcp->m_flags & M_SUB && sect.sct_type == SCT_WATER) continue; pr("%s %s @ %s\n", prnatid(sp->shp_own), prship(sp), xyas(sp->shp_x, sp->shp_y, player->cnum)); if (opt_HIDDEN) setcont(player->cnum, sp->shp_own, FOUND_LOOK); } }