]> git.pond.sub.org Git - empserver/commitdiff
Rebase of Hvy Metal I final version
authorMarkus Armbruster <armbru@pike.pond.sub.org>
Sat, 19 Jan 2008 14:19:13 +0000 (15:19 +0100)
committerMarkus Armbruster <armbru@pike.pond.sub.org>
Wed, 7 May 2008 08:33:41 +0000 (10:33 +0200)
Straightforward forward port.  Drop the code to reset track on
startup.  It's not necessary, and it breaks linking of empdump.

25 files changed:
include/econfig-spec.h
include/land.h
include/prototypes.h
include/sect.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/mfir.c
src/lib/commands/miss.c
src/lib/commands/sinf.c
src/lib/commands/spy.c
src/lib/common/move.c
src/lib/common/path.c
src/lib/global/nsc.c
src/lib/global/options.c
src/lib/subs/landgun.c
src/lib/subs/lndsub.c
src/lib/subs/mission.c
src/lib/subs/satmap.c
src/lib/subs/sect.c
src/lib/update/age.c
src/lib/update/finish.c
src/lib/update/human.c
src/lib/update/ship.c

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 f3923066f852be019408af186aca14efc6b0cffb..feb47c6aef852c4b28fc9b570b18a8ae913e9b7b 100644 (file)
@@ -190,6 +190,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 5edadd9697c3cdeb6d3d55451a3dab19b145f993..a82f9f7ae1c9c5fc3335544f4118c36838613999 100644 (file)
@@ -627,6 +627,7 @@ extern void sathead(void);
 extern int sct_postread(int, void *);
 extern int sct_prewrite(int, void *);
 extern void item_prewrite(short *);
+extern void set_railway(struct sctstr *);
 extern int issector(char *);
 /* sectdamage.c */
 extern int sect_damage(struct sctstr *, int);
@@ -710,6 +711,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..da0e9cb1c9bcca5049de3250be27eb64781657fc 100644 (file)
@@ -76,6 +76,7 @@ struct sctstr {
     natid sct_oldown;          /* old owner of sector (for liberation) */
     unsigned char sct_updated; /* Has this sect been updated? */
     unsigned char sct_off;     /* Should this sector produce? */
+    unsigned char sct_track;   /* nearby railways (RAILWAYS) */
     short sct_item[I_MAX+1];   /* amount of items stored here */
     short sct_del[I_MAX+1];    /* delivieries */
     short sct_dist[I_MAX+1];   /* distribution thresholds */
@@ -181,6 +182,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 ? (sp)->sct_track != 0                       \
+     : intrchr[INT_RAIL].in_enable && (sp)->sct_rail != 0)
+
 #define MOB_MOVE    0
 #define MOB_MARCH   1
 #define MOB_RAIL    2
diff --git a/info/Hvy-Metal.t b/info/Hvy-Metal.t
new file mode 100644 (file)
index 0000000..95ca439
--- /dev/null
@@ -0,0 +1,97 @@
+.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 Io 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
+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 have amtraks,
+artilley 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 need construction
+materials to build efficiency.  Ever seen Fort Knox?  Bridges are
+cheaper than usual.
+.s1
+Food is much harder to grow.  Expect 20% of your population to be
+farmers.
+.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
+New experimental option AUTO_POWER is enabled: the power report is
+only updated automatically, at the update.  No more tactical abuse.
+.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/
+.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..f4ae420
--- /dev/null
@@ -0,0 +1,25 @@
+.TH Concept "Railroad"
+.NA Railroad "How railroads work"
+.LV Expert
+Trains are land units with capability \*Qtrain\*U.
+.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 reports show the rail infrastructure efficiency in colum \*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.  This number is also shown by spy
+report 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 0e0aa697b2c7e06a9ac8f9228e417b17060801bf..88ec909adc315a681095aa10f0f61f7e8a76aa65 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..e316f982271635f5c18212aa73eff2728ed03399 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(sect.sct_track ? "  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..8c3151f3831aab7125fb6a75d4b1c132f40bbf17 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 ? !!sp->sct_track : 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 18d748febafd698361b4ef4fe63a7d35be4cceca..f3377fe6d11be9d10cc94f9fc7c6524805849633 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "misc.h"
 #include "nat.h"
+#include "optlist.h"
 #include "path.h"
 #include "sect.h"
 #include "xy.h"
@@ -48,6 +49,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))
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..a67edc5c393284fde157eff00b44543948762c58 100644 (file)
@@ -153,6 +153,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", fldoff(sct_track), NSC_UCHAR, 0, NULL, EF_BAD, NSC_EXTRA},
     NSC_IVEC(fldoff(sct_item), ""),
     NSC_IVEC(fldoff(sct_dist), "_dist"),
     NSC_IVEC(fldoff(sct_del), "_del"),
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 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 cc4b06dbbfd810774f953b18142e85900a9ba29e..8e5fcb4fd3d8e3ee01158f628a57e892cc8b76ca 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 ? !!sp->sct_track : 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 541b9b9babfd31712b0f516f69e0fa5de0616662..87dd3fed790766c9ce3f13988775c456979fbc0a 100644 (file)
@@ -42,6 +42,7 @@
 #include "nat.h"
 #include "nsc.h"
 #include "optlist.h"
