From 83fcc79bca0d085315dcd1bd39ea3b6742671ea7 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 29 Jul 2008 07:48:28 -0400 Subject: [PATCH 01/22] New journal event command Redundant information, but makes the journal easier to read. The redundancy might help making a journal replay tool robust. Put it in Hvy Metal II now to gather some real data. --- include/journal.h | 1 + src/lib/player/dispatch.c | 2 ++ src/lib/subs/journal.c | 8 ++++++++ 3 files changed, 11 insertions(+) diff --git a/include/journal.h b/include/journal.h index d9ae835e..f5fcd93c 100644 --- a/include/journal.h +++ b/include/journal.h @@ -41,6 +41,7 @@ void journal_login(void); void journal_logout(void); void journal_prng(unsigned); void journal_input(char *); +void journal_command(char *); void journal_update(int); #endif 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/subs/journal.c b/src/lib/subs/journal.c index c0852144..245c2456 100644 --- a/src/lib/subs/journal.c +++ b/src/lib/subs/journal.c @@ -44,6 +44,7 @@ * prng NAME SEED * login CNUM HOSTADDR USER * logout CNUM + * command NAME * input INPUT * update ETU */ @@ -173,6 +174,13 @@ 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) { From 221471af6f3b16bac197ec5972b2770157f62176 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 29 Jul 2008 20:38:48 -0400 Subject: [PATCH 02/22] New journal event output To enable, set econfig key keep_journal to at least 2. Output events are *not* flushed to disk immediately. Put it in Hvy Metal II now to gather real data for future testing of a journal replay tool. --- include/journal.h | 3 +++ src/lib/subs/journal.c | 15 ++++++++++++++- src/lib/subs/pr.c | 5 +++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/include/journal.h b/include/journal.h index f5fcd93c..d2029d30 100644 --- a/include/journal.h +++ b/include/journal.h @@ -34,12 +34,15 @@ #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); diff --git a/src/lib/subs/journal.c b/src/lib/subs/journal.c index 245c2456..56361e97 100644 --- a/src/lib/subs/journal.c +++ b/src/lib/subs/journal.c @@ -46,6 +46,7 @@ * logout CNUM * command NAME * input INPUT + * output THREAD ID OUTPUT * update ETU */ @@ -99,7 +100,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); @@ -168,6 +170,17 @@ journal_logout(void) journal_entry("logout %d", player->cnum); } +void +journal_output(struct player *pl, int id, char *output) +{ + if (keep_journal < 2) + return; + if (pl && pl->state == PS_PLAYING) + journal_entry("output %d %d %s", pl->cnum, id, output); + else + journal_entry("output %p %d %s", pl, id, output); +} + void journal_input(char *input) { diff --git a/src/lib/subs/pr.c b/src/lib/subs/pr.c index 1698d4c4..a5c2a20f 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" @@ -242,6 +243,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 +301,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) From 6be2e3f8c51a4669c584875fb2e6d69f8a5b5cc2 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 30 Jul 2008 08:26:34 -0400 Subject: [PATCH 03/22] Journal output lines instead of chunks Output often arrives in chunks other than lines. Hard to read in the journal. Delay journalling until we got a full line or our buffer is exhausted. This is less precise, but it'll do for now. --- include/journal.h | 2 +- src/lib/subs/journal.c | 28 +++++++++++++++++++++++++--- src/lib/subs/pr.c | 6 ++++-- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/include/journal.h b/include/journal.h index d2029d30..d2ee2159 100644 --- a/include/journal.h +++ b/include/journal.h @@ -42,7 +42,7 @@ 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_output(struct player *, char *); void journal_input(char *); void journal_command(char *); void journal_update(int); diff --git a/src/lib/subs/journal.c b/src/lib/subs/journal.c index 56361e97..3fafb6bf 100644 --- a/src/lib/subs/journal.c +++ b/src/lib/subs/journal.c @@ -69,6 +69,7 @@ static FILE *journal; static void journal_entry(char *fmt, ...) ATTRIBUTE((format (printf, 1, 2))); +static void journal_output_1(struct player *, char *, char *, int); static FILE * journal_open(void) @@ -171,14 +172,35 @@ journal_logout(void) } void -journal_output(struct player *pl, int id, char *output) +journal_output(struct player *pl, char *output) { + static char buf[1024]; + char *s, *e; + if (keep_journal < 2) return; + + for (s = output; (e = strchr(s, '\n')); s = e + 1) { + journal_output_1(pl, buf, s, (int)(e + 1 - s)); + buf[0] = 0; + } + if (strlen(buf) + strlen(s) < 1024) + strcpy(buf + strlen(buf), s); + else { + journal_output_1(pl, buf, s, -1); + buf[0] = 0; + } +} + +void +journal_output_1(struct player *pl, char *buf1, char *buf2, int buf2prec) +{ if (pl && pl->state == PS_PLAYING) - journal_entry("output %d %d %s", pl->cnum, id, output); + journal_entry("output %d %s%.*s", + pl->cnum, buf1, buf2prec, buf2); else - journal_entry("output %p %d %s", pl, id, output); + journal_entry("output %p %s%.*s", + pl, buf1, buf2prec, buf2); } void diff --git a/src/lib/subs/pr.c b/src/lib/subs/pr.c index a5c2a20f..ff56f893 100644 --- a/src/lib/subs/pr.c +++ b/src/lib/subs/pr.c @@ -125,6 +125,7 @@ pr_id(struct player *p, int id, char *format, ...) if (p->curid >= 0) { io_puts(p->iop, "\n"); + journal_output(p, "\n"); p->curid = -1; } va_start(ap, format); @@ -243,7 +244,7 @@ pr_player(struct player *pl, int id, char *buf) } } - journal_output(pl, id, buf); + journal_output(pl, buf); if (player == pl) { while (io_output_if_queue_long(pl->iop, @@ -301,7 +302,7 @@ upr_player(struct player *pl, int id, char *buf) } } - journal_output(pl, id, buf); + journal_output(pl, buf); if (player == pl) { while (io_output_if_queue_long(pl->iop, @@ -329,6 +330,7 @@ outid(struct player *pl, int n) buf[1] = ' '; buf[2] = '\0'; io_puts(pl->iop, buf); + journal_output(pl, buf); pl->curid = n; } From 1cd3179b82ffe9bdb3ecf7106d435326d909b35d Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 2 Aug 2008 09:04:16 -0400 Subject: [PATCH 04/22] Fix journalling of output ids --- include/journal.h | 2 +- src/lib/subs/journal.c | 34 ++++++++++++++++++++++------------ src/lib/subs/pr.c | 7 +++---- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/include/journal.h b/include/journal.h index d2ee2159..d2029d30 100644 --- a/include/journal.h +++ b/include/journal.h @@ -42,7 +42,7 @@ int journal_reopen(void); void journal_login(void); void journal_logout(void); void journal_prng(unsigned); -void journal_output(struct player *, char *); +void journal_output(struct player *, int, char *); void journal_input(char *); void journal_command(char *); void journal_update(int); diff --git a/src/lib/subs/journal.c b/src/lib/subs/journal.c index 3fafb6bf..e5354402 100644 --- a/src/lib/subs/journal.c +++ b/src/lib/subs/journal.c @@ -69,7 +69,7 @@ static FILE *journal; static void journal_entry(char *fmt, ...) ATTRIBUTE((format (printf, 1, 2))); -static void journal_output_1(struct player *, char *, char *, int); +static void journal_output_1(struct player *, int, char *, char *, int); static FILE * journal_open(void) @@ -172,35 +172,45 @@ journal_logout(void) } void -journal_output(struct player *pl, char *output) +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; - for (s = output; (e = strchr(s, '\n')); s = e + 1) { - journal_output_1(pl, buf, s, (int)(e + 1 - s)); + if (buf[0] && (pl != bpl && id != bid)) { + journal_output_1(bpl, bid, buf, "", -1); buf[0] = 0; } - if (strlen(buf) + strlen(s) < 1024) + + 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); - else { - journal_output_1(pl, buf, s, -1); + bpl = pl; + bid = id; + } else { + journal_output_1(pl, id, buf, s, -1); buf[0] = 0; } } void -journal_output_1(struct player *pl, char *buf1, char *buf2, int buf2prec) +journal_output_1(struct player *pl, int id, + char *buf1, char *buf2, int buf2prec) { if (pl && pl->state == PS_PLAYING) - journal_entry("output %d %s%.*s", - pl->cnum, buf1, buf2prec, buf2); + journal_entry("output %d %d %s%.*s", + pl->cnum, id, buf1, buf2prec, buf2); else - journal_entry("output %p %s%.*s", - pl, buf1, buf2prec, buf2); + journal_entry("output %p %d %s%.*s", + pl, id, buf1, buf2prec, buf2); } void diff --git a/src/lib/subs/pr.c b/src/lib/subs/pr.c index ff56f893..358bdc1f 100644 --- a/src/lib/subs/pr.c +++ b/src/lib/subs/pr.c @@ -125,7 +125,7 @@ pr_id(struct player *p, int id, char *format, ...) if (p->curid >= 0) { io_puts(p->iop, "\n"); - journal_output(p, "\n"); + journal_output(p, p->curid, "\n"); p->curid = -1; } va_start(ap, format); @@ -244,7 +244,7 @@ pr_player(struct player *pl, int id, char *buf) } } - journal_output(pl, buf); + journal_output(pl, id, buf); if (player == pl) { while (io_output_if_queue_long(pl->iop, @@ -302,7 +302,7 @@ upr_player(struct player *pl, int id, char *buf) } } - journal_output(pl, buf); + journal_output(pl, id, buf); if (player == pl) { while (io_output_if_queue_long(pl->iop, @@ -330,7 +330,6 @@ outid(struct player *pl, int n) buf[1] = ' '; buf[2] = '\0'; io_puts(pl->iop, buf); - journal_output(pl, buf); pl->curid = n; } From d1bde67589cd40ae1b3ad91ec2fedcfa3470d893 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 17 Mar 2009 20:19:49 +0100 Subject: [PATCH 05/22] Fix recipient thread in output journal Output journaling was cherry-picked from Hvy Metal II. However, how threads are identified in the journal changed since then. journal_output_1() needs updating for that. --- src/lib/subs/journal.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/lib/subs/journal.c b/src/lib/subs/journal.c index e5354402..78f1b49d 100644 --- a/src/lib/subs/journal.c +++ b/src/lib/subs/journal.c @@ -201,16 +201,12 @@ journal_output(struct player *pl, int id, char *output) } } -void +static void journal_output_1(struct player *pl, int id, char *buf1, char *buf2, int buf2prec) { - if (pl && pl->state == PS_PLAYING) - journal_entry("output %d %d %s%.*s", - pl->cnum, id, buf1, buf2prec, buf2); - else - journal_entry("output %p %d %s%.*s", - pl, id, buf1, buf2prec, buf2); + journal_entry("output %s %d %s%.*s", + empth_name(empth_self()), id, buf1, buf2prec, buf2); } void From 880f3856d10ec3cc63213dcf7729055eb37dcc11 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 5 Apr 2008 16:09:24 +0200 Subject: [PATCH 06/22] Make fairland record the island number in the deity territory Can be useful for deities when further customizing their game setup. --- src/util/fairland.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/fairland.c b/src/util/fairland.c index 2628f9d7..8f5f454b 100644 --- a/src/util/fairland.c +++ b/src/util/fairland.c @@ -1092,6 +1092,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); } From 29d2f5ccfe4d629151c4843f994ac8e9fcc74f58 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 9 Mar 2009 21:22:03 +0100 Subject: [PATCH 07/22] Change fairland island size probability distribution Island size is randomly chosen from the interval [1..2*is+1], with expected value is. Use two dice to roll the size instead of one. This makes extreme sizes much less likely. --- src/util/fairland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/fairland.c b/src/util/fairland.c index 8f5f454b..25518366 100644 --- a/src/util/fairland.c +++ b/src/util/fairland.c @@ -821,7 +821,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); From 3def3727f85fca1d9d8cb11b63d13a3459725be1 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 23 Feb 2009 21:56:49 +0100 Subject: [PATCH 08/22] New info Hvy-Plastic --- info/Hvy-Plastic.t | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 info/Hvy-Plastic.t diff --git a/info/Hvy-Plastic.t b/info/Hvy-Plastic.t new file mode 100644 index 00000000..fa3f6a05 --- /dev/null +++ b/info/Hvy-Plastic.t @@ -0,0 +1,49 @@ +.TH Concept "Hvy-Plastic" +.NA Hvy-Plastic "Special rules for Hvy Plastic" +.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 +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 +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.html +.s1 +.SA "Introduction, Server, show" From 48b72af69ac1745d5597ecab86b53dd90c86cb7c Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 16 Mar 2009 19:50:08 +0100 Subject: [PATCH 09/22] Document server time in info Hvy-Plastic --- info/Hvy-Plastic.t | 3 +++ 1 file changed, 3 insertions(+) diff --git a/info/Hvy-Plastic.t b/info/Hvy-Plastic.t index fa3f6a05..263e1cc7 100644 --- a/info/Hvy-Plastic.t +++ b/info/Hvy-Plastic.t @@ -34,6 +34,9 @@ Gold in mountains does not deplete at all. 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 From 1227140c6740b0e37ee5c590b77955bef880a6e1 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 10 Jan 2010 12:28:44 +0100 Subject: [PATCH 10/22] Update game name and URL for Hvy Plastic 2 in info Hvy-Plastic --- info/Hvy-Plastic.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/info/Hvy-Plastic.t b/info/Hvy-Plastic.t index 263e1cc7..92b635ff 100644 --- a/info/Hvy-Plastic.t +++ b/info/Hvy-Plastic.t @@ -1,5 +1,5 @@ .TH Concept "Hvy-Plastic" -.NA Hvy-Plastic "Special rules for Hvy Plastic" +.NA Hvy-Plastic "Special rules for Hvy Plastic 2" .LV Basic .s1 Ship types are customized. Better check show for the details. @@ -47,6 +47,6 @@ 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.html +http://www.pond.sub.org/~armbru/empire/hvy-plastic-2/ .s1 .SA "Introduction, Server, show" From aab337d2e3f6565b894aa6f9152f15d9f0482e9d Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 10 Jan 2010 12:31:44 +0100 Subject: [PATCH 11/22] Document fortress maintenance cost in info Hvy-Plastic --- info/Hvy-Plastic.t | 2 ++ 1 file changed, 2 insertions(+) diff --git a/info/Hvy-Plastic.t b/info/Hvy-Plastic.t index 92b635ff..b1aea5d7 100644 --- a/info/Hvy-Plastic.t +++ b/info/Hvy-Plastic.t @@ -21,6 +21,8 @@ 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. From 065881143ea47adf235a82d11a6db8801a71e71f Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 6 Feb 2010 21:36:21 +0100 Subject: [PATCH 12/22] Change fairland not to reject small worlds without trying Instead, print a warning and try. It may well work, and when it doesn't, it fails cleanly. (cherry picked from commit de81e4e20a40489fa2074060b4220ebb761025c8) --- src/util/fairland.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/util/fairland.c b/src/util/fairland.c index 25518366..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); } } From 069fb10409b6dd06495f195e771bccbc1bb58e8e Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 21 Feb 2010 18:44:16 +0100 Subject: [PATCH 13/22] Generation numbers didn't catch all potential yields on output io_output_if_queue_long() called ef_make_stale() only for long queues. Missed in commit 2fa5f652, v4.3.24. (cherry picked from commit a38c47a22c63b0e31874138548e45b58bfb636bf) --- src/lib/empthread/io.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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); } From 1f2865387a64a294e51e6a83e975488ca7c3a410 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 25 Feb 2010 07:07:28 +0100 Subject: [PATCH 14/22] Fix unsafe use of shared buffers in commands drawing maps Maps are generally drawn into static scratch buffers. Each command has its own buffers. Static scratch buffers are safe as long as they're never used across yields. Player output can yield unless the command has flag C_MOD set. Commands lradar, path, radar, route, satellite, sect, survey hadn't. If such a command yields while using scratch buffers, another instance of the command can clobber them. Abuse seems tricky, but possible: if a malicious player stalls output just right, a command yields while printing a map from the scratch buffer. It resumes only when the malicious player reads some output. If another player runs the same command before that, it overwrites the same static scratch buffer with its map. The malicious player receives the last such run's map. 4.2.8 fixed the same bug for bmap, lbmap, lmap, map, nmap, pbmap, pmap, sbmap and smap. All were broken in 4.2.0. Except radar maps (lradar and radar) were already broken in Empire 2 for AIX. (cherry picked from commit 8bdb5c5c1b5a672a280664b798687adc158fe3f7) --- src/lib/player/empmod.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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}, From bd07ee186b0e5c8d21cdf3238b71671ef3226d22 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 10 Mar 2010 08:54:06 +0100 Subject: [PATCH 15/22] Interdiction attacked submarines with surface-only weapons shp_mission_interdiction() used MI_INTERDICT instead of MI_SINTERDICT. Broken in commit cd8fe31e, v4.3.24. (cherry picked from commit 2dd97dbd00202643f4c61ba4e6aceb1eecd7797a) --- src/lib/subs/shpsub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/subs/shpsub.c b/src/lib/subs/shpsub.c index 465b0d67..51fe7079 100644 --- a/src/lib/subs/shpsub.c +++ b/src/lib/subs/shpsub.c @@ -649,11 +649,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; From b14edd0f7c8ef6e417fb4be08b1e9d0ca2340648 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 12 Mar 2010 20:39:39 +0100 Subject: [PATCH 16/22] Fix news for torpedo attack's return torpedo When a torpedo attack triggered a return torpedo, the news reported it to be fired by the attacker instead of the defender. (cherry picked from commit bb5abd95e0af72cded1940b2fd9885dca2a465cb) --- src/lib/commands/torp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 7f3f9c67264dc49e3814cde2d693fe73bfd08ea7 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 13 Mar 2010 13:49:36 +0100 Subject: [PATCH 17/22] Nuclear-tipped missile exploding on launch could not damage base Commit a269cdd7 (v4.3.23) removed the nuclear damage. But it left the nuke on the missile, which made pln_damage() oops and return zero damage. Fix by destroying the nuke separately. (cherry picked from commit 876f3424b0bb28efab505722d89b34395ad43ae6) --- src/lib/subs/mslsub.c | 6 ++++++ src/lib/subs/plnsub.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) 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); From 89992611193563b722e08b3e2faa38666c1e1ecf Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 20 Mar 2010 11:24:49 +0100 Subject: [PATCH 18/22] Fix navigate and march not to prompt for number of mines to lay When sub-command 'd' was used without arguments, do_unit_move() failed to supply the second argument to mine(), which duly prompted for it. This contracticted info, and could trigger a generation oops. do_unit_move() reads the ships into a list. It re-reads them when it prompts for sub-commands. shp_nav_one_sector() writes them back when it moves ships. The mine prompt made the list stale. Movement sub-commands before the next prompt for sub-commands wrote back stale ships, triggering a generation oops. Example: "nav 15 dg". Broken when mine-laying was added in commits 2438fe7c, v4.3.7. Same for march, commit 274c8e42, v4.3.7. (cherry picked from commit 45106ab91ffe6193bc90a725e8a07a7a3997f54c) --- src/lib/commands/navi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/commands/navi.c b/src/lib/commands/navi.c index 0f6189cd..0213be25 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; } From 03a9ab2cf6cbe3221c43a8f24836848a422b1735 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 13 Mar 2010 22:47:13 +0100 Subject: [PATCH 19/22] Fix navigate and march not to lay mines free of charge do_unit_move() reads the ships into a list. It re-reads them when it prompts for sub-commands. shp_nav_one_sector() writes them back when it moves ships. Mine-laying (sub-command 'd') updates the minelayer, invalidating the copy in the list. Any movement sub-command before the next prompt for sub-commands wiped out this update, triggering a seno mismatch oops. Happens only if 'd' is used without arguments, because remaining sub-commands are discarded when there are arguments. Broken when mine-laying was added in commits 2438fe7c, v4.3.7. Same for march, commit 274c8e42, v4.3.7. Fix by stopping after 'd' regardless of arguments. (cherry picked from commit 28cc236e1264d57a06dfb89cf43a600ba88d271c) --- src/lib/commands/navi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/commands/navi.c b/src/lib/commands/navi.c index 0213be25..745208e6 100644 --- a/src/lib/commands/navi.c +++ b/src/lib/commands/navi.c @@ -253,6 +253,7 @@ do_unit_move(struct emp_qelem *ulist, int *together, mine(); else landmine(); + stopping = 1; skip = 1; player->btused++; continue; From e0b21266ce96b9c8826b7eac0ea476f73601cc37 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 20 Mar 2010 17:55:56 +0100 Subject: [PATCH 20/22] Fix interdiction not to wipe out target ship updates Ships can expend shells to defend against missiles, in shp_missile_defense(). Any shell use by the target ship got wiped out when shp_missile_interdiction() wrote back the target ship, triggering a seqno mismatch oops. Ships get updated when they launch planes to intercept interdicting planes, in mission_pln_equip(). Any petrol use by the target ship got wiped out when shp_mission_interdiction() wrote back the target ship, triggering a seqno mismatch oops. Fix by re-reading the target ship in shp_damage_one(). This also affects shp_fort_interdiction(), where it is not necessary. A bit inefficient, but let's keep this fix simple. (cherry picked from commit 1d4fea32b845686163b9be79e21ca7ea279357e1) --- src/lib/subs/shpsub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/subs/shpsub.c b/src/lib/subs/shpsub.c index 51fe7079..11353607 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) { From b62025e82c70c6d67f13194db5daeaec070921a0 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 21 Mar 2010 09:26:37 +0100 Subject: [PATCH 21/22] Fix test for capability sweep in shp_hit_mine() Bogus array index, unpredictable result, can crash the server. Broken in commit ef7ea893, v4.3.24. (cherry picked from commit 054eba7a1d5f92d80ac340787cb8d7798a20ec1e) --- src/lib/subs/shpsub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/subs/shpsub.c b/src/lib/subs/shpsub.c index 11353607..fb44fe2c 100644 --- a/src/lib/subs/shpsub.c +++ b/src/lib/subs/shpsub.c @@ -708,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)); From 62b93e56e2e3c821b2c384cf201168ccd5059902 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 7 Apr 2010 23:35:25 +0200 Subject: [PATCH 22/22] Fix test for capability engineer in lnd_hit_mine() Bogus array index, unpredictable result, can crash the server. Broken in commit ef7ea893, v4.3.24. (cherry picked from commit 7506039f1b31eeaddab436831d23fb50c2f9409b) --- src/lib/subs/lndsub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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);