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; }
/* Setup call to metamethod to be run by Assembler VM. */ static TValue *mmcall(lua_State *L, ASMFunction cont, cTValue *mo, cTValue *a, cTValue *b) { /* ** |-- framesize -> top top+1 top+2 top+3 ** before: [func slots ...] ** mm setup: [func slots ...] [cont|?] [mo|tmtype] [a] [b] ** in asm: [func slots ...] [cont|PC] [mo|delta] [a] [b] ** ^-- func base ^-- mm base ** after mm: [func slots ...] [result] ** ^-- copy to base[PC_RA] --/ for lj_cont_ra ** istruecond + branch for lj_cont_cond* ** ignore for lj_cont_nop ** next PC: [func slots ...] */ TValue *top = L->top; if (curr_funcisL(L)) top = curr_topL(L); setcont(top++, cont); /* Assembler VM stores PC in upper word or FR2. */ if (LJ_FR2) setnilV(top++); copyTV(L, top++, mo); /* Store metamethod and two arguments. */ if (LJ_FR2) setnilV(top++); copyTV(L, top, a); copyTV(L, top+1, b); return top; /* Return new base. */ }
/* Helper for equality comparisons. __eq metamethod. */ TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne) { /* Field metatable must be at same offset for GCtab and GCudata! */ cTValue *mo = lj_meta_fast(L, tabref(o1->gch.metatable), MM_eq); if (mo) { TValue *top; uint32_t it; if (tabref(o1->gch.metatable) != tabref(o2->gch.metatable)) { cTValue *mo2 = lj_meta_fast(L, tabref(o2->gch.metatable), MM_eq); if (mo2 == NULL || !lj_obj_equal(mo, mo2)) return (TValue *)(intptr_t)ne; } top = curr_top(L); setcont(top, ne ? lj_cont_condf : lj_cont_condt); copyTV(L, top+1, mo); it = ~(uint32_t)o1->gch.gct; setgcV(L, top+2, o1, it); setgcV(L, top+3, o2, it); return top+2; /* Trigger metamethod call. */ } return (TValue *)(intptr_t)ne; }
static int showsat(struct sky **skypp, int x, int y) { struct sky *skyp; struct sky *todelete = NULL; struct sky **prev; int nsat = 0; prev = NULL; skyp = *skypp; prev = skypp; do { /* we delete it, we free it. */ if (todelete) { free(todelete); todelete = NULL; } if (skyp->s_sat.pln_x != x || skyp->s_sat.pln_y != y) { prev = &(*prev)->s_next; continue; } pr(" %12.12s (#%3d) %s @ %s\n", cname(skyp->s_sat.pln_own), skyp->s_sat.pln_own, prplane(&skyp->s_sat), xyas(x, y, player->cnum)); if (opt_HIDDEN) { /* FOUND_COAST should probably be changed to FOUND_SKY -KHS */ setcont(player->cnum, skyp->s_sat.pln_own, FOUND_COAST); } *prev = skyp->s_next; todelete = skyp; nsat++; } while (NULL != (skyp = skyp->s_next)); /* check that last one! */ if (todelete) free(todelete); return nsat; }
static int showship(struct coast **cpp, int x, int y) { struct coast *cp; struct coast *todelete = NULL; struct coast **prev; int nship = 0; prev = NULL; cp = *cpp; prev = cpp; do { /* we delete it, we free it. */ if (todelete) { free(todelete); todelete = NULL; } if (cp->c_shp.shp_x != x || cp->c_shp.shp_y != y) { prev = &(*prev)->c_next; continue; } pr(" %12.12s (#%3d) %s @ %s\n", cname(cp->c_shp.shp_own), cp->c_shp.shp_own, prship(&cp->c_shp), xyas(x, y, player->cnum)); if (opt_HIDDEN) { setcont(player->cnum, cp->c_shp.shp_own, FOUND_COAST); } *prev = cp->c_next; todelete = cp; nship++; } while (NULL != (cp = cp->c_next)); /* check that last one! */ if (todelete) free(todelete); return nship; }
void setrel(natid us, natid them, int rel) { struct natstr *mynp = getnatp(us); struct natstr *themnp = getnatp(them); int oldrel; char *whichway; int n_up = 0; int n_down = 0; char *addendum = NULL; if (CANT_HAPPEN(rel < AT_WAR)) rel = AT_WAR; if (CANT_HAPPEN(rel > ALLIED)) rel = ALLIED; if (CANT_HAPPEN(!mynp || !themnp)) return; if (us == them) return; oldrel = relations_with(us, them); if (oldrel == rel) return; if (rel > oldrel) whichway = "upgraded"; else whichway = "downgraded"; if (rel == ALLIED) { addendum = "Congratulations!"; n_up = N_DECL_ALLY; } else if (rel == FRIENDLY) { n_up = N_UP_FRIENDLY; n_down = N_DOWN_FRIENDLY; } else if (rel == NEUTRAL) { n_up = N_UP_NEUTRAL; n_down = N_DOWN_NEUTRAL; } else if (rel == HOSTILE) { addendum = "Another cold war..."; n_up = N_UP_HOSTILE; n_down = N_DOWN_HOSTILE; } else if (rel < HOSTILE) { addendum = "Declaration made (give 'em hell)."; n_down = N_DECL_WAR; } if (addendum && us == player->cnum && !update_running) pr("%s\n", addendum); mpr(us, "Diplomatic relations with %s %s to \"%s\".\n", cname(them), whichway, relates[rel]); if (!(getrejects(us, themnp) & REJ_TELE)) mpr(them, "Country %s has %s their relations with you to \"%s\"!\n", prnat(mynp), whichway, relates[rel]); putrel(mynp, them, rel); putnat(mynp); if (!player->god) { if (oldrel == ALLIED) nreport(us, N_DIS_ALLY, them, 1); else if (oldrel < HOSTILE && rel >= HOSTILE) nreport(us, N_DIS_WAR, them, 1); if (rel > oldrel) nreport(us, n_up, them, 1); else nreport(us, n_down, them, 1); } if (opt_HIDDEN) setcont(them, us, FOUND_TELE); }
/* Helper for CAT. Coercion, iterative concat, __concat metamethod. */ TValue *lj_meta_cat(lua_State *L, TValue *top, int left) { int fromc = 0; if (left < 0) { left = -left; fromc = 1; } do { if (!(tvisstr(top) || tvisnumber(top)) || !(tvisstr(top-1) || tvisnumber(top-1))) { cTValue *mo = lj_meta_lookup(L, top-1, MM_concat); if (tvisnil(mo)) { mo = lj_meta_lookup(L, top, MM_concat); if (tvisnil(mo)) { if (tvisstr(top-1) || tvisnumber(top-1)) top++; lj_err_optype(L, top-1, LJ_ERR_OPCAT); return NULL; /* unreachable */ } } /* One of the top two elements is not a string, call __cat metamethod: ** ** before: [...][CAT stack .........................] ** top-1 top top+1 top+2 ** pick two: [...][CAT stack ...] [o1] [o2] ** setup mm: [...][CAT stack ...] [cont|?] [mo|tmtype] [o1] [o2] ** in asm: [...][CAT stack ...] [cont|PC] [mo|delta] [o1] [o2] ** ^-- func base ^-- mm base ** after mm: [...][CAT stack ...] <--push-- [result] ** next step: [...][CAT stack .............] */ copyTV(L, top+2*LJ_FR2+2, top); /* Carefully ordered stack copies! */ copyTV(L, top+2*LJ_FR2+1, top-1); copyTV(L, top+LJ_FR2, mo); setcont(top-1, lj_cont_cat); if (LJ_FR2) { setnilV(top); setnilV(top+2); top += 2; } return top+1; /* Trigger metamethod call. */ } else { /* Pick as many strings as possible from the top and concatenate them: ** ** before: [...][CAT stack ...........................] ** pick str: [...][CAT stack ...] [...... strings ......] ** concat: [...][CAT stack ...] [result] ** next step: [...][CAT stack ............] */ TValue *e, *o = top; uint64_t tlen = tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM; char *p, *buf; do { o--; tlen += tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM; } while (--left > 0 && (tvisstr(o-1) || tvisnumber(o-1))); if (tlen >= LJ_MAX_STR) lj_err_msg(L, LJ_ERR_STROV); p = buf = lj_buf_tmp(L, (MSize)tlen); for (e = top, top = o; o <= e; o++) { if (tvisstr(o)) { GCstr *s = strV(o); MSize len = s->len; p = lj_buf_wmem(p, strdata(s), len); } else if (tvisint(o)) { p = lj_strfmt_wint(p, intV(o)); } else { lua_assert(tvisnum(o)); p = lj_strfmt_wnum(p, o); } } setstrV(L, top, lj_str_new(L, buf, (size_t)(p-buf))); } } while (left >= 1); if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) { if (!fromc) L->top = curr_topL(L); lj_gc_step(L); } return NULL; }
int tele(void) { natid to; struct natstr *natp; char buf[MAXTELSIZE + 1]; /* UTF-8 */ int n; if (*player->argp[0] == 'a') { if (getele("everybody", buf) <= 0) { pr("Announcement aborted\n"); return RET_FAIL; } pr("\n"); to = 0; if (typed_wu(player->cnum, to, buf, TEL_ANNOUNCE) < 0) logerror("tele: typed_wu failed to #%d", to); } else if (*player->argp[0] == 'p') { if (getele("your Gracious Deity", buf) <= 0) { pr("Prayer aborted\n"); return RET_FAIL; } pr("\n"); if (typed_wu(player->cnum, 0, buf, TEL_NORM) < 0) logerror("tele: typed_wu failed to #0"); } else { int kk; kk = 1; do { if ((n = natarg(player->argp[kk], "for which country? ")) < 0) return RET_SYN; to = n; if (kk == 1) { if (player->argp[2]) { if (getele("multiple recipients", buf) < 0) { pr("Telegram aborted\n"); return RET_FAIL; } } else { if (getele(cname(to), buf) < 0) { pr("Telegram aborted\n"); return RET_FAIL; } } pr("\n"); } natp = getnatp(to); if (natp->nat_stat < STAT_SANCT) { pr("%s has no \"telegram privileges\".\n", cname(to)); kk++; continue; } if (!player->god && (getrejects(player->cnum, natp) & REJ_TELE)) { pr("%s is rejecting your telegrams.\n", cname(to)); return RET_SYN; } if (typed_wu(player->cnum, to, buf, TEL_NORM) < 0) { logerror("tele: typed_wu failed to #%d", n); return RET_FAIL; } if (!player->god && natp->nat_stat != STAT_GOD && player->cnum != to) nreport(player->cnum, N_SENT_TEL, to, 1); if (opt_HIDDEN) { setcont(to, player->cnum, FOUND_TELE); } kk++; } while (player->argp[kk] != NULL); } return RET_OK; }
/* Helper for CAT. Coercion, iterative concat, __concat metamethod. */ TValue *lj_meta_cat(lua_State *L, TValue *top, int left) { do { int n = 1; if (!(tvisstr(top-1) || tvisnumber(top-1)) || !tostring(L, top)) { cTValue *mo = lj_meta_lookup(L, top-1, MM_concat); if (tvisnil(mo)) { mo = lj_meta_lookup(L, top, MM_concat); if (tvisnil(mo)) { if (tvisstr(top-1) || tvisnumber(top-1)) top++; lj_err_optype(L, top-1, LJ_ERR_OPCAT); return NULL; /* unreachable */ } } /* One of the top two elements is not a string, call __cat metamethod: ** ** before: [...][CAT stack .........................] ** top-1 top top+1 top+2 ** pick two: [...][CAT stack ...] [o1] [o2] ** setup mm: [...][CAT stack ...] [cont|?] [mo|tmtype] [o1] [o2] ** in asm: [...][CAT stack ...] [cont|PC] [mo|delta] [o1] [o2] ** ^-- func base ^-- mm base ** after mm: [...][CAT stack ...] <--push-- [result] ** next step: [...][CAT stack .............] */ copyTV(L, top+2, top); /* Careful with the order of stack copies! */ copyTV(L, top+1, top-1); copyTV(L, top, mo); setcont(top-1, lj_cont_cat); return top+1; /* Trigger metamethod call. */ } else if (strV(top)->len == 0) { /* Shortcut. */ (void)tostring(L, top-1); } else { /* Pick as many strings as possible from the top and concatenate them: ** ** before: [...][CAT stack ...........................] ** pick str: [...][CAT stack ...] [...... strings ......] ** concat: [...][CAT stack ...] [result] ** next step: [...][CAT stack ............] */ MSize tlen = strV(top)->len; char *buffer; int i; for (n = 1; n <= left && tostring(L, top-n); n++) { MSize len = strV(top-n)->len; if (len >= LJ_MAX_STR - tlen) lj_err_msg(L, LJ_ERR_STROV); tlen += len; } buffer = lj_str_needbuf(L, &G(L)->tmpbuf, tlen); n--; tlen = 0; for (i = n; i >= 0; i--) { MSize len = strV(top-i)->len; memcpy(buffer + tlen, strVdata(top-i), len); tlen += len; } setstrV(L, top-n, lj_str_new(L, buffer, tlen)); } left -= n; top -= n; } while (left >= 1); lj_gc_check_fixtop(L); return NULL; }
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); } }