+#include "path.h"
 #include "plane.h"
 #include "player.h"
 #include "prototypes.h"
@@ -49,6 +50,7 @@
 #include "xy.h"
 
 static int checksect(struct sctstr *);
+static void update_railway(struct sctstr *, struct sctstr *);
 
 int
 sct_postread(int id, void *ptr)
@@ -71,6 +73,8 @@ sct_prewrite(int id, void *ptr)
     bridge_damaged(sp);
     checksect(sp);
     getsect(sp->sct_x, sp->sct_y, &sect);
+    if (opt_RAILWAYS)
+       update_railway(sp, &sect);
     return 1;
 }
 
@@ -128,6 +132,69 @@ checksect(struct sctstr *sp)
     return 1;
 }
 
+/* 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))
+
+static void
+update_railway(struct sctstr *sp, struct sctstr *oldsp)
+{
+    struct sctstr sect;
+    int was_railway = SCT_IS_RAILWAY(oldsp);
+    int is_railway = SCT_IS_RAILWAY(sp);
+    int i;
+
+    if (was_railway == is_railway
+       && sp->sct_own == oldsp->sct_own
+       && SCT_MAY_HAVE_RAIL_EXT(sp) == SCT_MAY_HAVE_RAIL_EXT(oldsp))
+       return;
+
+    if (was_railway)
+       sp->sct_track--;
+    if (is_railway)
+       sp->sct_track++;
+
+    for (i = DIR_FIRST; i <= DIR_LAST; i++) {
+       getsect(sp->sct_x + diroff[i][0],
+               sp->sct_y + diroff[i][1],
+               &sect);
+       if (SCT_IS_RAILWAY(&sect) && SCT_EXTENDS_RAIL(&sect, oldsp))
+           sp->sct_track--;
+       if (SCT_IS_RAILWAY(&sect) && SCT_EXTENDS_RAIL(&sect, sp))
+           sp->sct_track++;
+       if (was_railway && SCT_EXTENDS_RAIL(oldsp, &sect))
+           sect.sct_track--;
+       if (is_railway && SCT_EXTENDS_RAIL(sp, &sect))
+           sect.sct_track++;
+       putsect(&sect);
+    }
+}
+
+void
+set_railway(struct sctstr *sp)
+{
+    int i;
+    struct sctstr *nsp;
+
+    sp->sct_track = !!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))
+           sp->sct_track++;
+    }
+}
+
 int
 issector(char *arg)
 {
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 da03cee164c04f4ca5299c9fd797a34cd007f864..8c2693ce91520ca2202edd66f126b849fe207a99 100644 (file)
@@ -87,6 +87,11 @@ finish_sects(int etu)
     /* Wipe it clean */
     memset(g_distptrs, 0, WORLD_SZ() * sizeof(*g_distptrs));
 
+    if (opt_RAILWAYS) {
+       for (n = 0; NULL != (sp = getsectid(n)); n++)
+           set_railway(sp);
+    }
+
     logerror("delivering...\n");
     /* Do deliveries */
     for (n = 0; NULL != (sp = getsectid(n)); n++) {
index 1a7b1c5fcb46b4f606f6e4a86681d463fcb2f162..9206edf11c390c224978baa1fd54aad60f588cd6 100644 (file)
@@ -109,6 +109,17 @@ 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);
+           }
        }
     } else
        sctwork = sp->sct_work = 100;
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],