diff --git a/include/journal.h b/include/journal.h index d9ae835e..d2029d30 100644 --- a/include/journal.h +++ b/include/journal.h @@ -34,13 +34,17 @@ #ifndef JOURNAL_H #define JOURNAL_H +struct player; /* FIXME temporary hack */ + int journal_startup(void); void journal_shutdown(void); int journal_reopen(void); void journal_login(void); void journal_logout(void); void journal_prng(unsigned); +void journal_output(struct player *, int, char *); void journal_input(char *); +void journal_command(char *); void journal_update(int); #endif diff --git a/info/Hvy-Plastic.t b/info/Hvy-Plastic.t new file mode 100644 index 00000000..b1aea5d7 --- /dev/null +++ b/info/Hvy-Plastic.t @@ -0,0 +1,54 @@ +.TH Concept "Hvy-Plastic" +.NA Hvy-Plastic "Special rules for Hvy Plastic 2" +.LV Basic +.s1 +Ship types are customized. Better check show for the details. +.s1 +Dreadnoughts are more heavily armored. Frigates are more fragile. +.s1 +More ships can carry choppers. Some ships are not ideal for this, and +this is reflected by the lack of large petrol and shell storage. +.s1 +Land unit types are heavily customized. Better check show for the +details. Non-mechanized units are slower and more vulnerable, +artillery firing ranges differ, few units are light (but troop +transports and landing ships can carry non-light units). +.s1 +Planes are tweaked somewhat. show is your friend. +.s1 +Nukes are on sale, but nuclear plants are not. Did I mention the show +command? +.s1 +Infrastructure is disabled. +.s1 +Fortresses cost maintenance, like capitals. +.s1 +Your refineries make less petrol from each barrel of oil than usual. +.s1 +Natural resources gold, oil and uran deplete much slower than usual. +A 100% gold resource contains 2500d, a 100% oil resource contains +2500o, and a 100% uranium resource contains 500u. Fully depleting a +sector will take you several updates, and a small fraction of the +resource contents will be lost. +.s1 +Gold in mountains does not deplete at all. +.s1 +Oil production does not depend on tech; you don't have to micro-manage +to conserve oil. +.s1 +Server time is in UTC, which means there will be no daylight savings +time. +.s1 +Missed updates due to server problems will be forced if caught within +15 minutes of planned update time or skipped otherwise. +.s1 +Everything you do in this game is logged by the deities for their own +nefarious purposes. However, the logs are treated confidentially. +.s1 +Make the deity laugh and get up to 5 gold bars. +.s1 +Source code and configuration is available from +.br +http://www.pond.sub.org/~armbru/empire/hvy-plastic-2/ +.s1 +.SA "Introduction, Server, show" diff --git a/src/lib/commands/navi.c b/src/lib/commands/navi.c index 0f6189cd..745208e6 100644 --- a/src/lib/commands/navi.c +++ b/src/lib/commands/navi.c @@ -244,8 +244,8 @@ do_unit_move(struct emp_qelem *ulist, int *together, skip = 1; continue; case 'd': - if (ac == 2) { - player->argp[2] = player->argp[1]; + if (ac < 3) { + player->argp[2] = ac < 2 ? "1" : player->argp[1]; sprintf(dp, "%d", leader->uid); player->argp[1] = dp; } @@ -253,6 +253,7 @@ do_unit_move(struct emp_qelem *ulist, int *together, mine(); else landmine(); + stopping = 1; skip = 1; player->btused++; continue; diff --git a/src/lib/commands/torp.c b/src/lib/commands/torp.c index 22b24d07..3ba4fd3b 100644 --- a/src/lib/commands/torp.c +++ b/src/lib/commands/torp.c @@ -319,7 +319,7 @@ fire_torp(struct shpstr *sp, struct shpstr *targ, int ntargets) if (mchr[(int)sp->shp_type].m_flags & M_SUB) nreport(targ->shp_own, N_TORP_SHIP, 0, 1); else - nreport(targ->shp_own, N_SHIP_TORP, player->cnum, 1); + nreport(targ->shp_own, N_SHIP_TORP, sp->shp_own, 1); } else { pr("Missed!\n"); if (sp->shp_own != 0) diff --git a/src/lib/empthread/io.c b/src/lib/empthread/io.c index 5f320259..67c60520 100644 --- a/src/lib/empthread/io.c +++ b/src/lib/empthread/io.c @@ -250,8 +250,11 @@ io_output_if_queue_long(struct iop *iop, int wait) if (CANT_HAPPEN(iop->last_out > len)) iop->last_out = 0; - if (len - iop->last_out < iop->bufsize) + if (len - iop->last_out < iop->bufsize) { + if (wait) + ef_make_stale(); return 0; + } return io_output(iop, wait); } diff --git a/src/lib/player/dispatch.c b/src/lib/player/dispatch.c index f5fae829..0ee31a87 100644 --- a/src/lib/player/dispatch.c +++ b/src/lib/player/dispatch.c @@ -38,6 +38,7 @@ #include "com.h" #include "empio.h" #include "file.h" +#include "journal.h" #include "match.h" #include "misc.h" #include "nat.h" @@ -94,6 +95,7 @@ dispatch(char *buf, char *redir) uprnf(buf); pr("\n"); } + journal_command(command->c_form); switch (command->c_addr()) { case RET_OK: player->btused += command->c_cost; diff --git a/src/lib/player/empmod.c b/src/lib/player/empmod.c index fe75b408..b9ec9d6a 100644 --- a/src/lib/player/empmod.c +++ b/src/lib/player/empmod.c @@ -141,7 +141,7 @@ struct cmndstr player_coms[] = { 1, load, C_MOD, NORM + CAP}, {"lookout ", 1, look, 0, NORM + CAP}, {"lost", 0, lost, 0, NORM}, - {"lradar ", 1, lrad, 0, NORM + CAP}, + {"lradar ", 1, lrad, C_MOD, NORM + CAP}, {"lretreat [i|h|b|c]", 1, lretr, C_MOD, NORM + CAP}, {"lstat ", 0, lsta, C_MOD, NORM}, @@ -176,7 +176,7 @@ struct cmndstr player_coms[] = { {"origin ", 1, orig, C_MOD, NORM}, {"paradrop ", 3, para, C_MOD, NORM + MONEY + CAP}, - {"path ", 0, path, 0, NORM}, + {"path ", 0, path, C_MOD, NORM}, {"payoff ", 0, payo, C_MOD, NORM}, {"pbmap [s|l|n|p|r|t|*|h]", 0, map, C_MOD, NORM}, {"pboard ", 3, pboa, C_MOD, NORM + MONEY + CAP}, @@ -192,7 +192,7 @@ struct cmndstr player_coms[] = { {"pstat ", 0, pstat, 0, NORM}, {"qorder ", 0, qorde, C_MOD, NORM + CAP}, {"quit", 0, quit, 0, VIS}, - {"radar ", 1, rada, 0, NORM + CAP}, + {"radar ", 1, rada, C_MOD, NORM + CAP}, {"range ", 1, range, C_MOD, NORM + CAP}, {"read [yes|no|]", 0, rea, C_MOD, VIS}, {"realm []", 0, real, C_MOD, NORM}, @@ -208,17 +208,17 @@ struct cmndstr player_coms[] = { {"resource ", 0, reso, 0, NORM}, {"retreat [i|t|s|h|b|d|u|c]", 1, retr, C_MOD, NORM + CAP}, - {"route ", 1, rout, 0, NORM}, + {"route ", 1, rout, C_MOD, NORM}, {"sabotage ", 1, sabo, C_MOD, NORM + MONEY + CAP}, {"sail ", 1, sail, C_MOD, NORM + CAP}, {"satellite [ [?cond&cond&...]]", - 1, sate, 0, NORM + MONEY + CAP}, + 1, sate, C_MOD, NORM + MONEY + CAP}, {"sbmap [s|l|n|p|r|t|*|h]", 0, map, C_MOD, NORM}, {"scrap ", 2, scra, C_MOD, NORM + MONEY + CAP}, {"scuttle ", 5, scut, C_MOD, NORM + CAP}, {"sdump []", 0, sdump, 0, NORM}, - {"sect ", 0, sct, 0, NORM}, + {"sect ", 0, sct, C_MOD, NORM}, {"sell ", 1, sell, C_MOD, NORM + CAP}, {"set ", 1, set, C_MOD, NORM + CAP}, @@ -245,7 +245,7 @@ struct cmndstr player_coms[] = { {"stop ", 1, stop, C_MOD, NORM + CAP}, {"strength ", 1, stre, C_MOD, NORM}, {"supply ", 1, supp, C_MOD, NORM + CAP}, - {"survey ", 0, surv, 0, NORM + CAP}, + {"survey ", 0, surv, C_MOD, NORM + CAP}, {"swapsector ", 0, swaps, C_MOD, GOD}, {"sweep ", 3, reco, C_MOD, NORM + MONEY + CAP}, diff --git a/src/lib/subs/journal.c b/src/lib/subs/journal.c index c0852144..78f1b49d 100644 --- a/src/lib/subs/journal.c +++ b/src/lib/subs/journal.c @@ -44,7 +44,9 @@ * prng NAME SEED * login CNUM HOSTADDR USER * logout CNUM + * command NAME * input INPUT + * output THREAD ID OUTPUT * update ETU */ @@ -67,6 +69,7 @@ static FILE *journal; static void journal_entry(char *fmt, ...) ATTRIBUTE((format (printf, 1, 2))); +static void journal_output_1(struct player *, int, char *, char *, int); static FILE * journal_open(void) @@ -98,7 +101,8 @@ journal_entry(char *fmt, ...) fprintf(journal, "\\%03o", *p); } fputs("\n", journal); - fflush(journal); + if (fmt[0] != 'o') /* FIXME disgusting hack */ + fflush(journal); if (ferror(journal)) { logerror("Error writing journal (%s)", strerror(errno)); clearerr(journal); @@ -167,12 +171,57 @@ journal_logout(void) journal_entry("logout %d", player->cnum); } +void +journal_output(struct player *pl, int id, char *output) +{ + static char buf[1024]; + static struct player *bpl; + static int bid; + char *s, *e; + + if (keep_journal < 2) + return; + + if (buf[0] && (pl != bpl && id != bid)) { + journal_output_1(bpl, bid, buf, "", -1); + buf[0] = 0; + } + + for (s = output; (e = strchr(s, '\n')); s = e + 1) { + journal_output_1(pl, id, buf, s, (int)(e + 1 - s)); + buf[0] = 0; + } + if (strlen(buf) + strlen(s) < 1024) { + strcpy(buf + strlen(buf), s); + bpl = pl; + bid = id; + } else { + journal_output_1(pl, id, buf, s, -1); + buf[0] = 0; + } +} + +static void +journal_output_1(struct player *pl, int id, + char *buf1, char *buf2, int buf2prec) +{ + journal_entry("output %s %d %s%.*s", + empth_name(empth_self()), id, buf1, buf2prec, buf2); +} + void journal_input(char *input) { journal_entry("input %s", input); } +void +journal_command(char *cmd) +{ + char *eptr = strchr(cmd, ' '); + journal_entry("command %.*s", eptr ? (int)(eptr - cmd) : -1, cmd); +} + void journal_update(int etu) { diff --git a/src/lib/subs/lndsub.c b/src/lib/subs/lndsub.c index a19e53dc..a5808e7c 100644 --- a/src/lib/subs/lndsub.c +++ b/src/lib/subs/lndsub.c @@ -862,7 +862,7 @@ lnd_hit_mine(struct lndstr *lp) nreport(lp->lnd_own, N_LHIT_MINE, 0, 1); m = MINE_LDAMAGE(); - if (lchr[lp->lnd_uid].l_flags & L_ENGINEER) + if (lchr[lp->lnd_type].l_flags & L_ENGINEER) m /= 2; landdamage(lp, m); diff --git a/src/lib/subs/mslsub.c b/src/lib/subs/mslsub.c index fb5a3f72..1e78e443 100644 --- a/src/lib/subs/mslsub.c +++ b/src/lib/subs/mslsub.c @@ -59,6 +59,7 @@ msl_launch(struct plnstr *pp, int type, char *what, coord x, coord y, natid victim, int *sublaunchp) { struct shpstr ship; + struct nukstr nuke; struct sctstr sect; int sublaunch = 0; char *from; @@ -93,6 +94,11 @@ msl_launch(struct plnstr *pp, int type, char *what, coord x, coord y, if (chance((0.05 + (100 - pp->pln_effic) / 100.0) * (1 - techfact(pp->pln_tech, 1.0)))) { mpr(pp->pln_own, "KABOOOOM! Missile explodes %s!\n", from); + if (getnuke(nuk_on_plane(pp), &nuke)) { + pr("%s lost!\n", prnuke(&nuke)); + nuke.nuk_effic = 0; + putnuke(nuke.nuk_uid, &nuke); + } if (chance(0.33)) { dam = pln_damage(pp, 'p', 1) / 2; if (pp->pln_ship >= 0) { diff --git a/src/lib/subs/plnsub.c b/src/lib/subs/plnsub.c index 597443bd..5e11ec05 100644 --- a/src/lib/subs/plnsub.c +++ b/src/lib/subs/plnsub.c @@ -988,7 +988,7 @@ pln_damage(struct plnstr *pp, char type, int noisy) int effective = 1; int pinbomber = 0; - if (CANT_HAPPEN(nuk_on_plane(pp) >= 0)) /* FIXME check uses! */ + if (CANT_HAPPEN(nuk_on_plane(pp) >= 0)) return 0; load = pln_load(pp); diff --git a/src/lib/subs/pr.c b/src/lib/subs/pr.c index 1698d4c4..358bdc1f 100644 --- a/src/lib/subs/pr.c +++ b/src/lib/subs/pr.c @@ -56,6 +56,7 @@ #include "com.h" #include "empio.h" #include "file.h" +#include "journal.h" #include "misc.h" #include "nat.h" #include "player.h" @@ -124,6 +125,7 @@ pr_id(struct player *p, int id, char *format, ...) if (p->curid >= 0) { io_puts(p->iop, "\n"); + journal_output(p, p->curid, "\n"); p->curid = -1; } va_start(ap, format); @@ -242,6 +244,8 @@ pr_player(struct player *pl, int id, char *buf) } } + journal_output(pl, id, buf); + if (player == pl) { while (io_output_if_queue_long(pl->iop, pl->may_sleep == PLAYER_SLEEP_FREELY) > 0) @@ -298,6 +302,8 @@ upr_player(struct player *pl, int id, char *buf) } } + journal_output(pl, id, buf); + if (player == pl) { while (io_output_if_queue_long(pl->iop, pl->may_sleep == PLAYER_SLEEP_FREELY) > 0) diff --git a/src/lib/subs/shpsub.c b/src/lib/subs/shpsub.c index 465b0d67..fb44fe2c 100644 --- a/src/lib/subs/shpsub.c +++ b/src/lib/subs/shpsub.c @@ -354,6 +354,8 @@ shp_count(struct emp_qelem *list, int wantflags, int nowantflags, static void shp_damage_one(struct ulist *mlp, int dam) { + /* ship might have changed (launched interceptors, missile defense) */ + getship(mlp->unit.ship.shp_uid, &mlp->unit.ship); shipdamage(&mlp->unit.ship, dam); putship(mlp->unit.ship.shp_uid, &mlp->unit.ship); if (!mlp->unit.ship.shp_own) { @@ -649,11 +651,12 @@ shp_mission_interdiction(struct emp_qelem *list, coord x, coord y, char *what = subs ? "subs" : "ships"; int wantflags = subs ? M_SUB : 0; int nowantflags = subs ? 0 : M_SUB; + int mission = subs ? MI_SINTERDICT : MI_INTERDICT; int dam; dam = unit_interdict(x, y, victim, what, shp_easiest_target(list, wantflags, nowantflags), - MI_INTERDICT); + mission); if (dam >= 0) shp_damage(list, dam, wantflags, nowantflags, x, y); return dam >= 0; @@ -705,7 +708,7 @@ shp_hit_mine(struct shpstr *sp) nreport(sp->shp_own, N_HIT_MINE, 0, 1); m = MINE_DAMAGE(); - if (mchr[sp->shp_uid].m_flags & M_SWEEP) + if (mchr[sp->shp_type].m_flags & M_SWEEP) m /= 2.0; shipdamage(sp, ldround(m, 1)); diff --git a/src/util/fairland.c b/src/util/fairland.c index 2628f9d7..e95b33d3 100644 --- a/src/util/fairland.c +++ b/src/util/fairland.c @@ -420,10 +420,9 @@ parse_args(int argc, char *argv[]) exit(1); } if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) { - puts("fairland: error -- world not big enough to fit continents."); - puts("arguments must satisfy:"); + puts("fairland: warning -- world might be too small to fit continents."); + puts("arguments should satisfy:"); puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y"); - exit(1); } } @@ -821,7 +820,7 @@ grow_islands(void) secs = 0; if (!place_island(c, &x, &y)) return; - isiz = 1 + rnd(2 * is - 1); + isiz = 1 + rnd(is) + rnd(is); do { ++secs; find_coast(c); @@ -1092,6 +1091,7 @@ write_sects(void) sct->sct_type = SCT_MOUNT; sct->sct_elev = total; sct->sct_newtype = sct->sct_type; + sct->sct_dterr = own[sct->sct_x][y] + 1; if (ORE) add_resources(sct); }