]> git.pond.sub.org Git - empserver/commitdiff
Merge branch 'master' into hvy-metal-2
authorMarkus Armbruster <armbru@pike.pond.sub.org>
Wed, 7 May 2008 08:36:54 +0000 (10:36 +0200)
committerMarkus Armbruster <armbru@pike.pond.sub.org>
Wed, 7 May 2008 08:38:52 +0000 (10:38 +0200)
Merge up to v4.3.14.  No functional change.

54 files changed:
Make.mk
include/commodity.h
include/econfig-spec.h
include/empobj.h
include/file.h
include/game.h
include/land.h
include/loan.h
include/lost.h
include/nat.h
include/news.h
include/nuke.h
include/plane.h
include/prototypes.h
include/sect.h
include/ship.h
include/trade.h
include/treaty.h
info/Hvy-Metal.t [new file with mode: 0644]
info/Options.t
info/Railroad.t [new file with mode: 0644]
info/Unit-types.t
src/lib/commands/add.c
src/lib/commands/buil.c
src/lib/commands/desi.c
src/lib/commands/edit.c
src/lib/commands/mfir.c
src/lib/commands/miss.c
src/lib/commands/sinf.c
src/lib/commands/spy.c
src/lib/commands/swap.c
src/lib/common/file.c
src/lib/common/move.c
src/lib/common/path.c
src/lib/global/nsc.c
src/lib/global/options.c
src/lib/global/sect.config
src/lib/subs/aircombat.c
src/lib/subs/attsub.c
src/lib/subs/bridgefall.c
src/lib/subs/landgun.c
src/lib/subs/lndsub.c
src/lib/subs/mission.c
src/lib/subs/nreport.c
src/lib/subs/nuke.c
src/lib/subs/plane.c
src/lib/subs/retreat.c
src/lib/subs/satmap.c
src/lib/subs/shpsub.c
src/lib/update/age.c
src/lib/update/human.c
src/lib/update/ship.c
src/util/fairland.c
src/util/files.c

diff --git a/Make.mk b/Make.mk
index 97e44e5d831d1bd03ddfc06eb2d7f8f2b6adc851..2698551594b8d54a98de35dbd0c81cd010c5690d 100644 (file)
--- a/Make.mk
+++ b/Make.mk
@@ -284,6 +284,7 @@ ifeq ($(empthread),Windows)
 $(client): src/lib/w32/getopt.o
 endif
 
+$(util): src/lib/common/move.o # FIXME hack for opt_RAILWAYS
 $(util): $(libs)
 
 lib/libas.a: $(filter src/lib/as/%, $(obj))
