void bsanct(void) { int count; struct sctstr s; struct nstr_sect nstr; if (player->god) return; count = 0; snxtsct_all(&nstr); while (nxtsct(&nstr, &s)) { if (!player->owner) continue; if (s.sct_type != SCT_SANCT) continue; pr("%s is no longer a sanctuary.\n", xyas(s.sct_x, s.sct_y, player->cnum)); if (s.sct_newtype == SCT_SANCT) s.sct_newtype = SCT_CAPIT; s.sct_type = s.sct_newtype; game_tick_to_now(&s.sct_access); (void)putsect(&s); count++; } if (count > 0) { game_note_bsanct(); nreport(player->cnum, N_BROKE_SANCT, 0, 1); } }
static void starv_sects(char *range) { struct nstr_sect nstr; struct sctstr sect; int nsect = 0; int s, save; if (!snxtsct(&nstr, range)) return; while (nxtsct(&nstr, §)) { if (!player->owner) continue; if (sect.sct_type == SCT_SANCT) continue; /* * Check for starvation. Suppress complaints about tiny * population without food by adding 1f just for the check. * That's okay because growfood() will grow at least that much * anyway. */ save = sect.sct_item[I_FOOD]; if (sect.sct_item[I_FOOD] == 0) sect.sct_item[I_FOOD] = 1; s = famine_victims(sect.sct_item, etu_per_update); sect.sct_item[I_FOOD] = save; if (s == 0) continue; if (nsect++ == 0) sect_hdr(); if (player->god) pr("%3d ", sect.sct_own); prxy("%4d,%-4d", nstr.x, nstr.y); pr(" %c", dchr[sect.sct_type].d_mnem); pr(" %c", sect.sct_own != sect.sct_oldown ? '*' : ' '); if (sect.sct_newtype != sect.sct_type) pr("%c", dchr[sect.sct_newtype].d_mnem); else pr(" "); pr("%4d%%", sect.sct_effic); starv_people(sect.sct_item, s); } if (nsect == 0) { if (player->argp[1]) pr("%s: No sector(s)\n", player->argp[1]); else pr("%s: No sector(s)\n", ""); return; } else pr("%d sector%s\n", nsect, splur(nsect)); return; }
/* * threshold <COMM> <SECTS> <THRESH> */ int thre(void) { struct sctstr sect; struct nstr_sect nstr; int val; struct ichrstr *ip; char *p; int thresh; i_type type; char prompt[128]; char buf[128]; if (!(ip = whatitem(player->argp[1], "What commodity? "))) return RET_SYN; if (!snxtsct(&nstr, player->argp[2])) return RET_SYN; type = ip->i_uid; while (nxtsct(&nstr, §)) { if (!player->owner) continue; val = sect.sct_dist[type]; if (val > 0) sprintf(prompt, "%s %s old threshold %d new? ", xyas(nstr.x, nstr.y, player->cnum), dchr[sect.sct_type].d_name, val); else sprintf(prompt, "%s %s threshold? ", xyas(nstr.x, nstr.y, player->cnum), dchr[sect.sct_type].d_name); if (!(p = getstarg(player->argp[3], prompt, buf))) return RET_FAIL; if (!*p) continue; if (!check_sect_ok(§)) return RET_FAIL; thresh = atoi(p); if (thresh < 0) return RET_FAIL; if (thresh > ITEM_MAX) thresh = ITEM_MAX; if ((val > 0) && (val == thresh)) { pr("%s threshold unchanged (left at %d)\n", xyas(nstr.x, nstr.y, player->cnum), val); continue; } if (val > 0 && player->argp[3] && *player->argp[3]) pr("%s old threshold %d\n", xyas(nstr.x, nstr.y, player->cnum), val); sect.sct_dist[type] = thresh; putsect(§); } return RET_OK; }
void bitinit2(struct nstr_sect *np, unsigned char *bitmap, int country) { struct sctstr sect; int eff; while (nxtsct(np, §)) { if (sect.sct_own != country) continue; eff = sect.sct_effic / 20; if (eff > 4) eff = 4; emp_setbitmap(np->x, np->y, bitmap, bitmaps[eff]); } snxtsct_rewind(np); }
/* * Update @owner's bmap for radar at @cx,@cy. * @eff is the radar's efficiency, @tlev its tech level, @spy its power. */ void rad_map_set(natid owner, int cx, int cy, int eff, double tlev, int spy) { struct nstr_sect ns; struct sctstr sect; int range = rad_range(eff, tlev, spy); int changed = 0; char ch; snxtsct_dist(&ns, cx, cy, range); while (nxtsct(&ns, §)) { ch = rad_char(§, ns.curdist, range, owner); changed += map_set(owner, ns.x, ns.y, ch, 0); } if (changed) writemap(owner); }
int wipe(void) { struct sctstr sect; struct nstr_sect nstr; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; while (nxtsct(&nstr, §)) { if (!player->owner) continue; memset(sect.sct_dist, 0, sizeof(sect.sct_dist)); pr("Distribution thresholds wiped from %s\n", xyas(nstr.x, nstr.y, player->cnum)); putsect(§); } return RET_OK; }
/*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; }
int fly_map(coord curx, coord cury) { struct nstr_sect ns; struct sctstr sect; char view[7]; int i; snxtsct_dist(&ns, curx, cury, 1); i = 0; while (i < 7 && nxtsct(&ns, §)) { /* Nasty: this relies on the iteration order */ if (!(view[i] = player->bmap[sect.sct_uid])) view[i] = ' '; i++; } pr(" %c %c\n", view[0], view[1]); pr(" %c %c %c\n", view[2], view[3], view[4]); pr(" %c %c\n", view[5], view[6]); return RET_OK; }
int newe(void) { struct natstr *natp; struct sctstr sect; struct nstr_sect nstr; double work, lcms, hcms; int nsect; int civs = 0; int uws = 0; int bwork; int twork; int type; int eff; int maxpop; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; player->simulation = 1; prdate(); nsect = 0; while (nxtsct(&nstr, §)) { if (!player->owner) continue; if (!sect.sct_off) { civs = (1.0 + obrate * etu_per_update) * sect.sct_item[I_CIVIL]; uws = (1.0 + uwbrate * etu_per_update) * sect.sct_item[I_UW]; natp = getnatp(sect.sct_own); maxpop = max_pop(natp->nat_level[NAT_RLEV], §); work = new_work(§, total_work(sect.sct_work, etu_per_update, civs, sect.sct_item[I_MILIT], uws, maxpop)); bwork = work / 2; type = sect.sct_type; eff = sect.sct_effic; if (sect.sct_newtype != type) { twork = (eff + 3) / 4; if (twork > bwork) { twork = bwork; } bwork -= twork; eff -= twork * 4; if (eff <= 0) { type = sect.sct_newtype; eff = 0; } twork = 100 - eff; if (twork > bwork) { twork = bwork; } if (dchr[type].d_lcms > 0) { lcms = sect.sct_item[I_LCM]; lcms = (int)(lcms / dchr[type].d_lcms); if (twork > lcms) twork = lcms; } if (dchr[type].d_hcms > 0) { hcms = sect.sct_item[I_HCM]; hcms = (int)(hcms / dchr[type].d_hcms); if (twork > hcms) twork = hcms; } eff += twork; } else if (eff < 100) { twork = 100 - eff; if (twork > bwork) { twork = bwork; } if (dchr[type].d_lcms > 0) { lcms = sect.sct_item[I_LCM]; lcms = (int)(lcms / dchr[type].d_lcms); if (twork > lcms) twork = lcms; } if (dchr[type].d_hcms > 0) { hcms = sect.sct_item[I_HCM]; hcms = (int)(hcms / dchr[type].d_hcms); if (twork > hcms) twork = hcms; } eff += twork; } } else { eff = sect.sct_effic; type = sect.sct_type; } if (nsect++ == 0) { pr("EFFICIENCY SIMULATION\n"); pr(" sect des projected eff\n"); } prxy("%4d,%-4d", nstr.x, nstr.y); pr(" %c", dchr[type].d_mnem); pr(" %3d%%\n", eff); } player->simulation = 0; if (nsect == 0) { if (player->argp[1]) pr("%s: No sector(s)\n", player->argp[1]); else pr("%s: No sector(s)\n", ""); return RET_FAIL; } else pr("%d sector%s\n", nsect, splur(nsect)); return RET_OK; }
int cens(void) { struct sctstr sect; int nsect; int n; struct nstr_sect nstr; char dirstr[20]; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; prdate(); for (n = 1; n <= 6; n++) dirstr[n] = dirch[n]; dirstr[0] = '.'; dirstr[7] = '$'; dirstr[8] = '\0'; nsect = 0; while (nxtsct(&nstr, §)) { if (!player->owner) continue; if (nsect++ == 0) cens_hdr(); if (player->god) pr("%3d ", sect.sct_own); prxy("%4d,%-4d", nstr.x, nstr.y); pr(" %c", dchr[sect.sct_type].d_mnem); if (sect.sct_newtype != sect.sct_type) pr("%c", dchr[sect.sct_newtype].d_mnem); else pr(" "); pr("%4d%%", sect.sct_effic); if (sect.sct_off) pr(" no "); else pr(" "); pr("%4d", sect.sct_mobil); pr(" %c", dirstr[sect.sct_del[I_UW] & 0x7]); pr("%c", dirstr[sect.sct_del[I_FOOD] & 0x7]); n = sect.sct_dist[I_UW] % 1000; pr(" %c", n == 0 ? '.' : '0' + (n / 100)); n = sect.sct_dist[I_FOOD] % 1000; pr("%c ", n == 0 ? '.' : '0' + (n / 100)); if (sect.sct_own != sect.sct_oldown) pr("%3d", sect.sct_oldown); else pr(" "); pr("%5d", sect.sct_item[I_CIVIL]); pr("%5d", sect.sct_item[I_MILIT]); pr("%5d", sect.sct_item[I_UW]); pr("%5d", sect.sct_item[I_FOOD]); pr("%4d%%", sect.sct_work); pr("%5d", sect.sct_avail); if (!player->god) { if (sect.sct_terr) pr("%4d", sect.sct_terr); else pr(" "); } pr("%5d", opt_FALLOUT ? sect.sct_fallout : 0); if (sect.sct_coastal) pr("%4d", sect.sct_coastal); pr("\n"); } if (nsect == 0) { if (player->argp[1]) pr("%s: No sector(s)\n", player->argp[1]); else pr("%s: No sector(s)\n", ""); return RET_FAIL; } else pr("%d sector%s\n", nsect, splur(nsect)); return 0; }
/* * format: coastwatch [<SECTS>] */ int coas(void) { struct sctstr sect; struct nstr_sect nstr; struct coast *cp; struct coast *list[TSIZE]; int i, n; int vrange, see; int x, y, dx, dy, dxmax; int nship = 0; double tech; struct nstr_item ni; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; for (i = 0; i < TSIZE; i++) list[i] = NULL; cp = malloc(sizeof(*cp)); snxtitem_all(&ni, EF_SHIP); while (nxtitem(&ni, &cp->c_shp)) { if (cp->c_shp.shp_own == 0 || cp->c_shp.shp_own == player->cnum) continue; /* * don't bother putting subs in the table... * unless they're in a sector you own (harbor or such) */ getsect(cp->c_shp.shp_x, cp->c_shp.shp_y, §); if ((mchr[(int)cp->c_shp.shp_type].m_flags & M_SUB) && (sect.sct_own != player->cnum)) continue; n = scthash(cp->c_shp.shp_x, cp->c_shp.shp_y, TSIZE); cp->c_spotted = 0; cp->c_number = i; cp->c_next = list[n]; list[n] = cp; cp = malloc(sizeof(*cp)); nship++; } /* get that last one! */ free(cp); pr("- = [ Coastwatch report for %s ] = -\n", cname(player->cnum)); pr(" Country Ship Location\n"); tech = tfact(player->cnum, 1.0); while (nxtsct(&nstr, §) && nship) { if (sect.sct_own != player->cnum) continue; see = sect.sct_type == SCT_RADAR ? 14 : 4; vrange = (int)(sect.sct_effic / 100.0 * see * tech); if (vrange < 1) vrange = 1; for (dy = -vrange; dy <= vrange; dy++) { y = ynorm(sect.sct_y + dy); dxmax = 2 * vrange - abs(dy); for (dx = -dxmax; dx <= dxmax; dx += 2) { x = xnorm(sect.sct_x + dx); n = scthash(x, y, TSIZE); if (!list[n]) continue; nship -= showship(&list[n], x, y); } } } /* free up the coast structs calloc'ed above */ for (i = 0; i < TSIZE; i++) { while (NULL != (cp = list[i])) { list[i] = cp->c_next; free(cp); } } 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; }
int desi(void) { int n; char *p; int des; struct nstr_sect nstr; struct sctstr sect; struct natstr *natp; char prompt[128]; char buf[1024]; int changed = 0; int rc = RET_OK; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; natp = getnatp(player->cnum); while (nxtsct(&nstr, §)) { if (!player->owner) continue; if (!player->god && dchr[sect.sct_type].d_cost < 0) continue; sprintf(prompt, "%s %d%% %s desig? ", xyas(sect.sct_x, sect.sct_y, player->cnum), sect.sct_effic, dchr[sect.sct_type].d_name); if (!(p = getstarg(player->argp[2], prompt, buf))) { rc = RET_FAIL; break; } if (!check_sect_ok(§)) continue; des = sct_typematch(p); if (des < 0) { pr("No such designation\n" "See \"info Sector-types\" for possible designations\n"); rc = RET_FAIL; break; } if (!player->god) { if (des == SCT_WASTE) { pr("Only a nuclear device (or %s) can make a %s!\n", cname(0), dchr[des].d_name); rc = RET_FAIL; break; } if (dchr[des].d_cost < 0) { pr("Only %s can designate a %s!\n", cname(0), dchr[des].d_name); rc = RET_FAIL; break; } if (dchr[des].d_terrain != dchr[sect.sct_type].d_terrain) { pr("You can't change a %s into a %s\n", dchr[sect.sct_type].d_name, dchr[des].d_name); continue; } } if (sect.sct_type == des && sect.sct_newtype == des) continue; if ((des == SCT_HARBR || des == SCT_BHEAD) && !sect.sct_coastal) { pr("%s does not border on water.\n", xyas(nstr.x, nstr.y, player->cnum)); if (player->god) pr("But if it's what you want ...\n"); else continue; } if (sect.sct_type == SCT_SANCT && !player->god) continue; n = sect.sct_type; if ((sect.sct_newtype != des) && (sect.sct_type != des) && dchr[des].d_cost > 0) { if (natp->nat_money < player->dolcost + dchr[des].d_cost) { pr("You can't afford a %s!\n", dchr[des].d_name); rc = RET_FAIL; break; } player->dolcost += dchr[des].d_cost; } if (sect.sct_type != des && (sect.sct_effic < 5 || player->god)) { if (player->god) set_coastal(§, sect.sct_type, des); sect.sct_type = des; sect.sct_effic = 0; changed += map_set(player->cnum, sect.sct_x, sect.sct_y, dchr[des].d_mnem, 0); } sect.sct_newtype = des; putsect(§); if (!player->god && sect.sct_x == natp->nat_xcap && sect.sct_y == natp->nat_ycap && des != SCT_CAPIT && des != SCT_SANCT && des != SCT_MOUNT) pr("You have redesignated your capital!\n"); if (opt_EASY_BRIDGES == 0) { /* may cause a bridge fall */ if (n != SCT_BHEAD) continue; bridgefall(§); } } if (changed) writemap(player->cnum); return rc; }
/* * Draw a radar map for radar at @cx,@cy. * @eff is the radar's efficiency, @tlev its tech level, @spy its power. * Submarines are detected at fraction @seesub of the range. */ void radmap(int cx, int cy, int eff, double tlev, int spy, double seesub) { int visib, rng; struct sctstr sect; struct shpstr ship; struct plnstr plane; struct nstr_sect ns; struct nstr_item ni; int x, y; int row; int n; int range = rad_range(eff, tlev, spy); int changed = 0; if (!radbuf) radbuf = malloc(WORLD_Y * MAPWIDTH(1)); if (!visbuf) visbuf = malloc(WORLD_Y * MAPWIDTH(1)); if (!rad) { rad = malloc(WORLD_Y * sizeof(char *)); if (rad && radbuf) { for (x = 0; x < WORLD_Y; x++) rad[x] = &radbuf[(WORLD_X + 1) * x]; } } if (!vis) { vis = malloc(WORLD_Y * sizeof(signed char *)); if (vis && visbuf) { for (x = 0; x < WORLD_Y; x++) vis[x] = &visbuf[(WORLD_X + 1) * x]; } } if (!radbuf || !visbuf || !rad || !vis) { pr("Memory error in radmap2, tell the deity.\n"); return; } memset(visbuf, 0, (WORLD_Y * (WORLD_X + 1))); pr("%s efficiency %d%%, max range %d\n", xyas(cx, cy, player->cnum), eff, range); snxtsct_dist(&ns, cx, cy, range); blankfill(radbuf, &ns.range, 1); while (nxtsct(&ns, §)) { rad[ns.dy][ns.dx] = rad_char(§, ns.curdist, range, player->cnum); changed += map_set(player->cnum, ns.x, ns.y, rad[ns.dy][ns.dx], 0); } if (changed) writemap(player->cnum); snxtitem_dist(&ni, EF_PLANE, cx, cy, range); while (nxtitem(&ni, &plane)) { if (plane.pln_own == 0) continue; /* Used to have 'ghosts' when scanning whole world --ts */ x = deltx(&ns.range, (int)plane.pln_x); y = delty(&ns.range, (int)plane.pln_y); if (pln_is_in_orbit(&plane) && plane.pln_own != player->cnum) { vis[y][x] = 100; rad[y][x] = '$'; } } snxtitem_dist(&ni, EF_SHIP, cx, cy, range); while (nxtitem(&ni, &ship)) { if (ship.shp_own == 0) continue; /* Used to have 'ghosts' when scanning whole world --ts */ x = deltx(&ns.range, (int)ship.shp_x); y = delty(&ns.range, (int)ship.shp_y); visib = shp_visib(&ship); rng = (int)(range * visib / 20.0); if (ni.curdist > rng) continue; if ((mchr[(int)ship.shp_type].m_flags & M_SUB) && ni.curdist > rng * seesub) continue; if (visib > vis[y][x]) { vis[y][x] = visib; /* &~0x20 makes it a cap letter */ rad[y][x] = (*mchr[(int)ship.shp_type].m_name) & ~0x20; } } /* * make the center of the display 0 * so ve et al can find it. */ rad[delty(&ns.range, cy)][deltx(&ns.range, cx)] = '0'; n = ns.range.height; for (row = 0; row < n; row++) pr("%s\n", rad[row]); pr("\n"); }
int rout(void) { struct ichrstr *ip; struct nstr_sect ns; struct natstr *natp; struct sctstr sect; struct nscstr cond[NS_NCOND]; int ncond; struct range relrange; int row; int y; int ry; i_type i_del; int dir; char *p; /* Note this is not re-entrant anyway, so we keep the buffers around */ static char *mapbuf = NULL; static char **map = NULL; int i; if (!(ip = whatitem(player->argp[1], "What item? "))) return RET_SYN; i_del = ip->i_uid;; if (!snxtsct(&ns, player->argp[2])) return RET_SYN; if (!mapbuf) mapbuf = malloc(WORLD_Y * MAPWIDTH(3)); if (!map) { map = malloc(WORLD_Y * sizeof(char *)); if (map && mapbuf) { for (i = 0; i < WORLD_Y; i++) map[i] = &mapbuf[MAPWIDTH(3) * i]; } else if (map) { free(map); map = NULL; } } if (!mapbuf || !map) { pr("Memory error, tell the deity.\n"); logerror("malloc failed in rout\n"); return RET_FAIL; } ncond = ns.ncond; memcpy(cond, ns.cond, sizeof(struct nscstr) * ncond); ns.ncond = 0; natp = getnatp(player->cnum); xyrelrange(natp, &ns.range, &relrange); blankfill(mapbuf, &ns.range, 3); border(&relrange, " ", " "); while (nxtsct(&ns, §)) { if (!player->owner) continue; p = &map[ns.dy][ns.dx * 2]; dir = sect.sct_del[i_del] & 0x7; if (dir && nstr_exec(cond, ncond, §)) memcpy(p, routech[dir], 3); p[1] = dchr[sect.sct_type].d_mnem; } for (row = 0, y = ns.range.ly; row < ns.range.height; y++, row++) { ry = yrel(natp, y); pr("%4d %s %-4d\n", ry, map[row], ry); if (y >= WORLD_Y) y -= WORLD_Y; } border(&relrange, " ", " "); return RET_OK; }
/* * survey type <sarg> ?cond * */ int surv(void) { int nsect; struct nstr_sect nstr; int y; struct valstr val; struct natstr *np; struct sctstr sect; struct range range; char *ptr; struct nscstr cond[NS_NCOND]; int ncond; int i; char buf[1024]; /* Note this is not re-entrant anyway, so we keep the buffers around */ static char *mapbuf = NULL; static char **map = NULL; nsect = 0; ptr = getstarg(player->argp[1], "commodity or variable? ", buf); if (!ptr || !*ptr) return RET_SYN; ptr = nstr_comp_val(ptr, &val, EF_SECTOR); if (!ptr) return RET_SYN; if (val.val_cat != NSC_OFF || nstr_promote(val.val_type) != NSC_LONG) { pr("Can't survey this\n"); return RET_SYN; } for (; isspace(*ptr); ++ptr) ; if (*ptr) return RET_SYN; if (!snxtsct(&nstr, player->argp[2])) return RET_SYN; if (!mapbuf) mapbuf = malloc(WORLD_Y * MAPWIDTH(1)); if (!map) { map = malloc(WORLD_Y * sizeof(char *)); if (map && mapbuf) { for (i = 0; i < WORLD_Y; i++) map[i] = &mapbuf[MAPWIDTH(1) * i]; } else if (map) { free(map); map = NULL; } } if (!mapbuf || !map) { pr("Memory error, tell the deity.\n"); logerror("malloc failed in sect\n"); return RET_FAIL; } ncond = nstr.ncond; memcpy(cond, nstr.cond, sizeof(struct nscstr) * ncond); nstr.ncond = 0; np = getnatp(player->cnum); xyrelrange(np, &nstr.range, &range); border(&range, " ", ""); blankfill(mapbuf, &nstr.range, 1); while (nxtsct(&nstr, §)) { if (!player->owner) continue; ptr = &map[nstr.dy][nstr.dx]; if (nstr_exec(cond, ncond, §)) { ++nsect; *ptr = 0x80 | code_char(val, §); } else { *ptr = dchr[sect.sct_type].d_mnem; } } for (y = nstr.range.ly, i = 0; i < nstr.range.height; y++, i++) { int yval; yval = yrel(np, y); pr("%4d %s %4d\n", yval, map[i], yval); if (y >= WORLD_Y) y -= WORLD_Y; } border(&range, " ", ""); if (nsect > 0) pr("\n%d sector%s.\n", nsect, splur(nsect)); return RET_OK; }
int enli(void) { struct nstr_sect nstr; struct sctstr sect; struct natstr *natp; int civ; int mil; int newmil; int milwant; int totalmil; int reserve; char *p; int quota; char prompt[128]; char buf[1024]; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; natp = getnatp(player->cnum); newmil = 500; sprintf(prompt, "Number to enlist (max %d) : ", newmil); if (!(p = getstarg(player->argp[2], prompt, buf))) return RET_SYN; if ((milwant = atoi(p)) > newmil) milwant = newmil; if (0 != (quota = (milwant < 0))) milwant = -milwant; totalmil = 0; reserve = natp->nat_reserve; if (reserve <= 0) { pr("No military reserves left\n"); return RET_OK; } while (nxtsct(&nstr, §)) { if (!player->owner) continue; if (sect.sct_oldown != player->cnum) continue; civ = sect.sct_item[I_CIVIL]; if (civ == 0) continue; if (sect.sct_loyal > 70) { pr("civilians refuse to report in %s!\n", xyas(sect.sct_x, sect.sct_y, player->cnum)); continue; } if (sect.sct_mobil <= 0) { pr("%s is out of mobility!\n", xyas(sect.sct_x, sect.sct_y, player->cnum)); } mil = sect.sct_item[I_MILIT]; newmil = civ * 0.5; if (quota) { if (newmil > milwant - mil) newmil = milwant - mil; if (newmil > 500) newmil = 500; } else if (newmil > milwant) newmil = milwant; if (newmil > 999 - mil) newmil = 999 - mil; if (newmil <= 0) continue; if (newmil > reserve) newmil = reserve; sect.sct_item[I_MILIT] = newmil + mil; reserve -= newmil; totalmil += newmil; sect.sct_item[I_CIVIL] = civ - newmil; pr("%3d enlisted in %s (%d)\n", newmil, xyas(sect.sct_x, sect.sct_y, player->cnum), mil + newmil); if (sect.sct_mobil > 0) sect.sct_mobil *= 1.0 - (double)newmil / (double)civ; putsect(§); if (totalmil >= 10000) { pr("Rioting in induction center interrupts enlistment\n"); break; } if (reserve == 0) { pr("Military reserve exhausted\n"); break; } } pr("Total new enlistment : %d\n", totalmil); pr("Military reserves stand at %d\n", reserve); if (totalmil) { natp->nat_reserve -= totalmil; putnat(natp); } if ((player->btused += roundavg(totalmil * 0.02)) > 0) pr("Paperwork at recruiting stations ... %d\n", player->btused); return RET_OK; }
static void gen_power(struct powstr *powbuf, int save) { float upower[MAXNOC]; float *f_ptr; float *f_pt2; struct powstr *pow; int i, maxpop; struct sctstr sect; struct dchrstr *dcp; struct plnstr plane; struct plchrstr *pcp; struct shpstr ship; struct mchrstr *mcp; struct lndstr land; struct lchrstr *lcp; struct nukstr nuke; struct nchrstr *ncp; struct nstr_item ni; struct nstr_sect ns; struct natstr *natp; player->btused += 10; memset(powbuf, 0, MAXNOC * sizeof(*powbuf)); memset(upower, 0, sizeof(upower)); snxtsct_all(&ns); while (nxtsct(&ns, §)) { if (sect.sct_own == 0) continue; dcp = &dchr[sect.sct_type]; natp = getnatp(sect.sct_own); pow = &powbuf[sect.sct_own]; pow->p_sects += 1.0; pow->p_effic += sect.sct_effic; addtopow(sect.sct_item, pow); pow->p_power += empobj_power(sect.sct_effic, dcp->d_mat, dcp->d_cost); maxpop = max_pop(natp->nat_level[NAT_RLEV], §); pow->p_power += (1.0 + maxpop / 1000.0 * 8) * sect.sct_effic / 100.0; } snxtitem_all(&ni, EF_LAND); while (nxtitem(&ni, &land)) { if (land.lnd_own == 0) continue; lcp = &lchr[land.lnd_type]; pow = &powbuf[land.lnd_own]; addtopow(land.lnd_item, pow); upower[land.lnd_own] += empunit_power(land.lnd_effic, land.lnd_tech, lcp->l_mat, lcp->l_cost); if (!(lcp->l_flags & L_SPY)) pow->p_units += 1.0; } snxtitem_all(&ni, EF_SHIP); while (nxtitem(&ni, &ship)) { if (ship.shp_own == 0) continue; mcp = &mchr[ship.shp_type]; pow = &powbuf[ship.shp_own]; addtopow(ship.shp_item, pow); upower[ship.shp_own] += empunit_power(ship.shp_effic, ship.shp_tech, mcp->m_mat, mcp->m_cost); pow->p_ships += 1.0; } snxtitem_all(&ni, EF_PLANE); while (nxtitem(&ni, &plane)) { if (plane.pln_own == 0) continue; pcp = &plchr[plane.pln_type]; pow = &powbuf[plane.pln_own]; upower[plane.pln_own] += empunit_power(plane.pln_effic, plane.pln_tech, pcp->pl_mat, pcp->pl_cost); pow->p_planes += 1.0; } snxtitem_all(&ni, EF_NUKE); while (nxtitem(&ni, &nuke)) { if (nuke.nuk_own == 0) continue; ncp = &nchr[nuke.nuk_type]; upower[nuke.nuk_own] += empunit_power(nuke.nuk_effic, nuke.nuk_tech, ncp->n_mat, ncp->n_cost); } for (i = 1; NULL != (natp = getnatp(i)); i++) { pow = &powbuf[i]; pow->p_nation = i; if (natp->nat_stat != STAT_ACTIVE) { pow->p_power = 0.; continue; } pow->p_money = natp->nat_money; pow->p_power += money_power(natp->nat_money); pow->p_power *= power_tech_factor(natp->nat_level[NAT_TLEV]); pow->p_power += upower[i]; /* ack. add this vec to the "world power" element */ f_pt2 = &powbuf[0].p_sects; f_ptr = &pow->p_sects; while (f_ptr <= &pow->p_power) { *f_pt2 += *f_ptr; f_pt2++; f_ptr++; } } qsort(&powbuf[1], MAXNOC - 1, sizeof(*powbuf), powcmp); if (!save) return; for (i = 0; i < MAXNOC; i++) putpower(i, &powbuf[i]); #ifdef _WIN32 /* * At least some versions of Windows fail to update mtime on * write(), they delay it until the write actually hits the disk. * Bad, because `power' displays that time. Force it. */ _commit(empfile[EF_POWER].fd); #endif }
/* * Actually get the commod * * First, try to forage in the sector * Second look for a warehouse or headquarters to leech * Third, look for a ship we own in a harbor * Fourth, look for supplies in a supply unit we own * (one good reason to do this last is that the supply * unit will then call resupply, taking more time) * * May want to put code to resupply with SAMs here, later --ts */ static int s_commod(struct empobj *sink, short *vec, i_type type, int wanted, int limit, int actually_doit) { natid own = sink->own; coord x = sink->x; coord y = sink->y; int lookrange; struct sctstr sect; struct nstr_sect ns; struct nstr_item ni; struct lchrstr *lcp; struct shpstr ship; struct lndstr land; /* leave at least 1 military in sectors/ships */ int minimum = 0; int can_move; double move_cost, weight, mobcost; int packing; struct dchrstr *dp; struct ichrstr *ip; if (wanted > limit) wanted = limit; if (wanted <= vec[type]) return 1; wanted -= vec[type]; /* try to get it from sector we're in */ if (sink->ef_type != EF_SECTOR) { getsect(x, y, §); if (sect.sct_own == own) { if (!opt_NOFOOD && type == I_FOOD) minimum = 1 + (int)ceil(food_needed(sect.sct_item, etu_per_update)); if (sect.sct_item[type] - wanted >= minimum) { sect.sct_item[type] -= wanted; if (actually_doit) { vec[type] += wanted; putsect(§); put_empobj(sink->ef_type, sink->uid, sink); } return 1; } else if (sect.sct_item[type] - minimum > 0) { wanted -= sect.sct_item[type] - minimum; sect.sct_item[type] = minimum; if (actually_doit) { vec[type] += sect.sct_item[type] - minimum; putsect(§); } } } } /* look for a headquarters or warehouse */ lookrange = tfact(own, 10.0); snxtsct_dist(&ns, x, y, lookrange); while (nxtsct(&ns, §) && wanted) { if (ns.curdist == 0) continue; if (sect.sct_own != own) continue; if ((sect.sct_type != SCT_WAREH) && (sect.sct_type != SCT_HEADQ) && (sect.sct_type != SCT_HARBR)) continue; if ((sect.sct_type == SCT_HEADQ) && (sect.sct_dist_x == sect.sct_x) && (sect.sct_dist_y == sect.sct_y)) continue; if (sect.sct_effic < 60) continue; move_cost = path_find(sect.sct_x, sect.sct_y, x, y, own, MOB_MOVE); if (move_cost < 0) continue; if (!opt_NOFOOD && type == I_FOOD) minimum = 1 + (int)ceil(food_needed(sect.sct_item, etu_per_update)); if (sect.sct_item[type] <= minimum) continue; ip = &ichr[type]; dp = &dchr[sect.sct_type]; packing = ip->i_pkg[dp->d_pkg]; if (packing > 1 && sect.sct_effic < 60) packing = 1; weight = (double)ip->i_lbs / packing; mobcost = move_cost * weight; if (mobcost > 0) can_move = (double)sect.sct_mobil / mobcost; else can_move = sect.sct_item[type] - minimum; if (can_move > sect.sct_item[type] - minimum) can_move = sect.sct_item[type] - minimum; if (can_move >= wanted) { int n; sect.sct_item[type] -= wanted; /* take off mobility for delivering sect */ n = roundavg(wanted * weight * move_cost); sect.sct_mobil -= LIMIT_TO(n, 0, sect.sct_mobil); if (actually_doit) { vec[type] += wanted; putsect(§); put_empobj(sink->ef_type, sink->uid, sink); } return 1; } else if (can_move > 0) { int n; wanted -= can_move; sect.sct_item[type] -= can_move; /* take off mobility for delivering sect */ n = roundavg(can_move * weight * move_cost); sect.sct_mobil -= LIMIT_TO(n, 0, sect.sct_mobil); if (actually_doit) { vec[type] += can_move; putsect(§); } } } /* look for an owned ship in a harbor */ snxtitem_dist(&ni, EF_SHIP, x, y, lookrange); while (nxtitem(&ni, &ship) && wanted) { if (sink->ef_type == EF_SHIP && sink->uid == ship.shp_uid) continue; if (ship.shp_own != own) continue; if (!(mchr[(int)ship.shp_type].m_flags & M_SUPPLY)) continue; getsect(ship.shp_x, ship.shp_y, §); if (sect.sct_type != SCT_HARBR) continue; if (sect.sct_effic < 2) continue; move_cost = path_find(sect.sct_x, sect.sct_y, x, y, own, MOB_MOVE); if (move_cost < 0) continue; if (!opt_NOFOOD && type == I_FOOD) minimum = 1 + (int)ceil(food_needed(ship.shp_item, etu_per_update)); if (ship.shp_item[type] <= minimum) continue; ip = &ichr[type]; dp = &dchr[sect.sct_type]; packing = ip->i_pkg[dp->d_pkg]; if (packing > 1 && sect.sct_effic < 60) packing = 1; weight = (double)ip->i_lbs / packing; mobcost = move_cost * weight; if (mobcost > 0) can_move = (double)sect.sct_mobil / mobcost; else can_move = ship.shp_item[type] - minimum; if (can_move > ship.shp_item[type] - minimum) can_move = ship.shp_item[type] - minimum; if (can_move >= wanted) { int n; ship.shp_item[type] -= wanted; n = roundavg(wanted * weight * move_cost); sect.sct_mobil -= LIMIT_TO(n, 0, sect.sct_mobil); if (actually_doit) { vec[type] += can_move; putship(ship.shp_uid, &ship); if (n) putsect(§); put_empobj(sink->ef_type, sink->uid, sink); } return 1; } else if (can_move > 0) { int n; wanted -= can_move; ship.shp_item[type] -= can_move; n = roundavg(can_move * weight * move_cost); sect.sct_mobil -= LIMIT_TO(n, 0, sect.sct_mobil); if (actually_doit) { vec[type] += can_move; putship(ship.shp_uid, &ship); if (n) putsect(§); } } } /* look for an owned supply unit */ snxtitem_dist(&ni, EF_LAND, x, y, lookrange); while (nxtitem(&ni, &land) && wanted) { int min; if (sink->ef_type == EF_LAND && sink->uid == land.lnd_uid) continue; if (land.lnd_own != own) continue; lcp = &lchr[(int)land.lnd_type]; if (!(lcp->l_flags & L_SUPPLY)) continue; if (land.lnd_item[type] <= get_minimum(&land, type)) continue; if (land.lnd_ship >= 0) { getsect(land.lnd_x, land.lnd_y, §); if (sect.sct_type != SCT_HARBR || sect.sct_effic < 2) continue; } move_cost = path_find(land.lnd_x, land.lnd_y, x, y, own, MOB_MOVE); if (move_cost < 0) continue; #if 0 /* * Recursive supply is disabled for now. It can introduce * cycles into the "resupplies from" relation. The code below * attempts to break these cycles by temporarily zapping the * commodity being supplied. That puts the land file in a * funny state temporarily, risking loss of supplies when * something goes wrong on the way. Worse, it increases * lnd_seqno even when !actually_doit, which can lead to * spurious seqno mismatch oopses in users of * lnd_could_be_supplied(). I can't be bothered to clean up * this mess right now, because recursive resupply is too dumb * to be really useful anyway: each step uses the first source * it finds, without consideration of mobility cost. If you * re-enable it, don't forget to uncomment its documentation * in supply.t as well. */ if (land.lnd_item[type] - wanted < get_minimum(&land, type)) { struct lndstr save; /* * Temporarily zap this unit's store, so the recursion * avoids it. */ save = land; land.lnd_item[type] = 0; putland(land.lnd_uid, &land); save.lnd_seqno = land.lnd_seqno; s_commod((struct empobj *)&land, land.lnd_item, type, wanted, lchr[land.lnd_type].l_item[type] - wanted, actually_doit); land.lnd_item[type] += save.lnd_item[type]; if (actually_doit) putland(land.lnd_uid, &land); else putland(save.lnd_uid, &save); } #endif min = get_minimum(&land, type); ip = &ichr[type]; weight = ip->i_lbs; mobcost = move_cost * weight; if (mobcost > 0) can_move = (double)land.lnd_mobil / mobcost; else can_move = land.lnd_item[type] - min; if (can_move > land.lnd_item[type] - min) can_move = land.lnd_item[type] - min; if (can_move >= wanted) { land.lnd_item[type] -= wanted; land.lnd_mobil -= roundavg(wanted * weight * move_cost); if (actually_doit) { vec[type] += wanted; putland(land.lnd_uid, &land); put_empobj(sink->ef_type, sink->uid, sink); } return 1; } else if (can_move > 0) { wanted -= can_move; land.lnd_item[type] -= can_move; land.lnd_mobil -= roundavg(can_move * weight * move_cost); if (actually_doit) { vec[type] += can_move; putland(land.lnd_uid, &land); } } } if (actually_doit) put_empobj(sink->ef_type, sink->uid, sink); return 0; }
int dump(void) { struct sctstr sect; char dirstr[20]; int nsect; int n, i; struct nstr_sect nstr; int field[128]; struct natstr *np; time_t now; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; prdate(); (void)strcpy(dirstr, ". $"); for (n = 1; n <= 6; n++) dirstr[n] = dirch[n]; nsect = 0; np = getnatp(player->cnum); if (!player->argp[2]) { for (n = 1; n <= 80; n++) field[n - 1] = n; field[n - 1] = 0; } else { n = 2; i = 0; while (player->argp[n]) { if (!strcmp("des", player->argp[n])) { field[i++] = 1; } else if (!strcmp("sdes", player->argp[n])) { field[i++] = 2; } else if (!strcmp("eff", player->argp[n])) { field[i++] = 3; } else if (!strcmp("mob", player->argp[n])) { field[i++] = 4; } else if (!strcmp("*", player->argp[n])) { field[i++] = 5; } else if (!strcmp("off", player->argp[n])) { field[i++] = 6; } else if (!strcmp("min", player->argp[n])) { field[i++] = 7; } else if (!strcmp("gold", player->argp[n])) { field[i++] = 8; } else if (!strcmp("fert", player->argp[n])) { field[i++] = 9; } else if (!strcmp("ocontent", player->argp[n])) { field[i++] = 10; } else if (!strcmp("uran", player->argp[n])) { field[i++] = 11; } else if (!strcmp("work", player->argp[n])) { field[i++] = 12; } else if (!strcmp("avail", player->argp[n])) { field[i++] = 13; } else if (!strcmp("terr", player->argp[n])) { field[i++] = 14; } else if (!strcmp("civ", player->argp[n])) { field[i++] = 15; } else if (!strcmp("mil", player->argp[n])) { field[i++] = 16; } else if (!strcmp("uw", player->argp[n])) { field[i++] = 17; } else if (!strcmp("food", player->argp[n])) { field[i++] = 18; } else if (!strcmp("shell", player->argp[n])) { field[i++] = 19; } else if (!strcmp("gun", player->argp[n])) { field[i++] = 20; } else if (!strcmp("pet", player->argp[n])) { field[i++] = 21; } else if (!strcmp("iron", player->argp[n])) { field[i++] = 22; } else if (!strcmp("dust", player->argp[n])) { field[i++] = 23; } else if (!strcmp("bar", player->argp[n])) { field[i++] = 24; } else if (!strcmp("oil", player->argp[n])) { field[i++] = 25; } else if (!strcmp("lcm", player->argp[n])) { field[i++] = 26; } else if (!strcmp("hcm", player->argp[n])) { field[i++] = 27; } else if (!strcmp("rad", player->argp[n])) { field[i++] = 28; } else if (!strcmp("u_del", player->argp[n])) { field[i++] = 29; } else if (!strcmp("f_del", player->argp[n])) { field[i++] = 30; } else if (!strcmp("s_del", player->argp[n])) { field[i++] = 31; } else if (!strcmp("g_del", player->argp[n])) { field[i++] = 32; } else if (!strcmp("p_del", player->argp[n])) { field[i++] = 33; } else if (!strcmp("i_del", player->argp[n])) { field[i++] = 34; } else if (!strcmp("d_del", player->argp[n])) { field[i++] = 35; } else if (!strcmp("b_del", player->argp[n])) { field[i++] = 36; } else if (!strcmp("o_del", player->argp[n])) { field[i++] = 37; } else if (!strcmp("l_del", player->argp[n])) { field[i++] = 38; } else if (!strcmp("h_del", player->argp[n])) { field[i++] = 39; } else if (!strcmp("r_del", player->argp[n])) { field[i++] = 40; } else if (!strcmp("u_cut", player->argp[n])) { field[i++] = 41; } else if (!strcmp("f_cut", player->argp[n])) { field[i++] = 42; } else if (!strcmp("s_cut", player->argp[n])) { field[i++] = 43; } else if (!strcmp("g_cut", player->argp[n])) { field[i++] = 44; } else if (!strcmp("p_cut", player->argp[n])) { field[i++] = 45; } else if (!strcmp("i_cut", player->argp[n])) { field[i++] = 46; } else if (!strcmp("d_cut", player->argp[n])) { field[i++] = 47; } else if (!strcmp("b_cut", player->argp[n])) { field[i++] = 48; } else if (!strcmp("o_cut", player->argp[n])) { field[i++] = 49; } else if (!strcmp("l_cut", player->argp[n])) { field[i++] = 50; } else if (!strcmp("h_cut", player->argp[n])) { field[i++] = 51; } else if (!strcmp("r_cut", player->argp[n])) { field[i++] = 52; } else if (!strcmp("dist_x", player->argp[n])) { field[i++] = 53; } else if (!strcmp("dist_y", player->argp[n])) { field[i++] = 54; } else if (!strcmp("c_dist", player->argp[n])) { field[i++] = 55; } else if (!strcmp("m_dist", player->argp[n])) { field[i++] = 56; } else if (!strcmp("u_dist", player->argp[n])) { field[i++] = 57; } else if (!strcmp("f_dist", player->argp[n])) { field[i++] = 58; } else if (!strcmp("s_dist", player->argp[n])) { field[i++] = 59; } else if (!strcmp("g_dist", player->argp[n])) { field[i++] = 60; } else if (!strcmp("p_dist", player->argp[n])) { field[i++] = 61; } else if (!strcmp("i_dist", player->argp[n])) { field[i++] = 62; } else if (!strcmp("d_dist", player->argp[n])) { field[i++] = 63; } else if (!strcmp("b_dist", player->argp[n])) { field[i++] = 64; } else if (!strcmp("o_dist", player->argp[n])) { field[i++] = 65; } else if (!strcmp("l_dist", player->argp[n])) { field[i++] = 66; } else if (!strcmp("h_dist", player->argp[n])) { field[i++] = 67; } else if (!strcmp("r_dist", player->argp[n])) { field[i++] = 68; } else if (!strcmp("road", player->argp[n])) { field[i++] = 69; } else if (!strcmp("rail", player->argp[n])) { field[i++] = 70; } else if (!strcmp("defense", player->argp[n])) { field[i++] = 71; } else if (!strcmp("fallout", player->argp[n])) { field[i++] = 72; } else if (!strcmp("coast", player->argp[n])) { field[i++] = 73; } else if (!strcmp("c_del", player->argp[n])) { field[i++] = 74; } else if (!strcmp("m_del", player->argp[n])) { field[i++] = 75; } else if (!strcmp("c_cut", player->argp[n])) { field[i++] = 76; } else if (!strcmp("m_cut", player->argp[n])) { field[i++] = 77; } else if (!strcmp("terr1", player->argp[n])) { field[i++] = 78; } else if (!strcmp("terr2", player->argp[n])) { field[i++] = 79; } else if (!strcmp("terr3", player->argp[n])) { field[i++] = 80; } else { pr("Unrecognized field %s\n", player->argp[n]); } if (n++ > 100) { pr("Too many fields\n"); return RET_FAIL; } } field[i] = 0; } if (player->god) pr(" "); time(&now); pr("DUMP SECTOR %ld\n", (long)now); if (player->god) pr("own "); pr("x y"); n = 0; while (field[n]) { pr(" "); switch (field[n]) { case 1: pr("des"); break; case 2: pr("sdes"); break; case 3: pr("eff"); break; case 4: pr("mob"); break; case 5: pr("*"); break; case 6: pr("off"); break; case 7: pr("min"); break; case 8: pr("gold"); break; case 9: pr("fert"); break; case 10: pr("ocontent"); break; case 11: pr("uran"); break; case 12: pr("work"); break; case 13: pr("avail"); break; case 14: pr("terr"); break; case 15: pr("civ"); break; case 16: pr("mil"); break; case 17: pr("uw"); break; case 18: pr("food"); break; case 19: pr("shell"); break; case 20: pr("gun"); break; case 21: pr("pet"); break; case 22: pr("iron"); break; case 23: pr("dust"); break; case 24: pr("bar"); break; case 25: pr("oil"); break; case 26: pr("lcm"); break; case 27: pr("hcm"); break; case 28: pr("rad"); break; case 29: pr("u_del"); break; case 30: pr("f_del"); break; case 31: pr("s_del"); break; case 32: pr("g_del"); break; case 33: pr("p_del"); break; case 34: pr("i_del"); break; case 35: pr("d_del"); break; case 36: pr("b_del"); break; case 37: pr("o_del"); break; case 38: pr("l_del"); break; case 39: pr("h_del"); break; case 40: pr("r_del"); break; case 41: pr("u_cut"); break; case 42: pr("f_cut"); break; case 43: pr("s_cut"); break; case 44: pr("g_cut"); break; case 45: pr("p_cut"); break; case 46: pr("i_cut"); break; case 47: pr("d_cut"); break; case 48: pr("b_cut"); break; case 49: pr("o_cut"); break; case 50: pr("l_cut"); break; case 51: pr("h_cut"); break; case 52: pr("r_cut"); break; case 53: pr("dist_x"); break; case 54: pr("dist_y"); break; case 55: pr("c_dist"); break; case 56: pr("m_dist"); break; case 57: pr("u_dist"); break; case 58: pr("f_dist"); break; case 59: pr("s_dist"); break; case 60: pr("g_dist"); break; case 61: pr("p_dist"); break; case 62: pr("i_dist"); break; case 63: pr("d_dist"); break; case 64: pr("b_dist"); break; case 65: pr("o_dist"); break; case 66: pr("l_dist"); break; case 67: pr("h_dist"); break; case 68: pr("r_dist"); break; case 69: pr("road"); break; case 70: pr("rail"); break; case 71: pr("defense"); break; case 72: pr("fallout"); break; case 73: pr("coast"); break; case 74: pr("c_del"); break; case 75: pr("m_del"); break; case 76: pr("c_cut"); break; case 77: pr("m_cut"); break; case 78: pr("terr1"); break; case 79: pr("terr2"); break; case 80: pr("terr3"); break; } n++; } pr("\n"); while (nxtsct(&nstr, §)) { if (!player->owner) continue; nsect++; /* census */ if (player->god) pr("%d ", sect.sct_own); pr("%d %d", xrel(np, nstr.x), yrel(np, nstr.y)); n = 0; while (field[n]) { pr(" "); switch (field[n++]) { case 1: pr("%c", dchr[sect.sct_type].d_mnem); break; case 2: if (sect.sct_newtype != sect.sct_type) pr("%c", dchr[sect.sct_newtype].d_mnem); else pr("_"); break; case 3: pr("%d", sect.sct_effic); break; case 4: pr("%d", sect.sct_mobil); break; case 5: pr("%c", sect.sct_own != sect.sct_oldown ? '*' : '.'); break; case 6: pr("%d", sect.sct_off); break; case 7: pr("%d", sect.sct_min); break; case 8: pr("%d", sect.sct_gmin); break; case 9: pr("%d", sect.sct_fertil); break; case 10: pr("%d", sect.sct_oil); break; case 11: pr("%d", sect.sct_uran); break; case 12: pr("%d", sect.sct_work); break; case 13: pr("%d", sect.sct_avail); break; case 14: pr("%d", sect.sct_terr); break; case 15: pr("%d", sect.sct_item[I_CIVIL]); break; case 16: pr("%d", sect.sct_item[I_MILIT]); break; case 17: pr("%d", sect.sct_item[I_UW]); break; case 18: pr("%d", sect.sct_item[I_FOOD]); break; /* commodity */ case 19: pr("%d", sect.sct_item[I_SHELL]); break; case 20: pr("%d", sect.sct_item[I_GUN]); break; case 21: pr("%d", sect.sct_item[I_PETROL]); break; case 22: pr("%d", sect.sct_item[I_IRON]); break; case 23: pr("%d", sect.sct_item[I_DUST]); break; case 24: pr("%d", sect.sct_item[I_BAR]); break; case 25: pr("%d", sect.sct_item[I_OIL]); break; case 26: pr("%d", sect.sct_item[I_LCM]); break; case 27: pr("%d", sect.sct_item[I_HCM]); break; case 28: pr("%d", sect.sct_item[I_RAD]); break; /* cutoff */ case 29: pr("%c", dirstr[sect.sct_del[I_UW] & 0x7]); break; case 30: pr("%c", dirstr[sect.sct_del[I_FOOD] & 0x7]); break; case 31: pr("%c", dirstr[sect.sct_del[I_SHELL] & 0x7]); break; case 32: pr("%c", dirstr[sect.sct_del[I_GUN] & 0x7]); break; case 33: pr("%c", dirstr[sect.sct_del[I_PETROL] & 0x7]); break; case 34: pr("%c", dirstr[sect.sct_del[I_IRON] & 0x7]); break; case 35: pr("%c", dirstr[sect.sct_del[I_DUST] & 0x7]); break; case 36: pr("%c", dirstr[sect.sct_del[I_BAR] & 0x7]); break; case 37: pr("%c", dirstr[sect.sct_del[I_OIL] & 0x7]); break; case 38: pr("%c", dirstr[sect.sct_del[I_LCM] & 0x7]); break; case 39: pr("%c", dirstr[sect.sct_del[I_HCM] & 0x7]); break; case 40: pr("%c", dirstr[sect.sct_del[I_RAD] & 0x7]); break; case 41: pr("%d", sect.sct_del[I_UW] & ~0x7); break; case 42: pr("%d", sect.sct_del[I_FOOD] & ~0x7); break; case 43: pr("%d", sect.sct_del[I_SHELL] & ~0x7); break; case 44: pr("%d", sect.sct_del[I_GUN] & ~0x7); break; case 45: pr("%d", sect.sct_del[I_PETROL] & ~0x7); break; case 46: pr("%d", sect.sct_del[I_IRON] & ~0x7); break; case 47: pr("%d", sect.sct_del[I_DUST] & ~0x7); break; case 48: pr("%d", sect.sct_del[I_BAR] & ~0x7); break; case 49: pr("%d", sect.sct_del[I_OIL] & ~0x7); break; case 50: pr("%d", sect.sct_del[I_LCM] & ~0x7); break; case 51: pr("%d", sect.sct_del[I_HCM] & ~0x7); break; case 52: pr("%d", sect.sct_del[I_RAD] & ~0x7); break; /* level */ case 53: pr("%d", xrel(getnatp(player->cnum), sect.sct_dist_x)); break; case 54: pr("%d", yrel(getnatp(player->cnum), sect.sct_dist_y)); break; case 55: pr("%d", sect.sct_dist[I_CIVIL]); break; case 56: pr("%d", sect.sct_dist[I_MILIT]); break; case 57: pr("%d", sect.sct_dist[I_UW]); break; case 58: pr("%d", sect.sct_dist[I_FOOD]); break; case 59: pr("%d", sect.sct_dist[I_SHELL]); break; case 60: pr("%d", sect.sct_dist[I_GUN]); break; case 61: pr("%d", sect.sct_dist[I_PETROL]); break; case 62: pr("%d", sect.sct_dist[I_IRON]); break; case 63: pr("%d", sect.sct_dist[I_DUST]); break; case 64: pr("%d", sect.sct_dist[I_BAR]); break; case 65: pr("%d", sect.sct_dist[I_OIL]); break; case 66: pr("%d", sect.sct_dist[I_LCM]); break; case 67: pr("%d", sect.sct_dist[I_HCM]); break; case 68: pr("%d", sect.sct_dist[I_RAD]); break; case 69: pr("%d", sect.sct_road); break; case 70: pr("%d", sect.sct_rail); break; case 71: pr("%d", SCT_DEFENSE(§)); break; case 72: if (opt_FALLOUT) pr("%d", sect.sct_fallout); else pr("0"); break; case 73: pr("%d", sect.sct_coastal); break; case 74: pr("%c", dirstr[sect.sct_del[I_CIVIL] & 0x7]); break; case 75: pr("%c", dirstr[sect.sct_del[I_MILIT] & 0x7]); break; case 76: pr("%d", sect.sct_del[I_CIVIL] & ~0x7); break; case 77: pr("%d", sect.sct_del[I_MILIT] & ~0x7); break; case 78: pr("%d", sect.sct_terr1); break; case 79: pr("%d", sect.sct_terr2); break; case 80: pr("%d", sect.sct_terr3); break; } } pr("\n"); } if (nsect == 0) { if (player->argp[1]) pr("%s: No sector(s)\n", player->argp[1]); else pr("%s: No sector(s)\n", ""); return RET_FAIL; } else pr("%d sector%s\n", nsect, splur(nsect)); return RET_OK; }
int detonate(struct nukstr *np, coord x, coord y, int airburst) { int nuketype = np->nuk_type; struct nchrstr *ncp; struct plnstr plane; struct sctstr sect; struct shpstr ship; struct lndstr land; struct nukstr nuke; natid own; int type; int damage; int fallout; int rad; struct nstr_sect ns; struct nstr_item ni; int changed = 0; pr("Releasing RV's for %s detonation...\n", airburst ? "airburst" : "groundburst"); getsect(x, y, §); ncp = &nchr[nuketype]; kaboom(x, y, ncp->n_blast); rad = ncp->n_blast; if (!airburst) rad = rad * 2 / 3; if (sect.sct_type == SCT_WATER) rad = 0; /* Nukes falling on water affect only 1 sector */ np->nuk_effic = 0; putnuke(np->nuk_uid, np); snxtsct_dist(&ns, x, y, rad); while (nxtsct(&ns, §)) { own = sect.sct_own; type = sect.sct_type; if ((damage = nukedamage(ncp, ns.curdist, airburst)) <= 0) continue; if (type == SCT_SANCT) { pr("bounced off %s\n", xyas(ns.x, ns.y, player->cnum)); mpr(own, "%s nuclear device bounced off %s\n", cname(player->cnum), xyas(ns.x, ns.y, own)); nreport(player->cnum, N_NUKE, own, 1); continue; } sect_damage(§, damage); if (opt_FALLOUT) { fallout = sect.sct_fallout; if (ncp->n_flags & N_NEUT) fallout += damage * 30; else fallout += damage * 3; sect.sct_fallout = MIN(fallout, FALLOUT_MAX); } if (damage > 100) { sect.sct_oldown = 0; sect.sct_own = 0; if (type == SCT_WATER || type == SCT_BSPAN || type == SCT_BTOWER) { if (type != SCT_WATER) { pr("left nothing but water in %s\n", xyas(ns.x, ns.y, player->cnum)); if (own != player->cnum) mpr(own, "%s nuclear device left nothing but water in %s\n", cname(player->cnum), xyas(ns.x, ns.y, own)); sect.sct_newtype = SCT_WATER; sect.sct_type = SCT_WATER; } } else { sect.sct_newtype = SCT_WASTE; sect.sct_type = SCT_WASTE; pr("turned %s into a radioactive wasteland\n", xyas(ns.x, ns.y, player->cnum)); if (own != player->cnum) mpr(own, "%s nuclear device turned %s into a radioactive wasteland\n", cname(player->cnum), xyas(ns.x, ns.y, own)); } changed |= map_set(player->cnum, sect.sct_x, sect.sct_y, dchr[sect.sct_type].d_mnem, 0); } else { pr("did %d%% damage in %s\n", damage, xyas(ns.x, ns.y, player->cnum)); if (own != player->cnum) mpr(own, "%s nuclear device did %d%% damage in %s\n", cname(player->cnum), damage, xyas(ns.x, ns.y, own)); } (void)putsect(§); if (type != SCT_WATER) nreport(player->cnum, N_NUKE, own, 1); } if (changed) writebmap(player->cnum); snxtitem_dist(&ni, EF_PLANE, x, y, rad); while (nxtitem(&ni, &plane)) { if ((own = plane.pln_own) == 0) continue; if (plane.pln_flags & PLN_LAUNCHED) continue; damage = nukedamage(ncp, ni.curdist, airburst) - plane.pln_harden; if (damage <= 0) continue; if (plane.pln_ship >= 0) { /* Are we on a sub? */ getship(plane.pln_ship, &ship); if (mchr[(int)ship.shp_type].m_flags & M_SUB) { struct sctstr sect1; /* Should we damage this sub? */ getsect(ship.shp_x, ship.shp_y, §1); if (sect1.sct_type == SCT_BSPAN || sect1.sct_type == SCT_BTOWER || sect1.sct_type == SCT_WATER) { /* Ok, we're not in a harbor or trapped inland. Now, did we get pasted directly? */ if (ship.shp_x != x || ship.shp_y != y) { /* Nope, so don't mess with it */ continue; } } } } planedamage(&plane, damage); if (own == player->cnum) { pr("%s at %s reports %d%% damage\n", prplane(&plane), xyas(plane.pln_x, plane.pln_y, player->cnum), damage); } else { mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", cname(player->cnum), damage, prplane(&plane), xyas(plane.pln_x, plane.pln_y, own)); } putplane(ni.cur, &plane); } snxtitem_dist(&ni, EF_LAND, x, y, rad); while (nxtitem(&ni, &land)) { if ((own = land.lnd_own) == 0) continue; if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) continue; if (land.lnd_ship >= 0) { /* Are we on a sub? */ getship(land.lnd_ship, &ship); if (mchr[(int)ship.shp_type].m_flags & M_SUB) { struct sctstr sect1; /* Should we damage this sub? */ getsect(ship.shp_x, ship.shp_y, §1); if (sect1.sct_type == SCT_BSPAN || sect1.sct_type == SCT_BTOWER || sect1.sct_type == SCT_WATER) { /* Ok, we're not in a harbor or trapped inland. Now, did we get pasted directly? */ if (ship.shp_x != x || ship.shp_y != y) { /* Nope, so don't mess with it */ continue; } } } } land_damage(&land, damage); if (own == player->cnum) { pr("%s at %s reports %d%% damage\n", prland(&land), xyas(land.lnd_x, land.lnd_y, player->cnum), damage); } else { mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", cname(player->cnum), damage, prland(&land), xyas(land.lnd_x, land.lnd_y, own)); } putland(land.lnd_uid, &land); } snxtitem_dist(&ni, EF_SHIP, x, y, rad); while (nxtitem(&ni, &ship)) { if ((own = ship.shp_own) == 0) continue; if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) continue; if (mchr[(int)ship.shp_type].m_flags & M_SUB) { struct sctstr sect1; /* Should we damage this sub? */ getsect(ship.shp_x, ship.shp_y, §1); if (sect1.sct_type == SCT_BSPAN || sect1.sct_type == SCT_BTOWER || sect1.sct_type == SCT_WATER) { /* Ok, we're not in a harbor or trapped inland. Now, did we get pasted directly? */ if (ship.shp_x != x || ship.shp_y != y) { /* Nope, so don't mess with it */ continue; } } } ship_damage(&ship, damage); if (own == player->cnum) { pr("%s at %s reports %d%% damage\n", prship(&ship), xyas(ship.shp_x, ship.shp_y, player->cnum), damage); } else { mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", cname(player->cnum), damage, prship(&ship), xyas(ship.shp_x, ship.shp_y, own)); } putship(ship.shp_uid, &ship); } snxtitem_dist(&ni, EF_NUKE, x, y, rad); while (nxtitem(&ni, &nuke)) { if ((own = nuke.nuk_own) == 0) continue; if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) continue; if (!pct_chance(damage)) continue; nuke.nuk_effic = 0; if (own == player->cnum) { pr("%s at %s destroyed\n", prnuke(&nuke), xyas(nuke.nuk_x, nuke.nuk_y, player->cnum)); } else { mpr(own, "%s nuclear device destroyed %s at %s\n", cname(player->cnum), prnuke(&nuke), xyas(nuke.nuk_x, nuke.nuk_y, own)); } putnuke(ni.cur, &nuke); } return nukedamage(ncp, 0, airburst); }
/* * format: skywatch [<SECTS>] */ int skyw(void) { struct sctstr sect; struct nstr_sect nstr; struct sky *skyp; struct sky *list[TSIZE]; int i, n; int vrange, see; int x, y, dx, dy, dxmax; int nsat = 0; double tech; struct nstr_item ni; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; for (i = 0; i < TSIZE; i++) list[i] = NULL; skyp = malloc(sizeof(*skyp)); snxtitem_all(&ni, EF_PLANE); while (nxtitem(&ni, &skyp->s_sat)) { if (!skyp->s_sat.pln_own) continue; if (!pln_is_in_orbit(&skyp->s_sat)) continue; getsect(skyp->s_sat.pln_x, skyp->s_sat.pln_y, §); n = scthash(skyp->s_sat.pln_x, skyp->s_sat.pln_y, TSIZE); skyp->s_spotted = 0; skyp->s_next = list[n]; list[n] = skyp; skyp = malloc(sizeof(*skyp)); nsat++; } /* get that last one! */ free(skyp); pr("- = [ Skywatch report for %s ] = -\n", cname(player->cnum)); pr(" Country Satellite Location\n"); tech = tfact(player->cnum, 1.0); while (nxtsct(&nstr, §) && nsat) { if (sect.sct_own != player->cnum) continue; see = sect.sct_type == SCT_RADAR ? 14 : 4; vrange = (int)(sect.sct_effic / 100.0 * see * tech); if (vrange < 1) vrange = 1; for (dy = -vrange; dy <= vrange; dy++) { y = ynorm(sect.sct_y + dy); dxmax = 2 * vrange - abs(dy); for (dx = -dxmax; dx <= dxmax; dx += 2) { x = xnorm(sect.sct_x + dx); n = scthash(x, y, TSIZE); if (!list[n]) continue; nsat -= showsat(&list[n], x, y); } } } /* free up the sky structs calloc'ed above */ for (i = 0; i < TSIZE; i++) { while (NULL != (skyp = list[i])) { list[i] = skyp->s_next; free(skyp); } } return RET_OK; }
int cuto(void) { struct sctstr sect; int nsect; int n; struct nstr_sect nstr; char dirstr[12]; if (!snxtsct(&nstr, player->argp[1])) return RET_SYN; prdate(); (void)strcpy(dirstr, ". $"); for (n = 1; n <= 6; n++) dirstr[n] = dirch[n]; nsect = 0; while (nxtsct(&nstr, §)) { if (!player->owner) continue; if (nsect++ == 0) { pr("DELIVERY CUTOFF LEVELS\n"); if (player->god) pr("own"); pr(" sect cmufsgpidbolhr civ mil uw food sh gun pet irn dst bar oil lcm hcm rad\n"); } if (player->god) pr("%3d", sect.sct_own); prxy("%3d,%-3d", nstr.x, nstr.y); /* FIXME too narrow */ pr(" %c ", dchr[sect.sct_type].d_mnem); pr("%c", dirstr[sect.sct_del[I_CIVIL] & 0x7]); pr("%c", dirstr[sect.sct_del[I_MILIT] & 0x7]); pr("%c", dirstr[sect.sct_del[I_UW] & 0x7]); pr("%c", dirstr[sect.sct_del[I_FOOD] & 0x7]); pr("%c", dirstr[sect.sct_del[I_SHELL] & 0x7]); pr("%c", dirstr[sect.sct_del[I_GUN] & 0x7]); pr("%c", dirstr[sect.sct_del[I_PETROL] & 0x7]); pr("%c", dirstr[sect.sct_del[I_IRON] & 0x7]); pr("%c", dirstr[sect.sct_del[I_DUST] & 0x7]); pr("%c", dirstr[sect.sct_del[I_BAR] & 0x7]); pr("%c", dirstr[sect.sct_del[I_OIL] & 0x7]); pr("%c", dirstr[sect.sct_del[I_LCM] & 0x7]); pr("%c", dirstr[sect.sct_del[I_HCM] & 0x7]); pr("%c", dirstr[sect.sct_del[I_RAD] & 0x7]); pr("%4d", sect.sct_del[I_CIVIL] & ~0x7); pr("%4d", sect.sct_del[I_MILIT] & ~0x7); pr("%4d", sect.sct_del[I_UW] & ~0x7); pr("%4d", sect.sct_del[I_FOOD] & ~0x7); pr("%4d", sect.sct_del[I_SHELL] & ~0x7); pr("%4d", sect.sct_del[I_GUN] & ~0x7); pr("%4d", sect.sct_del[I_PETROL] & ~0x7); pr("%4d", sect.sct_del[I_IRON] & ~0x7); pr("%4d", sect.sct_del[I_DUST] & ~0x7); pr("%4d", sect.sct_del[I_BAR] & ~0x7); pr("%4d", sect.sct_del[I_OIL] & ~0x7); pr("%4d", sect.sct_del[I_LCM] & ~0x7); pr("%4d", sect.sct_del[I_HCM] & ~0x7); pr("%4d", sect.sct_del[I_RAD] & ~0x7); pr("\n"); } if (nsect == 0) { if (player->argp[1]) pr("%s: No sector(s)\n", player->argp[1]); else pr("%s: No sector(s)\n", ""); return RET_FAIL; } else pr("%d sector%s\n", nsect, splur(nsect)); return RET_OK; }
int grin(void) { struct nstr_sect nstr; struct sctstr sect; char *p; int prd, i, n, qty; char buf[1024]; double grind_eff = 0.8; struct pchrstr *pp; i_type ctype; unsigned camt; prd = dchr[SCT_BANK].d_prd; if (prd < 0 || pchr[prd].p_type < 0) { pr("Grinding is disabled.\n"); return RET_FAIL; } pp = &pchr[prd]; if (!(p = getstarg(player->argp[1], "Sectors? ", buf))) return RET_SYN; if (!snxtsct(&nstr, p)) return RET_SYN; p = getstarg(player->argp[2], "amount : ", buf); if (!p || !*p) return RET_SYN; qty = atoi(p); if (qty < 0) return RET_SYN; while (nxtsct(&nstr, §)) { if (!player->owner) continue; if (sect.sct_effic < 60 || sect.sct_own != player->cnum) continue; /* materials limit */ n = MIN(qty, sect.sct_item[pp->p_type]); /* work limit */ n = MIN(n, sect.sct_avail / 5); /* space limit */ for (i = 0; i < MAXPRCON; i++) { ctype = pp->p_ctype[i]; camt = pp->p_camt[i]; if (!camt) continue; if (CANT_HAPPEN(ctype <= I_NONE || ctype > I_MAX)) continue; n = MIN(n, (double)(ITEM_MAX - sect.sct_item[ctype]) / (camt * grind_eff)); } if (n > 0) { pr("%d bars ground up in %s\n", n, xyas(sect.sct_x, sect.sct_y, player->cnum)); sect.sct_item[I_BAR] -= n; for (i = 0; i < MAXPRCON; i++) { ctype = pp->p_ctype[i]; camt = pp->p_camt[i]; if (!camt) continue; if (CANT_HAPPEN(ctype <= I_NONE || ctype > I_MAX)) continue; sect.sct_item[ctype] += n * camt * grind_eff; } sect.sct_avail -= n * 5; putsect(§); } } return RET_OK; }