index c375766196d2632b78a83401439f62113892e66c..d515364e7c8937eefdd4fc6ca646d1b5686803ed 100644 (file)
@@ -44,6 +44,7 @@ struct comstr {
     /* initial part must match struct empobj */
     short ef_type;
     short com_uid;
+    unsigned com_seqno;
     time_t com_timestamp;
     natid com_owner;
     /* end of part matching struct empobj */
index bc4ccc6a9ccc6d3043f65e5d5bffd286c16c0ba7..d426e58a0c36964cb5a1adc15fb8f68cae4ae267 100644 (file)
@@ -161,6 +161,8 @@ EMPCF_OPT("INTERDICT_ATT", opt_INTERDICT_ATT,
     "Interdict post-attack move in")
 EMPCF_OPT("LANDSPIES", opt_LANDSPIES,
     "Enable the land unit type spies")
+EMPCF_OPT("LIMBER", opt_LIMBER,
+    "Artillery requires mobility to start firing")
 EMPCF_OPT("LOANS", opt_LOANS,
     "Allow bailing out of other countries via S&L scandals")
 EMPCF_OPT("LOSE_CONTACT", opt_LOSE_CONTACT,
@@ -179,6 +181,8 @@ EMPCF_OPT("NO_PLAGUE", opt_NO_PLAGUE,
     "Disable plague")
 EMPCF_OPT("PINPOINTMISSILE", opt_PINPOINTMISSILE,
     "Enable marine missiles")
+EMPCF_OPT("RAILWAYS", opt_RAILWAYS,
+    "Highways double as rail")
 EMPCF_OPT("RES_POP", opt_RES_POP,
     "Population is limited by research")
 EMPCF_OPT("SAIL", opt_SAIL,
index 2610c18ee6b1406693d645b90a761fcb9bc10b81..63931c1062c90b1b45ab16c4b678bdcf0dc8faf6 100644 (file)
@@ -57,6 +57,7 @@ struct empobj {
      */
     short ef_type;
     short uid;
+    unsigned seqno;
     time_t timestamp;
     /* end of part matching struct emptypedstr */
     natid own;         /* valid if EFF_OWNER is in table's flags */
index 795177840a35759f4d1073944c27fb0e68df6693..9d724f6587d78415c03b8ebc1e171985854661ec 100644 (file)
@@ -67,6 +67,7 @@ struct empfile {
 struct emptypedstr {
     short ef_type;
     short uid;
+    unsigned seqno;
     time_t timestamp;
 };
 
@@ -187,6 +188,7 @@ extern int ef_close(int);
 extern int ef_flush(int);
 extern void ef_blank(int, int, void *);
 extern int ef_write(int, int, void *);
+extern void ef_set_uid(int, void *, int);
 extern int ef_extend(int, int);
 extern int ef_ensure_space(int, int, int);
 extern int ef_truncate(int, int);
index 8a52509c5313f4a848b2d1ab84149d523fd06c18..1a343c7f9fb6a84c7a6e74176922a6c52b86a8d5 100644 (file)
@@ -40,6 +40,7 @@ struct gamestr {
     /* initial part must match struct empobj */
     short ef_type;
     short game_uid;
+    unsigned game_seqno;
     time_t game_timestamp;
     /* end of part matching struct empobj */
     char game_upd_disable;     /* updates disabled? */
index f3923066f852be019408af186aca14efc6b0cffb..73ca0b8276a5b7b66e99585ece8fb713d8ef7a5b 100644 (file)
@@ -51,6 +51,7 @@ struct lndstr {
     /* initial part must match struct empobj */
     short ef_type;
     short lnd_uid;             /* unit id (land unit) */
+    unsigned lnd_seqno;
     time_t lnd_timestamp;      /* Last time this unit was touched */
     natid lnd_own;             /* owner's country num */
     coord lnd_x;               /* x location in abs coords */
@@ -190,6 +191,7 @@ extern int lnd_hardtarget(struct lndstr *);
 extern int lnd_mar_one_sector(struct emp_qelem *, int, natid, int);
 extern int lnd_support(natid, natid, coord, coord, int);
 extern int lnd_can_attack(struct lndstr *);
+extern void lnd_unlimber(struct lndstr *lp);
 extern int lnd_fortify (struct lndstr *lp, int hard_amt);
 extern void lnd_set_tech(struct lndstr *, int);
 
index 542af6c8399d140b9d812ab4ad42666742fcf576..d18c4d88a6f0a99f45b6d4ab17be3ab1f412f7ef 100644 (file)
@@ -44,6 +44,7 @@ struct lonstr {
     /* initial part must match struct empobj */
     short ef_type;
     short l_uid;
+    unsigned l_seqno;
     time_t l_timestamp;
     /* end of part matching struct empobj */
     natid l_loner;             /* loan shark */
index c371f936c2a962fdcab935b477abaa07c38eb880..1bb930796338f5c403b3564c00b149ac981eebb7 100644 (file)
@@ -41,6 +41,7 @@ struct loststr {
     /* initial part must match struct empobj */
     short ef_type;
     int lost_uid;
+    unsigned lost_seqno;
     time_t lost_timestamp;     /* When it was lost */
     natid lost_owner;          /* Who lost it */
     /* end of part matching struct empobj */
index b2f2bd5f81b8b5df37502cd7c5b9f4f1a314b07f..58b8067fcedab35b219d1b8803735876236fdaa9 100644 (file)
@@ -70,6 +70,7 @@ struct realmstr {
     /* initial part must match struct empobj */
     short ef_type;
     short r_uid;               /* realm table index */
+    unsigned r_seqno;
     time_t r_timestamp;                /* Last time this realm was touched */
     natid r_cnum;              /* country number */
     /* end of part matching struct empobj */
@@ -82,6 +83,7 @@ struct natstr {
     /* initial part must match struct empobj */
     short ef_type;
     short nat_uid;             /* equals nat_cnum */
+    unsigned nat_seqno;
     time_t nat_timestamp;
     natid nat_cnum;            /* our country number */
     /* end of part matching struct empobj */
index c736114444bfedd1d1f33cc4ee53690d7645f10e..5665a92fa223cc77fb562daeb9fe3d59d6f85bfc 100644 (file)
@@ -48,6 +48,7 @@ struct nwsstr {
     /* initial part must match struct empobj */
     short ef_type;
     short nws_uid;
+    unsigned nws_seqno;
     time_t nws_timestamp;
     /* end of part matching struct empobj */
     natid nws_ano;             /* "actor" country # */
index 2f7fcdaa1ac98fedf4df0b7a0660dc8393ed604e..054cdb4c34c507044bc705b52f48dbb8c3823583 100644 (file)
@@ -44,6 +44,7 @@ struct nukstr {
     /* initial part must match struct empobj */
     short ef_type;
     short nuk_uid;
+    unsigned nuk_seqno;
     time_t nuk_timestamp;      /* Last time this nuke was touched */
     natid nuk_own;
     coord nuk_x, nuk_y;                /* current loc of device */
index 2133f3628097b3d099240a46d634a46af350d7d8..485ebb51e69856a479128b61d850a5b7763d7705 100644 (file)
@@ -48,6 +48,7 @@ struct plnstr {
     /* initial part must match struct empobj */
     short ef_type;
     short pln_uid;             /* plane unit id */
+    unsigned pln_seqno;
     time_t pln_timestamp;      /* Last time this plane was touched */
     natid pln_own;             /* owning country */
     coord pln_x;               /* plane x-y */
index 5edadd9697c3cdeb6d3d55451a3dab19b145f993..cc4fd26a914a970073ccfb0b4960ed4ba91ff839 100644 (file)
@@ -710,6 +710,7 @@ extern int wu(natid, natid, char *, ...) ATTRIBUTE((format (printf, 3, 4)));
  * src/lib/update/ *.c 
  */
 /* age.c */
+extern int age_people(int, int);
 extern void age_levels(int);
 /* anno.c */
 extern void delete_old_announcements(void);
index c0d7822240912457b6d23074ebfbbd6488bc5371..b0237a3c48ccf6b2bc02b2ae2c047342a90de228 100644 (file)
@@ -46,6 +46,7 @@ struct sctstr {
     /* initial part must match struct empobj */
     short ef_type;
     short sct_uid;             /* equals XYOFFSET(sct_x, sct_y) */
+    unsigned sct_seqno;
     time_t sct_timestamp;      /* Last time this sector was written to */
     natid sct_own;             /* owner's country num */
     coord sct_x;               /* x coord of sector */
@@ -102,6 +103,7 @@ enum d_navigation {
 struct dchrstr {
     unsigned char d_uid;
     char d_mnem;               /* map symbol */
+    unsigned char d_terrain;   /* terrain sector type */
     int d_prd;                 /* product type */
     int d_peffic;              /* process efficiency, in percent */
     float d_mob0, d_mob1;      /* movement cost at 0 and 100% eff */
@@ -169,6 +171,9 @@ extern struct dchrstr dchr[SCT_TYPE_MAX + 2];
 extern struct dchrstr bigcity_dchr;
 #define IS_BIG_CITY(type) (dchr[(type)].d_pkg == UPKG)
 
+#define IS_BRIDGE_HEAD(type) \
+    ((type) == SCT_BHEAD || (type) == SCT_HIWAY || (type) == SCT_BTOWER)
+
 /* Minimal efficiency of sectors that can be knocked down (bridges) */
 #define SCT_MINEFF 20
 
@@ -181,6 +186,11 @@ extern struct dchrstr bigcity_dchr;
 
 #define FORTEFF 5              /* forts must be 5% efficient to fire. */
 
+/* Can trains enter sector SP? */
+#define SCT_HAS_RAIL(sp)                                       \
+    (opt_RAILWAYS ? sct_rail_track((sp)) != 0                  \
+     : intrchr[INT_RAIL].in_enable && (sp)->sct_rail != 0)
+
 #define MOB_MOVE    0
 #define MOB_MARCH   1
 #define MOB_RAIL    2
@@ -216,5 +226,6 @@ struct sctintrins {
 extern struct sctintrins intrchr[INT_DEF + 2];
 
 extern int fort_fire(struct sctstr *);
+extern int sct_rail_track(struct sctstr *);
 
 #endif
index 1f7fbf8ab9edfabd88fd4ea0d995ab4d491a792c..d09a07b0d1c500d2f7b4ee70dafa88e1cb34c79a 100644 (file)
@@ -65,6 +65,7 @@ struct shpstr {
     /* initial part must match struct empobj */
     short ef_type;
     short shp_uid;             /* unit id (ship #) */
+    unsigned shp_seqno;
     time_t shp_timestamp;      /* Last time this ship was touched. */
     natid shp_own;             /* owner's country num */
     coord shp_x;               /* x location in abs coords */
index 307f990b4a40fa4dc1f0ba8e941f20e006224d1b..074a77da4a0922df5c4362603dc7ce82eb240c8c 100644 (file)
@@ -44,6 +44,7 @@ struct trdstr {
     /* initial part must match struct empobj */
     short ef_type;
     short trd_uid;
+    unsigned trd_seqno;
     time_t trd_timestamp;
     natid trd_owner;
     /* end of part matching struct empobj */
index d5efd77e6d0e90c7795017dd988f7c53f2d848ab..31491eeff139b2ad0cc3ea736d5b23a5dc42e7b6 100644 (file)
@@ -41,6 +41,7 @@ struct trtstr {
     /* initial part must match struct empobj */
     short ef_type;
     short trt_uid;
+    unsigned trt_seqno;
     time_t trt_timestamp;
     /* end of part matching struct empobj */
     natid trt_cna;             /* proposer */
diff --git a/info/Hvy-Metal.t b/info/Hvy-Metal.t
new file mode 100644 (file)
index 0000000..d091996
--- /dev/null
@@ -0,0 +1,118 @@
+.TH Concept "Hvy-Metal"
+.NA Hvy-Metal "Special rules for Hvy Metal"
+.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, and jf2 count as choppers.  Some ships
+are not ideal for this, and this is reflected by the lack of large
+petrol and shell storage.  But it gives players yet another
+interesting avenue to explore, and reflects the ships better.  Also
+helps simulate irregular forces desperately equipping what they can for
+a role.  A chance for a creative player to spring surprises.
+.s1
+New assault ship type: Think Tarawa or Iwo Jima class ships.  These
+put the ASSAULT back into landings.  Huge mil capacity, can operate
+choppers and Harriers.  Able to drop 12 marine units and a horde of
+mil onto a shore, or sustain para drops and air strikes inland with
+its aircraft.  Go ashore in a hurry, Big Time.  A fat target too, so
+guard it carefully.
+.s1
+Ships can navigate bridge sectors regardless of owner.
+.s1
+Ships can assault the sector they're in.
+.s1
+Land unit types are heavily customized.  Better check show for the
+details.  Non-mechanized units are slower and more vulnerable,
+infantry units have capability security, marines can have amtraks,
+artillery firing ranges differ, few units are light (but troop
+transports and landing ships can carry non-light units), food
+capacities are reduced.
+.s1
+Tanks and AAA can fire.  \*QHey guys, why don't we shoot this big gun
+on this tank at those d*mn elves on that hill instead of hanging our
+laundry on it\*U?  Don't expect the range of an artillery unit, which
+specializes in this and has forward observers built in to the unit
+cost.  Watch your magazines too!
+.s1
+Artillery units with capability heavy can only fire at sectors and
+fire offensive support.  They can't target ships, return fire,
+interdict, or fire defensive support.
+.s1
+Artillery units in mountains receive a range bonus of +0.5.
+.s1
+New experimental option RAILWAYS is enabled: trains run on highways
+and sectors next to highways.  Use sinfra to find out mobility costs.
+Try sect # ?track>0 to visualize your track.  Check \*Qinfo
+Railroad\*U for details.
+.s1
+There are more train types, BIG siege guns, etc.
+.\"And we got the
+.\"Mother Of All Guns: something like what was attempted a few times in
+.\"history, a huge costly gun with incredible range.  It CAN be moved.
+.\"Slowly.  Has all the problems fixed positions have.  If these are not
+.\"obvious, any experienced player will gladly demonstrate them for you.
+.s1
+Infrastructure is disabled.
+.s1
+New experimental option LIMBER is enabled: slow guns and heavy railway
+guns use mobility to unlimber.  Limbering and unlimbering is
+completely automatic.  See info \*QUnit-types\*U for details.
+.s1
+Planes are tweaked somewhat.  show is your friend.
+.s1
+Che age just like military reserves: 1% decay per 24 ETUs.  In
+sufficiently loyal sectors you don't own, however, a full half of them
+(rounded up) vanish each update.  The anti command is disabled.
+.s1
+Mountains, fortresses and cities provide a respectable defensive
+bonus.  Cities cost real money to build.  Banks cost some money, too.
+Ever seen Fort Knox?  Bridges cost only half as many hcms as usual.
+.s1
+There is no bridge head sector type.  Highways can serve as bridge
+heads.
+.s1
+New sector type freeway.  You can turn plains into freeway and back,
+but you can't turn either into anything else.  Freeways can serve as
+bridge heads.
+.s1
+Plains produce food.
+.s1
+Food is much harder to grow.  Expect 20% of your population to be
+farmers.
+.s1
+Sectors without any food get one unit of food for free to avoid
+starvation.  In Hvy Metal, that free food is always completely
+consumed.
+.s1
+New sector type biofuel plant lets you make oil from food, at a cost.
+.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.
+Fully depleting a sector will take you several updates.  Oil
+production does not depend on tech; you don't have to micro-manage to
+conserve oil.  Resources are scarce.  Expect to fight over them.
+.s1
+Oil derricks need to set up shop before they produce: no production
+while mobility is below maximum.
+.s1
+Automatic shell supply for sector flak and ship missile defense is
+disabled, because its bugs interfere with Hvy Metal modifications.
+.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 deities laugh and get up to 5 gold bars.  5 bars per week up
+for grabs.
+.s1
+Source code and configuration is available from
+.br
+http://www.stdio.com/~rhyatt/empire/hvy_metal_II/
+.s1
+.SA "Introduction, Server"
index 07f165c5162b9cffa5852d100261c035d596b840..99450c9c121f653a0d88b7442cbf40a920454990 100644 (file)
@@ -48,6 +48,11 @@ TECH_POP:       Technology costs more to make as your civilian population
                  grows past 50,000 civilians.
 TREATIES:       Sign treaties with your friends and enemies, and breaking of
                  them is reported in the news.
+
+The following options are new in Hvy Metal:
+
+LIMBER         Artillery requires mobility to start firing
+RAILWAYS       Highways double as rail
 .fi
 
 .SA "Hidden, Server, version"
diff --git a/info/Railroad.t b/info/Railroad.t
new file mode 100644 (file)
index 0000000..82e6eea
--- /dev/null
@@ -0,0 +1,27 @@
+.TH Concept "Railroad"
+.NA Railroad "How railroads work"
+.LV Expert
+Trains are land units with capability \*Qtrain\*U.  They can't be
+loaded on land units, but they can be loaded on ships, subject to the
+usual restrictions for non-light and heavy land units.
+.s1
+Unlike other units, trains can enter a sector only if it has
+(operational) railroad track.
+.s1
+If option RAILWAYS is disabled, a sector has railroad track as long as
+its rail infrastructure efficiency is non-zero.  Train mobility cost
+depends on rail infrastructure efficiency (see \*Qinfo Mobility\*U).
+Spy and satellite reports show approximate rail infrastructure
+efficiency in column \*Qrl eff\*U.
+.s1
+If option RAILWAYS is enabled, all highway-like sectors are railways,
+and the track is operational as long as the sector is at least 5%
+efficient.  A sector is highway-like if its mobility cost at 100% is
+zero (column mob cost in \*Qshow sect s\*u).  Operational railways
+additionally extend track into adjacent sectors that are at least 60%
+efficient.  Sector selector track gives the number of operational
+railways within one sector range.  Spy and satellite reports show the
+presence of track in column \*Qrl eff\*U.  To visualize your railway
+network, try \*Qsect # ?track#0\*U.
+.s1
+.SA "LandUnits"
index 1a0cca53dc6d146da6157045ed789f00015bf752..5c956734a403bd50eabcfc22289dac936e9fc7ea 100644 (file)
@@ -163,6 +163,15 @@ The number of extra-light planes the land unit can carry.
 The number of land units the unit can carry (no 'heavy' units)
 .in
 .s1
+If option LIMBER is enabled, guns need to be \*Qlimbered\*U to march
+and \*Qunlimbered\*U to fire or fortify.  Limbering and unlimbering is
+completely automatic.  Limbering is free, but unlimbering can cost
+mobility, depending on the type of artillery unit: heavy railway
+artillery and any artillery with a speed below 22 pay unlimber
+mobility equivalent to a march with path cost 0.2, plus 1.  This gains
+one point of fortification.  Presence of engineer units in the same
+sector cut the cost by a third.
+.s1
 Each land unit can carry a certain amount of products and has certain
 capabilities. These are listed under the cargoes & abilities section.
 The cargoes give the number of each product that can be carried.
@@ -196,6 +205,7 @@ the unit can fire 'general unit flak' (see "info Flak")
 the unit is a spy
 .L train
 the unit is a train, and can't be loaded on land units
+(see "info Railroad")
 .L heavy
 the unit cannot be carried on land units or ships, not even supply ships
 .in
@@ -238,4 +248,3 @@ marines 1                  5f 10s xlight light marine
 .FI
 .s1
 .SA "land, LandUnits"
-
index eba4d33e234a48a1c6b3e564eb184b702143888f..fb83eacb56afbf00a7aa2a07f004dc029db97eaf 100644 (file)
@@ -154,13 +154,8 @@ add(void)
                sect.sct_defense = 0;
                sect.sct_own = 0;
                sect.sct_oldown = 0;
-               if (sect.sct_type == SCT_BSPAN ||
-                   sect.sct_type == SCT_BTOWER)
-                   sect.sct_newtype = sect.sct_type = SCT_WATER;
-               else if (sect.sct_type != SCT_MOUNT &&
-                   sect.sct_type != SCT_PLAINS)
-                   sect.sct_newtype = sect.sct_type = SCT_RURAL;
-               /* No dist path */
+               sect.sct_newtype = sect.sct_type
+                   = dchr[sect.sct_type].d_terrain;
                sect.sct_dist_x = sect.sct_x;
                sect.sct_dist_y = sect.sct_y;
                memset(sect.sct_item, 0, sizeof(sect.sct_item));
index c9ea788a34b6d56cba75c29cf6550fdaa3f26adf..bb3d2d6e826b7dafeddae1ccdb91572a27bfc87e 100644 (file)
@@ -528,12 +528,10 @@ build_bridge(struct sctstr *sp, short *vec)
     char buf[1024];
 
     if (opt_EASY_BRIDGES == 0) {       /* must have a bridge head or tower */
-       if (sp->sct_type != SCT_BTOWER) {
-           if (sp->sct_type != SCT_BHEAD)
-               return 0;
-           if (sp->sct_newtype != SCT_BHEAD)
-               return 0;
-       }
+       if (!IS_BRIDGE_HEAD(sp->sct_type))
+           return 0;
+       if (sp->sct_newtype != sp->sct_type)
+           return 0;
     }
 
     if (sp->sct_effic < 60 && !player->god) {
index cee4e2d83ede209cbb811c165dcef1f7d3231ab6..20e278635bc615168cf5ad18af34a6ac3278a006 100644 (file)
@@ -92,12 +92,17 @@ desi(void)
                pr("Only %s can make a %s!\n", cname(0), dchr[des].d_name);
                continue;
            }
+           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 (sect.sct_type == SCT_SANCT)
            breaksanct++;
-       if ((des == SCT_HARBR || des == SCT_BHEAD) && !sect.sct_coastal) {
+       if (des == SCT_HARBR && !sect.sct_coastal) {
            pr("%s does not border on water.\n",
               xyas(nstr.x, nstr.y, player->cnum));
            if (player->god)
@@ -129,11 +134,8 @@ desi(void)
        if (sect.sct_x == cap_x && sect.sct_y == cap_y
            && 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;
+       if (!opt_EASY_BRIDGES && IS_BRIDGE_HEAD(n))
            bridgefall(&sect);
-       }
     }
     if (changed)
        writemap(player->cnum);
index 52279b8414aa0f2f3c7020e43a31af1d1e9825b5..0b3108c0ab54c65f09c3eeed0b32b9f7a57bff80 100644 (file)
@@ -584,7 +584,7 @@ doland(char op, int arg, char *p, struct sctstr *sect)
            return RET_SYN;
        sect->sct_x = newx;
        sect->sct_y = newy;
-       sect->sct_uid = XYOFFSET(newx, newy);
+       ef_set_uid(EF_SECTOR, &sect, XYOFFSET(newx, newy));
        break;
     case 'D':
        if (!sarg_xy(p, &newx, &newy))
@@ -767,7 +767,7 @@ doship(char op, int arg, char *p, struct shpstr *ship)
        ship->shp_rflags = arg;
        break;
     case 'U':
-       ship->shp_uid = arg;
+       ef_set_uid(EF_SHIP, ship, arg);
        break;
     case 'O':
        if (ship->shp_own)
@@ -871,7 +871,7 @@ dounit(char op, int arg, char *p, struct lndstr *land)
        land->lnd_land = arg;
        break;
     case 'U':
-       land->lnd_uid = arg;
+       ef_set_uid(EF_LAND, land, arg);
        break;
     case 'O':
        if (land->lnd_own)
@@ -994,7 +994,7 @@ doplane(char op, int arg, char *p, struct plnstr *plane)
        plane->pln_nuketype = arg;
        break;
     case 'U':
-       plane->pln_uid = arg;
+       ef_set_uid(EF_PLANE, plane, arg);
        break;
     case 'l':
        if (!sarg_xy(p, &newx, &newy))
index b4d9d05aa62cae9e8c853402eeb4a216e9602505..68677b4988c6f32295b12e28d2c404d72cc76cd2 100644 (file)
@@ -330,6 +330,12 @@ multifire(void)
                pr("Unit %d cannot fire!\n", fland.lnd_uid);
                continue;
            }
+           if (lchr[(int)fland.lnd_type].l_flags & L_HEAVY
+               && target != targ_land) {
+               pr("%s is too ponderous to target ships!\n",
+                  prland(&fland));
+               continue;
+           }
            if (fland.lnd_item[I_GUN] == 0) {
                pr("%s -- not enough guns\n", prland(&fland));
                continue;
@@ -349,6 +355,8 @@ multifire(void)
                pr("Klick!     ...\n");
                continue;
            }
+
+           lnd_unlimber(&fland);
            if (target == targ_ship) {
                if (chance(lnd_acc(&fland) / 100.0))
                    dam = ldround(dam / 2.0, 1);
@@ -687,6 +695,9 @@ quiet_bigdef(int type, struct emp_qelem *list, natid own, natid aown,
        /* Don't shoot yourself */
        if (land.lnd_own == aown)
            continue;
+       /* Too ponderous for counter-battery fire */
+       if (lchr[(int)land.lnd_type].l_flags & L_HEAVY)
+           continue;
 
        rel = getrel(getnatp(land.lnd_own), own);
        rel2 = getrel(getnatp(land.lnd_own), aown);
@@ -708,6 +719,7 @@ quiet_bigdef(int type, struct emp_qelem *list, natid own, natid aown,
        if (dam2 < 0)
            continue;
 
+       lnd_unlimber(&land);
        (*nfiring)++;
        if (!fp)
            add_to_flist(list, (struct empobj *)&land, dam2, 0);
index abf9d16f9ee00723f9a50559106d0aa8d8124e63..f44656dba97bdf975a48f4d02ff45b35b9813228 100644 (file)
@@ -226,11 +226,16 @@ mission(void)
                continue;
            }
 
-       if ((mission == MI_INTERDICT) && (type == EF_LAND))
+       if ((mission == MI_INTERDICT) && (type == EF_LAND)) {
            if (lchr[(int)gp->type].l_dam == 0) {
                pr("%s: cannot fire at range!\n", obj_nameof(gp));
                continue;
            }
+           if (lchr[(int)gp->type].l_flags & L_HEAVY) {
+               pr("%s: too ponderous to interdict!\n", obj_nameof(gp));
+               continue;
+           }
+       }
 
        if ((mission == MI_INTERDICT) && (type == EF_PLANE)) {
            struct plchrstr *pcp;
index e17cf3f7c1ec8279bf6f73559839c69c04542124..43780c6eec12317494a873de4748a5675af3e5c5 100644 (file)
@@ -73,7 +73,10 @@ sinfra(void)
        pr("%4d%% ", sect.sct_effic);
        pr("%4d%% ", sect.sct_road);
        prmobcost(&sect, MOB_MOVE);
-       pr("%4d%% ", sect.sct_rail);
+       if (opt_RAILWAYS)
+           pr(sct_rail_track(&sect) ? "  yes " : "   no ");
+       else
+           pr("%4d%% ", sect.sct_rail);
        prmobcost(&sect, MOB_RAIL);
        pr("%4d%% ", SCT_DEFENSE(&sect));
        pr("%5.2f\n", sector_strength(&sect));
index 291ab46b4ddcab7d8b51392d126dda559f858dab..020b42c8a7065f8310070ebbfdcfc96c6670678f 100644 (file)
@@ -224,7 +224,7 @@ spyline(struct sctstr *sp)
        sp->sct_oldown,
        roundintby((int)sp->sct_effic, 10),
        roundintby((int)sp->sct_road, 10),
-       roundintby((int)sp->sct_rail, 10),
+       opt_RAILWAYS ? !!sct_rail_track(sp) : roundintby(sp->sct_rail, 10),
        roundintby((int)sp->sct_defense, 10),
        roundintby(sp->sct_item[I_CIVIL], 10),
        roundintby(sp->sct_item[I_MILIT], 10),
index a28b89913c38ae3c266f01166e00eeef40c0ed12..309977c5eaffadcd314ece6b3091ecb936f4ea8c 100644 (file)
@@ -63,14 +63,14 @@ swaps(void)
     /* change the location of secta to that of sectb */
     secta.sct_x = sectb.sct_x;
     secta.sct_y = sectb.sct_y;
-    secta.sct_uid = sectb.sct_uid;
+    ef_set_uid(EF_SECTOR, &secta, sectb.sct_uid);
     secta.sct_dist_x = sectb.sct_x;
     secta.sct_dist_y = sectb.sct_y;
     secta.sct_coastal = sectb.sct_coastal;
     /* change the location of sectb to where secta was */
     sectb.sct_x = tmp.sct_x;
     sectb.sct_y = tmp.sct_y;
-    sectb.sct_uid = tmp.sct_uid;
+    ef_set_uid(EF_SECTOR, &sectb, tmp.sct_uid);
     sectb.sct_dist_x = tmp.sct_x;
     sectb.sct_dist_y = tmp.sct_y;
     sectb.sct_coastal = tmp.sct_coastal;
index 9586bc4dde4856a54cb5688953bb5e3cac2e6778..d89256a43fdf60d0c3da615fb0946eebcb4b0060 100644 (file)
 
 static int ef_realloc_cache(struct empfile *, int);
 static int fillcache(struct empfile *, int);
+static int do_read(struct empfile *, void *, int, int);
 static int do_write(struct empfile *, void *, int, int, time_t);
+static int get_seqno(struct empfile *, int);
+static void new_seqno(struct empfile *, void *);
 static void do_blank(struct empfile *, void *, int, int);
 
 /*
@@ -300,11 +303,28 @@ ef_read(int type, int id, void *into)
  */
 static int
 fillcache(struct empfile *ep, int id)
+{
+    int ret;
+
+    if (CANT_HAPPEN(!ep->cache))
+       return -1;
+
+    ret = do_read(ep, ep->cache, id, MIN(ep->csize, ep->fids - id));
+    if (ret >= 0) {
+       /* cache changed */
+       ep->baseid = id;
+       ep->cids = ret;
+    }
+    return ret;
+}
+
+static int
+do_read(struct empfile *ep, void *buf, int id, int count)
 {
     int n, ret;
     char *p;
 
-    if (CANT_HAPPEN(ep->fd < 0 || !ep->cache))
+    if (CANT_HAPPEN(ep->fd < 0 || id < 0 || count < 0))
        return -1;
 
     if (lseek(ep->fd, id * ep->size, SEEK_SET) == (off_t)-1) {
@@ -313,21 +333,21 @@ fillcache(struct empfile *ep, int id)
        return -1;
     }
 
-    p = ep->cache;
-    n = MIN(ep->csize, ep->fids - id) * ep->size;
+    p = buf;
+    n = count * ep->size;
     while (n > 0) {
        ret = read(ep->fd, p, n);
        if (ret < 0) {
            if (errno != EINTR) {
                logerror("Error reading %s elt %d (%s)",
                         ep->file,
-                        id + (int)((p - ep->cache) / ep->size),
+                        id + (int)((p - (char *)buf) / ep->size),
                         strerror(errno));
                break;
            }
        } else if (ret == 0) {
            logerror("Unexpected EOF reading %s elt %d",
-                    ep->file, id + (int)((p - ep->cache) / ep->size));
+                    ep->file, id + (int)((p - (char *)buf) / ep->size));
            break;
        } else {
            p += ret;
@@ -335,12 +355,7 @@ fillcache(struct empfile *ep, int id)
        }
     }
 
-    if (p == ep->cache)
-       return -1;              /* nothing read, old cache still ok */
-
-    ep->baseid = id;
-    ep->cids = (p - ep->cache) / ep->size;
-    return ep->cids;
+    return (p - (char *)buf) / ep->size;
 }
 
 /*
@@ -425,6 +440,7 @@ ef_write(int type, int id, void *from)
        ep->prewrite(id, from);
     if (CANT_HAPPEN((ep->flags & EFF_MEM) ? id >= ep->fids : id > ep->fids))
        return 0;               /* not implemented */
+    new_seqno(ep, from);
     if (!(ep->flags & EFF_PRIVATE)) {
        if (do_write(ep, from, id, 1, time(NULL)) < 0)
            return 0;
@@ -442,6 +458,60 @@ ef_write(int type, int id, void *from)
     return 1;
 }
 
+void
+ef_set_uid(int type, void *buf, int uid)
+{
+    struct emptypedstr *elt;
+    struct empfile *ep;
+
+    if (ef_check(type) < 0)
+       return;
+    ep = &empfile[type];
+    if (!(ep->flags & EFF_TYPED))
+       return;
+    elt = buf;
+    if (elt->uid == uid)
+       return;
+    elt->uid = uid;
+    elt->seqno = get_seqno(ep, uid);
+}
+
+static int
+get_seqno(struct empfile *ep, int id)
+{
+    struct emptypedstr *elt;
+
+    if (!(ep->flags & EFF_TYPED))
+       return 0;
+    if (id < 0 || id >= ep->fids)
+       return 0;
+    if (id >= ep->baseid && id < ep->baseid + ep->cids)
+       elt = (void *)(ep->cache + (id - ep->baseid) * ep->size);
+    else {
+       /* need a buffer, steal last cache slot */
+       if (ep->cids == ep->csize)
+           ep->cids--;
+       elt = (void *)(ep->cache + ep->cids * ep->size);
+       if (do_read(ep, elt, id, 1) < 0)
+           return 0;           /* deep trouble */
+    }
+    return elt->seqno;
+}
+
+static void
+new_seqno(struct empfile *ep, void *buf)
+{
+    struct emptypedstr *elt = buf;
+    unsigned old_seqno;
+
+    if (!(ep->flags & EFF_TYPED))
+       return;
+    old_seqno = get_seqno(ep, elt->uid);
+    if (CANT_HAPPEN(old_seqno != elt->seqno))
+       old_seqno = MAX(old_seqno, elt->seqno);
+    elt->seqno = old_seqno + 1;
+}
+
 /*
  * Extend table TYPE by COUNT elements.
  * Any pointers obtained from ef_ptr() become invalid.
@@ -504,9 +574,17 @@ ef_extend(int type, int count)
 void
 ef_blank(int type, int id, void *buf)
 {
+    struct empfile *ep;
+    struct emptypedstr *elt;
+
     if (ef_check(type) < 0)
        return;
-    do_blank(&empfile[type], buf, id, 1);
+    ep = &empfile[type];
+    do_blank(ep, buf, id, 1);
+    if (ep->flags & EFF_TYPED) {
+       elt = buf;
+       elt->seqno = get_seqno(ep, elt->uid);
+    }
 }
 
 /*
index 18d748febafd698361b4ef4fe63a7d35be4cceca..7cbabf8249cc85d058105be85f25bba1d44b39f0 100644 (file)
 
 #include <config.h>
 
+#include "file.h"
 #include "misc.h"
 #include "nat.h"
+#include "optlist.h"
 #include "path.h"
 #include "sect.h"
 #include "xy.h"
@@ -48,6 +50,12 @@ sector_mcost(struct sctstr *sp, int mobtype)
     if (base < 0)
        return -1.0;
 
+    if (mobtype == MOB_RAIL && opt_RAILWAYS) {
+       if (!SCT_HAS_RAIL(sp))
+           return -1;
+       mobtype = MOB_MARCH;
+    }
+
     /* linear function in eff, d_mob0 at 0%, d_mob1 at 100% */
     base += (dchr[sp->sct_type].d_mob1 - base) * sp->sct_effic / 100;
     if (CANT_HAPPEN(base < 0))
@@ -83,3 +91,33 @@ speed_factor(double effspd, int tech)
 {
     return 480.0 / (effspd + techfact(tech, effspd));
 }
+
+/* Minimal efficiency for railway and railway extension (opt_RAILWAYS) */
+#define SCT_RAIL_EFF 5
+#define SCT_RAIL_EXT_EFF 60
+
+/* Is sector SP a railway? */
+#define SCT_IS_RAILWAY(sp) \
+    (dchr[(sp)->sct_type].d_mob1 == 0 && (sp)->sct_effic >= SCT_RAIL_EFF)
+/* May sector SP have a railway extension? */
+#define SCT_MAY_HAVE_RAIL_EXT(sp) \
+    ((sp)->sct_effic >= SCT_RAIL_EXT_EFF)
+/* Does railway sector SP extend railway track into sector TOSP? */
+#define SCT_EXTENDS_RAIL(sp, tosp) \
+    ((sp)->sct_own == (tosp)->sct_own && SCT_MAY_HAVE_RAIL_EXT(tosp))
+
+int
+sct_rail_track(struct sctstr *sp)
+{
+    int i, res;
+    struct sctstr *nsp;
+
+    res = !!SCT_IS_RAILWAY(sp);
+    for (i = DIR_FIRST; i <= DIR_LAST; i++) {
+       nsp = getsectp(sp->sct_x + diroff[i][0],
+                      sp->sct_y + diroff[i][1]);
+       if (SCT_IS_RAILWAY(nsp) && SCT_EXTENDS_RAIL(nsp, sp))
+           res++;
+    }
+    return res;
+}
index 61bf4e7b077785f94b567495eee47ec2ca601339..53149a6e6a7d0bf5a73ef1848039829bca52c257 100644 (file)
@@ -218,8 +218,7 @@ bp_neighbors(struct as_coord c, struct as_coord *cp, void *pp)
           move through it.  We calculate it later. */
        if (dchr[sp->sct_type].d_mob0 < 0)
            continue;
-       if (bp->bp_mobtype == MOB_RAIL
-           && (!intrchr[INT_RAIL].in_enable || sp->sct_rail == 0))
+       if (bp->bp_mobtype == MOB_RAIL && !SCT_HAS_RAIL(sp))
            continue;
        if (sp->sct_own != from->sct_own)
            continue;
index 205ae005727146ab6313a15e3c896be23aa5e248..0abe19acc9ea7f17aa3596228ea2fc608c33c755 100644 (file)
@@ -47,6 +47,7 @@
 
 static void *nsc_ver(struct valstr *, struct natstr *, void *);
 static void *nsc_ver_maxnoc(struct valstr *, struct natstr *, void *);
+static void *nsc_sct_track(struct valstr *, struct natstr *, void *);
 static void *nsc_pln_att(struct valstr *, struct natstr *, void *);
 static void *nsc_pln_def(struct valstr *, struct natstr *, void *);
 static void *nsc_lnd_att(struct valstr *, struct natstr *, void *);
@@ -153,6 +154,7 @@ struct castr sect_ca[] = {
     {"uran", fldoff(sct_uran), NSC_UCHAR, 0, NULL, EF_BAD, 0},
     {"oldown", fldoff(sct_oldown), NSC_NATID, 0, NULL, EF_NATION, 0},
     {"off", fldoff(sct_off), NSC_UCHAR, 0, NULL, EF_BAD, 0},
+    {"track", 0, NSC_LONG, 0, nsc_sct_track, EF_BAD, NSC_EXTRA},
     NSC_IVEC(fldoff(sct_item), ""),
     NSC_IVEC(fldoff(sct_dist), "_dist"),
     NSC_IVEC(fldoff(sct_del), "_del"),
@@ -178,6 +180,7 @@ struct castr dchr_ca[] = {
     {"uid", fldoff(d_uid), NSC_UCHAR, 0, NULL, EF_SECTOR_CHR, 0},
     {"name", fldoff(d_name), NSC_STRING, 0, NULL, EF_BAD, 0},
     {"mnem", fldoff(d_mnem), NSC_STRINGY, 1, NULL, EF_BAD, NSC_CONST},
+    {"terrain", fldoff(d_terrain), NSC_UCHAR, 0, NULL, EF_SECTOR_CHR, 0},
     {"prd", fldoff(d_prd), NSC_INT, 0, NULL, EF_PRODUCT, 0},
     {"peffic", fldoff(d_peffic), NSC_INT, 0, NULL, EF_BAD, 0},
     {"mob0", fldoff(d_mob0), NSC_FLOAT, 0, NULL, EF_BAD, 0},
@@ -764,6 +767,13 @@ nsc_ver_maxnoc(struct valstr *val, struct natstr *np, void *ptr)
     return NULL;
 }
 
+static void *
+nsc_sct_track(struct valstr *val, struct natstr *np, void *ptr)
+{
+    val->val_as.lng = sct_rail_track(ptr);
+    return NULL;
+}
+
 static void *
 nsc_pln_def(struct valstr *val, struct natstr *np, void *ptr)
 {
index 02753e4502a58e27a2a6d7ebac3c152891bbf7fb..67dd12bed45b8face6eb859ed714ab8652e5dd59 100644 (file)
@@ -49,6 +49,7 @@ int opt_GUINEA_PIGS = 0;
 int opt_HIDDEN = 0;
 int opt_INTERDICT_ATT = 1;
 int opt_LANDSPIES = 1;
+int opt_LIMBER = 0;
 int opt_LOANS = 1;
 int opt_LOSE_CONTACT = 0;
 int opt_MARKET = 0;
@@ -58,6 +59,7 @@ int opt_NOMOBCOST = 1;
 int opt_NO_FORT_FIRE = 0;
 int opt_NO_PLAGUE = 1;
 int opt_PINPOINTMISSILE = 1;
+int opt_RAILWAYS = 0;
 int opt_RES_POP = 0;
 int opt_SAIL = 1;
 int opt_SHOWPLANE = 1;
index 2e4032fd1b15c62edaf80408b7b6237041560e8a..4608ce6e1dbdc8331cf7608aefce5e151ea88227 100644 (file)
@@ -28,7 +28,7 @@
 #   sect.config: Sector characteristics
 #
 #   Known contributors to this file:
-#      Markus Armbruster, 2006
+#      Markus Armbruster, 2006-2008
 #
 #   Derived from sect.c; known contributors:
 #      Dave Pare, 1986
 #      Steve McClure, 1998
 #
 
+# Sector terrain (column terra) is the uid of the underlying terrain
+# sector type.  Sector types that occur in that column are terrain
+# types, and must have themselves as terrain.
+
 # Available products (column prd) are in product.config.  Navigation
 # types (column nav) are in sector_navigation[].  Packing types
 # (column pkg) are in packing[].
 
 # Players can only designate sectors with a non-negative value in
-# column cost.  All such sectors should have the same population limit
-# (column maxp), or else players can abuse redesignation to
-# mass-murder people.
+# column cost, and only to something with the same terrain.  All
+# sectors with the same terrain and non-negative cost should have the
+# same population limit (column maxp), or else players can abuse
+# redesignation to mass-murder people.
 
 # A sector with urban packing (urba in column pkg) is a big city.
 # Column maxp applies at 0% efficiency.  The limit at 100% is ten
 # econfig key custom_tables.
 
 config sect-chr
-uid mnem  prd peff mob0 mob1  nav  pkg ostr dstr val cost bui lcm hcm maxp name
-  0  "."   -1    0   -1   -1  sea norm  0.0  0.0   0   -1   0   0   0    0 "sea"
-  1  "^" dust   75  2.4  1.2 land norm  1.0  4.0   5   -1   1   0   0  100 "mountain"
-  2  "s"   -1    0   -1   -1 land norm  0.0 99.0 127   -1   0   0   0 1000 "sanctuary"
-  3 "\134" -1    0   -1   -1 land norm  0.0 99.0   0   -1   0   0   0    0 "wasteland"
-  4  "-"   -1    0  0.4  0.4 land norm  1.0  2.0   1    0   0   0   0 1000 "wilderness"
+uid mnem terra prd peff mob0 mob1  nav  pkg ostr dstr val cost bui lcm hcm maxp name
+  0  "."    0   -1    0   -1   -1  sea norm  0.0  0.0   0   -1   0   0   0    0 "sea"
+  1  "^"    1 dust   75  2.4  1.2 land norm  1.0  4.0   5   -1   1   0   0  100 "mountain"
+  2  "s"    4   -1    0   -1   -1 land norm  0.0 99.0 127   -1   0   0   0 1000 "sanctuary"
+  3 "\134"  3   -1    0   -1   -1 land norm  0.0 99.0   0   -1   0   0   0    0 "wasteland"
+  4  "-"    4   -1    0  0.4  0.4 land norm  1.0  2.0   1    0   0   0   0 1000 "wilderness"
 # Uncomment one of the following two.  The second one is for big cities.
-  5  "c"   -1    0  0.4  0.2 land norm  1.0  2.0  30    0   1   0   0 1000 "capital"
-# 5  "c"   -1    0  0.4  0.2 cana urba  1.0  2.0  30    0  10   1   2 1000 "city"
-  6  "u"  rad  100  0.4  0.2 land norm  1.0  2.0  15    0   1   0   0 1000 "uranium mine"
-  7  "p"  hap  100  0.4  0.2 land norm  1.0  1.5   5    0   1   0   0 1000 "park"
-  8  "d"  gun  100  0.4  0.2 land norm  1.0  1.5   7    0   1   0   0 1000 "defense plant"
-  9  "i"   sh  100  0.4  0.2 land norm  1.0  1.5   6    0   1   0   0 1000 "shell industry"
- 10  "m" iron  100  0.4  0.2 land norm  1.0  2.0   5    0   1   0   0 1000 "mine"
- 11  "g" dust  100  0.4  0.2 land norm  1.0  2.0   8    0   1   0   0 1000 "gold mine"
- 12  "h"   -1    0  0.4  0.2 harb ware  1.0  1.5  12    0   1   0   0 1000 "harbor"
- 13  "w"   -1    0  0.4  0.2 land ware  1.0  1.5   7    0   1   0   0 1000 "warehouse"
- 14  "*"   -1    0  0.4  0.2 land norm  1.0  1.25 12    0   1   0   0 1000 "airfield"
- 15  "a" food  900  0.4  0.2 land norm  1.0  1.5   2    0   1   0   0 1000 "agribusiness"
- 16  "o"  oil  100  0.4  0.2 land norm  1.0  1.5   5    0   1   0   0 1000 "oil field"
- 17  "j"  lcm  100  0.4  0.2 land norm  1.0  1.5   3    0   1   0   0 1000 "light manufacturing"
- 18  "k"  hcm  100  0.4  0.2 land norm  1.0  1.5   4    0   1   0   0 1000 "heavy manufacturing"
- 19  "f"   -1    0  0.4  0.2 land norm  2.0  4.0  10    0   5   0   1 1000 "fortress"
- 20  "t" tech  100  0.4  0.2 land norm  1.0  1.5  10    0   1   0   0 1000 "technical center"
- 21  "r"  med  100  0.4  0.2 land norm  1.0  1.5   9    0   1   0   0 1000 "research lab"
- 22  "n"   -1    0  0.4  0.2 land norm  1.0  2.0  10    0   1   0   0 1000 "nuclear plant"
- 23  "l"  edu  100  0.4  0.2 land norm  1.0  1.5   4    0   1   0   0 1000 "library/school"
- 24  "+"   -1    0  0.4  0.0 land norm  1.0  1.0   3    0   1   0   0 1000 "highway"
- 25  ")"   -1    0  0.4  0.2 land norm  1.0  1.5   4    0   1   0   0 1000 "radar installation"
- 26  "!"   -1    0  0.4  0.2 land norm  1.0  1.5  12    0   1   0   0 1000 "headquarters"
- 27  "#"   -1    0  0.4  0.0 land norm  1.0  1.0   3    0   1   0   0 1000 "bridge head"
- 28  "="   -1    0  0.4  0.0 brid norm  1.0  1.0   5   -1   1   0   0  100 "bridge span"
- 29  "b" bars  100  0.4  0.2 land bank  1.0  2.25 10    0   1   0   0 1000 "bank"
- 30  "%"  pet 1000  0.4  0.2 land norm  1.0  1.5   2    0   1   0   0 1000 "refinery"
- 31  "e"   -1    0  0.4  0.2 land norm  1.0  2.0   7    0   1   0   0 1000 "enlistment center"
- 32  "~"   -1    0  0.4  0.2 land norm  1.0  1.5   1   -1   1   0   0  100 "plains"
- 33  "@"   -1    0  0.4  0.0 land norm  1.0  1.5   4   -1   1   0   0  100 "bridge tower"
+  5  "c"    4   -1    0  0.4  0.2 land norm  1.0  2.0  30    0   1   0   0 1000 "capital"
+# 5  "c"    4   -1    0  0.4  0.2 cana urba  1.0  2.0  30    0  10   1   2 1000 "city"
+  6  "u"    4  rad  100  0.4  0.2 land norm  1.0  2.0  15    0   1   0   0 1000 "uranium mine"
+  7  "p"    4  hap  100  0.4  0.2 land norm  1.0  1.5   5    0   1   0   0 1000 "park"
+  8  "d"    4  gun  100  0.4  0.2 land norm  1.0  1.5   7    0   1   0   0 1000 "defense plant"
+  9  "i"    4   sh  100  0.4  0.2 land norm  1.0  1.5   6    0   1   0   0 1000 "shell industry"
+ 10  "m"    4 iron  100  0.4  0.2 land norm  1.0  2.0   5    0   1   0   0 1000 "mine"
+ 11  "g"    4 dust  100  0.4  0.2 land norm  1.0  2.0   8    0   1   0   0 1000 "gold mine"
+ 12  "h"    4   -1    0  0.4  0.2 harb ware  1.0  1.5  12    0   1   0   0 1000 "harbor"
+ 13  "w"    4   -1    0  0.4  0.2 land ware  1.0  1.5   7    0   1   0   0 1000 "warehouse"
+ 14  "*"    4   -1    0  0.4  0.2 land norm  1.0  1.25 12    0   1   0   0 1000 "airfield"
+ 15  "a"    4 food  900  0.4  0.2 land norm  1.0  1.5   2    0   1   0   0 1000 "agribusiness"
+ 16  "o"    4  oil  100  0.4  0.2 land norm  1.0  1.5   5    0   1   0   0 1000 "oil field"
+ 17  "j"    4  lcm  100  0.4  0.2 land norm  1.0  1.5   3    0   1   0   0 1000 "light manufacturing"
+ 18  "k"    4  hcm  100  0.4  0.2 land norm  1.0  1.5   4    0   1   0   0 1000 "heavy manufacturing"
+ 19  "f"    4   -1    0  0.4  0.2 land norm  2.0  4.0  10    0   5   0   1 1000 "fortress"
+ 20  "t"    4 tech  100  0.4  0.2 land norm  1.0  1.5  10    0   1   0   0 1000 "technical center"
+ 21  "r"    4  med  100  0.4  0.2 land norm  1.0  1.5   9    0   1   0   0 1000 "research lab"
+ 22  "n"    4   -1    0  0.4  0.2 land norm  1.0  2.0  10    0   1   0   0 1000 "nuclear plant"
+ 23  "l"    4  edu  100  0.4  0.2 land norm  1.0  1.5   4    0   1   0   0 1000 "library/school"
+ 24  "+"    4   -1    0  0.4  0.0 land norm  1.0  1.0   3    0   1   0   0 1000 "highway"
+ 25  ")"    4   -1    0  0.4  0.2 land norm  1.0  1.5   4    0   1   0   0 1000 "radar installation"
+ 26  "!"    4   -1    0  0.4  0.2 land norm  1.0  1.5  12    0   1   0   0 1000 "headquarters"
+ 27  "#"    4   -1    0  0.4  0.0 land norm  1.0  1.0   3    0   1   0   0 1000 "bridge head"
+ 28  "="    0   -1    0  0.4  0.0 brid norm  1.0  1.0   5   -1   1   0   0  100 "bridge span"
+ 29  "b"    4 bars  100  0.4  0.2 land bank  1.0  2.25 10    0   1   0   0 1000 "bank"
+ 30  "%"    4  pet 1000  0.4  0.2 land norm  1.0  1.5   2    0   1   0   0 1000 "refinery"
+ 31  "e"    4   -1    0  0.4  0.2 land norm  1.0  2.0   7    0   1   0   0 1000 "enlistment center"
+ 32  "~"   32   -1    0  0.4  0.2 land norm  1.0  1.5   1   -1   1   0   0  100 "plains"
+ 33  "@"    0   -1    0  0.4  0.0 land norm  1.0  1.5   4   -1   1   0   0  100 "bridge tower"
 /config
index 11616ee916fcc0ee0140783c7982045297710855..106b797755c36e773eea550511a0093709a42a22 100644 (file)
@@ -770,12 +770,18 @@ ac_doflak(struct emp_qelem *list, struct sctstr *from)
 
     gun = MIN(FLAK_GUN_MAX, from->sct_item[I_GUN]);
     shell = from->sct_item[I_SHELL];
+#if 0
+    /*
+     * FIXME can supply from itself, causing seqno mismatch oops
+     * further down
+     */
     if (gun > shell * 2) {
        shell += supply_commod(from->sct_own, from->sct_x, from->sct_y,
                               I_SHELL, (gun + 1) / 2 - shell);
        from->sct_item[I_SHELL] = shell;
        putsect(from);
     }
+#endif
     if (gun > shell * 2)
        gun = shell * 2;
 
index 5183b2a5a7f0d3b668c325cc3fd0d1cbd33a8b75..d3d6c5c3048a9f9f7a5e7e75ce0cba1e0a1030ec 100644 (file)
@@ -461,6 +461,7 @@ att_abort(int combat_mode, struct combat *off, struct combat *def)
        if (att_get_combat(off, 0) < 0)
            return abort_attack();
        if (off->type == EF_SHIP &&
+           !(off->x == def->x && off->y == def->y) &&
            (!getsect(off->x, off->y, &sect) ||
             sect.sct_type != SCT_WATER)) {
            pr("%s can not %s from that far inland!\n",
index f407f32f06c8607a716eb8c46eb96a728a78d866..624b0a957303b6d36212f6bc6e7a9322bbf05207 100644 (file)
@@ -70,7 +70,7 @@ bridge_damaged(struct sctstr *sp)
     des = sp->sct_type;
     if (des == SCT_BSPAN || des == SCT_BTOWER)
        knockdown(sp);
-    if ((des == SCT_BHEAD || des == SCT_BTOWER) && !opt_EASY_BRIDGES)
+    if (IS_BRIDGE_HEAD(des) && !opt_EASY_BRIDGES)
        bridgefall(sp);
 }
 
@@ -98,17 +98,16 @@ bridgefall(struct sctstr *sp)
            if (nnx == sp->sct_x && nny == sp->sct_y)
                continue;
            getsect(nnx, nny, &bh_sect);
-           if (bh_sect.sct_type == SCT_BHEAD &&
-               bh_sect.sct_newtype == SCT_BHEAD)
-               break;
-           if (bh_sect.sct_type == SCT_BTOWER)
-               break;
            /* With EASY_BRIDGES, it just has to be next to any
               land */
            if (opt_EASY_BRIDGES) {
                if (bh_sect.sct_type != SCT_WATER &&
                    bh_sect.sct_type != SCT_BSPAN)
                    break;
+           } else {
+               if (IS_BRIDGE_HEAD(bh_sect.sct_type)
+                   && bh_sect.sct_newtype == bh_sect.sct_type)
+                   break;
            }
        }
        if (j > 6) {
index 151679a41a0e6e8849b6de301168e7f43d823cf9..a6a21da9e275cc94f7086d7babbb012e853d976f 100644 (file)
@@ -287,7 +287,11 @@ shp_torp_hitchance(struct shpstr *sp, int range)
 double
 lnd_fire_range(struct lndstr *lp)
 {
-    return effrange(lnd_frg(lp), lp->lnd_tech);
+    struct sctstr sect;
+
+    getsect(lp->lnd_x, lp->lnd_y, &sect);
+    return effrange(lnd_frg(lp), lp->lnd_tech)
+       + (sect.sct_type == SCT_MOUNT ? 0.5 : 0.0);
 }
 
 int
index 395ffcf2fdbb63422f2ab5ea26686ae353669c6f..578c1af0a8d038455a2aa94df6ec8154b79eeed2 100644 (file)
@@ -991,7 +991,7 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor,
                continue;
            }
        }
-       if ((!intrchr[INT_RAIL].in_enable || sect.sct_rail == 0)
+       if (!SCT_HAS_RAIL(&sect)
            && lnd_mobtype(&llp->unit.land) == MOB_RAIL) {
            if (together) {
                pr("no rail system in %s\n", xyas(newx, newy, actor));
@@ -1126,6 +1126,9 @@ lnd_support(natid victim, natid attacker, coord x, coord y, int defending)
     while (nxtitem(&ni, &land)) {
        if ((land.lnd_x == x) && (land.lnd_y == y))
            continue;
+       /* Too ponderous for defensive support */
+       if (defending && (lchr[(int)land.lnd_type].l_flags & L_HEAVY))
+           continue;
        rel = getrel(getnatp(land.lnd_own), attacker);
        rel2 = getrel(getnatp(land.lnd_own), victim);
        if ((land.lnd_own != attacker) &&
@@ -1144,6 +1147,7 @@ lnd_support(natid victim, natid attacker, coord x, coord y, int defending)
        if (dam2 < 0)
            continue;
 
+       lnd_unlimber(&land);
        if (defending)
            nreport(land.lnd_own, N_FIRE_BACK, victim, 1);
        else
@@ -1170,31 +1174,81 @@ lnd_can_attack(struct lndstr *lp)
     return 1;
 }
 
+/*
+ * Return mobility required to unlimber LP.
+ */
+static double
+lnd_mob_to_unlimber(struct lndstr *lp)
+{
+    struct lchrstr *lcp = &lchr[(int)lp->lnd_type];
+
+    if (!opt_LIMBER || lcp->l_dam == 0 || lp->lnd_harden != 0)
+       return 0;
+
+    if (lnd_spd(lp) < 22
+       || (lcp->l_flags & (L_HEAVY | L_TRAIN)) == (L_HEAVY | L_TRAIN)) {
+       /*
+        * Slow artillery is towed and needs to be unlimbered.
+        * Heavy railway guns need to be assembled.
+        */
+       return lnd_pathcost(lp, 0.2);
+    }
+
+    return 0;
+}
+
+/*
+ * Unlimber land unit LP.
+ * No effect unless LP is limbered artillery.
+ */
+void
+lnd_unlimber(struct lndstr *lp)
+{
+    double unlimber_mob, mult, newmob;
+
+    unlimber_mob = lnd_mob_to_unlimber(lp);
+    if (unlimber_mob == 0)
+       return;
+
+    mult = has_helpful_engineer(lp->lnd_x, lp->lnd_y, lp->lnd_own)
+       ? 1.5 : 1.0;
+    newmob = lp->lnd_mobil - (1 + unlimber_mob) / mult;
+    lp->lnd_mobil = (signed char)MAX(-127, floor(newmob));
+    CANT_HAPPEN(lp->lnd_harden != 0);
+    lp->lnd_harden = 1;
+}
+
 /*
  * Increase fortification value of LP.
  * Fortification costs mobility.  Use up to MOB mobility.
+ * Automatically unlimbers.
  * Return actual fortification increase.
  */
 int
 lnd_fortify(struct lndstr *lp, int mob)
 {
     int hard_amt;
-    double mob_used, mult;
+    double mob_used, unlimber_mob, mult;
 
     if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
        return 0;
 
     mob_used = MIN(lp->lnd_mobil, mob);
-    if (mob_used < 0)
-       return 0;
-
     mult = has_helpful_engineer(lp->lnd_x, lp->lnd_y, lp->lnd_own)
        ? 1.5 : 1.0;
+    unlimber_mob = lnd_mob_to_unlimber(lp);
+
+    hard_amt = (int)(mob_used * mult - unlimber_mob);
+    if (hard_amt < 1)
+       /*
+        * FIXME unlimber_mob > land_mob_max breaks fortify command
+        * FIXME > etu_per_update * land_mob_scale breaks auto-fort. at update
+        */
+       return 0;
 
-    hard_amt = (int)(mob_used * mult);
     if (lp->lnd_harden + hard_amt > land_mob_max) {
        hard_amt = land_mob_max - lp->lnd_harden;
-       mob_used = ceil(hard_amt / mult);
+       mob_used = ceil((hard_amt + unlimber_mob) / mult);
     }
 
     lp->lnd_mobil -= (int)mob_used;
index e038c12c6207f3265d3bd7b63a7bd43744d8c91d..340f2f570fc857efb86338cce127c08802ddb893 100644 (file)
@@ -436,6 +436,10 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                (md > land_max_interdiction_range))
                continue;
 
+           /* Too ponderous for interdiction fire */
+           if (lchr[(int)lp->lnd_type].l_flags & L_HEAVY)
+               continue;
+
            range = roundrange(lnd_fire_range(lp));
            if (md > range)
                continue;
@@ -445,6 +449,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
            if (dam2 < 0)
                continue;
 
+           lnd_unlimber(lp);
            if (sect.sct_type == SCT_WATER) {
                if (chance(lnd_acc(lp) / 100.0))
                    dam2 = ldround(dam2 / 2.0, 1);
index 8a53cbeedecc6656dd674b938a68752fea4ea695..2dffb2681c758b3fae4f005105e8b920174c9f19 100644 (file)
@@ -111,7 +111,7 @@ delete_old_news(void)
     for (j = 0; getnews(i + j, &news); j++) {
        if (news.nws_vrb == 0)
            break;
-       news.nws_uid = j;
+       ef_set_uid(EF_NEWS, &news, j);
        putnews(j, &news);
     }
     CANT_HAPPEN(i + j != news_tail);
index fe71e7ba9aa9229ba2ee5b6430a44dcc066e7d4c..363621f3015f019b3c9d157c59f220d91bc70c04 100644 (file)
@@ -89,6 +89,9 @@ nuk_prewrite(int n, void *ptr)
     }
 
     getnuke(n, &nuke);
+    if (nuke.nuk_plane != np->nuk_plane)
+       logerror("phantom nuke debug: nuk#%d plane %d->%d",
+                np->nuk_uid, nuke.nuk_plane, np->nuk_plane);
 
     return 1;
 }
index aaaaf8453cb8eda9f71b4bd2647f63eabdf35719..17554dd1416d3b33af913dc8ad7dec2301c14418 100644 (file)
@@ -132,6 +132,9 @@ pln_prewrite(int n, void *ptr)
        }
     }
     getplane(n, &plane);
+    if (plane.pln_nuketype != pp->pln_nuketype)
+       logerror("phantom nuke debug: pln#%d nuketype %d->%d",
+                pp->pln_uid, plane.pln_nuketype, pp->pln_nuketype);
 
     return 1;
 }
index 57eceeae7d4762cae4da6afc5296dc0de619f38a..b3fb5ef7b39c5c214fbef53c2e16f807de19a163 100644 (file)
@@ -251,6 +251,7 @@ retreat_ship1(struct shpstr *sp, char code, int orig)
        getsect(newx, newy, &sect);
        if (shp_check_nav(&sect, sp) != CN_NAVIGABLE ||
            (sect.sct_own && sect.sct_own != sp->shp_own &&
+            sect.sct_type != SCT_BSPAN &&
             getrel(getnatp(sect.sct_own), sp->shp_own) < FRIENDLY)) {
            wu(0, sp->shp_own, "%s %s,\nbut could not retreat to %s!\n",
               prship(sp), conditions[findcondition(code)].desc[orig],
index cc4b06dbbfd810774f953b18142e85900a9ba29e..f4def5dfff43b4f890e9ec70b44fe18129e10acd 100644 (file)
@@ -285,7 +285,7 @@ satdisp_sect(struct sctstr *sp, int acc)
        dchr[sp->sct_type].d_mnem,
        sp->sct_own, roundintby((int)sp->sct_effic, acc / 2),
        roundintby((int)sp->sct_road, acc / 2),
-       roundintby((int)sp->sct_rail, acc / 2),
+       opt_RAILWAYS ? !!sct_rail_track(sp) : roundintby(sp->sct_rail, acc / 2),
        roundintby((int)sp->sct_defense, acc / 2),
        roundintby(sp->sct_item[I_CIVIL], acc),
        roundintby(sp->sct_item[I_MILIT], acc),
index 7ceebb7a00cc10b1ff845c89218639dbd3ec0ffe..f5b90fd9b99bd482f4ebc80d1a36f23bcc6a64a8 100644 (file)
@@ -753,6 +753,7 @@ shp_nav_one_sector(struct emp_qelem *list, int dir, natid actor,
        navigate = shp_check_nav(&sect, &mlp->unit.ship);
        if (navigate != CN_NAVIGABLE ||
            (sect.sct_own && actor != sect.sct_own &&
+            sect.sct_type != SCT_BSPAN &&
             getrel(getnatp(sect.sct_own), actor) < FRIENDLY)) {
            if (dchr[sect.sct_type].d_nav == NAV_CANAL &&
                !(((struct mchrstr *)mlp->chrp)->m_flags & M_CANAL) &&
@@ -867,12 +868,18 @@ shp_missile_defense(coord dx, coord dy, natid bombown, int hardtarget)
        shell = ship.shp_item[I_SHELL];
        if (ship.shp_item[I_MILIT] < 1) /* do we have mil? */
            continue;
+#if 0
+       /*
+        * FIXME can supply from itself, causing seqno mismatch oops
+        * further down
+        */
        if (shell < 2) {        /* do we need shells */
            shell += supply_commod(ship.shp_own, ship.shp_x, ship.shp_y,
                                   I_SHELL, 2);
            if (shell < 2)
                continue;
        }
+#endif
        if (ship.shp_item[I_GUN] < 1)   /* we need at least 1 gun */
            continue;
 
index 29dca549f46659029f6a2c6a4e07f0b9324e6353..98cecaabbdcc0b88dac1849a3ef060418cbc8381 100644 (file)
 
 #include "update.h"
 
+int
+age_people(int n, int etu)
+{
+    /* age by 1% per 24 etus */
+    return roundavg(n * (1.0 - etu / 2400.0));
+}
+
 void
 age_levels(int etu)
 {
@@ -43,7 +50,6 @@ age_levels(int etu)
     int i;
     double level;
     double delta;
-    int deltares;
 
     best_tech = 0.0;
     best_res = 0.0;
@@ -61,14 +67,7 @@ age_levels(int etu)
            delta = np->nat_level[NAT_TLEV] * etu / (100 * level_age_rate);
            np->nat_level[NAT_TLEV] -= delta;
        }
-       /*
-        * age reserves by 1% per every 24 etus
-        */
-       deltares = -roundavg(np->nat_reserve * etu / 2400.0);
-       if (deltares != 0)
-           np->nat_reserve += deltares;
-       /* Chad Zabel - above number is negative ( was a -= there
-          which was wrong. */
+       np->nat_reserve = age_people(np->nat_reserve, etu);
     }
     best_tech /= 5;
     best_res /= 5;
index 1a7b1c5fcb46b4f606f6e4a86681d463fcb2f162..d36b9e158fe17a33a358c26cb594454788fbd758 100644 (file)
@@ -61,6 +61,7 @@ do_feed(struct sctstr *sp, struct natstr *np, short *vec,
     int starved, sctwork;
     int needed;
     int maxpop;
+    int manna;
 
     /* grow people & stuff */
     sctwork = sp->sct_work;
@@ -72,12 +73,16 @@ do_feed(struct sctstr *sp, struct natstr *np, short *vec,
                                     maxpop));
 
     if (sp->sct_type != SCT_SANCT) {
+       manna = 0;
        if (opt_NOFOOD == 0) {
            needed = (int)ceil(food_needed(vec, etu));
            if (vec[I_FOOD] < needed) {
                /* need to grow "emergency rations" */
                work_avail -= 2 * growfood(sp, vec, work_avail / 2, etu);
                /* It's twice as hard to grow those than norm */
+               if (vec[I_FOOD] == 0)
+                   /* Conjure up 1f to make life easier for the player */
+                   manna = vec[I_FOOD] = 1;
            }
            if (vec[I_FOOD] < needed && sp->sct_own == sp->sct_oldown) {
                /* steal food from warehouses, headquarters,
@@ -109,7 +114,21 @@ do_feed(struct sctstr *sp, struct natstr *np, short *vec,
            if (!player->simulation)
                sp->sct_work = sctwork;
            grow_people(sp, etu, np, &work_avail, sctwork, vec);
+           /* age che */
+           if (!player->simulation) {
+               int oldche = sp->sct_che;
+               sp->sct_che = age_people(sp->sct_che, etu);
+               if (sp->sct_che_target == sp->sct_own && sp->sct_loyal < 40)
+                   /* make them fade away eventually, for playability */
+                   sp->sct_che /= 2;
+               if (sp->sct_che != oldche)
+                   logerror("che in %d,%d aged from %d to %d",
+                            sp->sct_x, sp->sct_y, oldche, sp->sct_che);
+           }
        }
+       if (manna)
+           /* Take away food we conjured up */
+           vec[I_FOOD] = 0;
     } else
        sctwork = sp->sct_work = 100;
     /* Here is where we truncate extra people, always */
@@ -141,13 +160,7 @@ growfood(struct sctstr *sp, short *vec, int work, int etu)
     food = MIN(food_workers, food_fertil);
     if (food > ITEM_MAX - vec[I_FOOD])
        food = ITEM_MAX - vec[I_FOOD];
-    /*
-     * Be nice; grow minimum one food unit.
-     * This makes life simpler for the player.
-     */
     vec[I_FOOD] += food;
-    if (vec[I_FOOD] == 0)
-       vec[I_FOOD] = 1;
     work_used = food / fcrate;
     return work_used;
 }
index 59546ddb65687c71c879aa2858a2b0495a16f052..cccbe260d3620e137eb360eeeb4aac52dbb0943f 100644 (file)
@@ -157,7 +157,8 @@ upd_ship(struct shpstr *sp, int etus,
 
            /* produce oil */
            if (np->nat_money >= 0
-               && (mp->m_flags & M_OIL) && sectp->sct_type == SCT_WATER) {
+               && (mp->m_flags & M_OIL) && sectp->sct_type == SCT_WATER
+               && sp->shp_mobil >= ship_mob_max) {
                product = &pchr[dchr[SCT_OIL].d_prd];
                oil_gained = roundavg(total_work(100, etus,
                                                 sp->shp_item[I_CIVIL],
index 8a5696d1a77dcb0e28a96b300ea2a53cb549c081..6e2e8eb38f1cd9b77885621969a9abe2f91e9465 100644 (file)
@@ -1098,6 +1098,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);
            sct++;
index 4618ba6efc7c7dfaa5f1d47523950420a58fdebf..a7c802b7fdc809dc8ae3c24d4e0d3dce3e91fde4 100644 (file)
@@ -155,6 +155,7 @@ main(int argc, char *argv[])
     for (i = 1; i < MAXNOC; i++) {
        nat.ef_type = EF_NATION;
        nat.nat_cnum = nat.nat_uid = i;
+       nat.nat_seqno = 0;
        putnat((&nat));
     }
     memset(&realm, 0, sizeof(realm));
@@ -164,6 +165,7 @@ main(int argc, char *argv[])
        for (j = 0; j < MAXNOR; j++) {
            realm.r_realm = j;
            realm.r_uid = (i * MAXNOR) + j;
+           realm.r_seqno = 0;
            putrealm(&realm);
        }
     }
@@ -209,6 +211,7 @@ file_sct_init(coord x, coord y, struct sctstr *ptr)
 
     sp->ef_type = EF_SECTOR;
     sp->sct_uid = XYOFFSET(x, y);
+    sp->sct_seqno = 0;
     sp->sct_x = x;
     sp->sct_y = y;
     sp->sct_dist_x = x;