diff --git a/include/econfig-spec.h b/include/econfig-spec.h index bc4ccc6a..d426e58a 100644 --- a/include/econfig-spec.h +++ b/include/econfig-spec.h @@ -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, diff --git a/include/land.h b/include/land.h index f3923066..feb47c6a 100644 --- a/include/land.h +++ b/include/land.h @@ -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); diff --git a/include/prototypes.h b/include/prototypes.h index 5edadd96..a82f9f7a 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -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); diff --git a/include/sect.h b/include/sect.h index c0d78222..da0e9cb1 100644 --- a/include/sect.h +++ b/include/sect.h @@ -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 index 00000000..95ca4392 --- /dev/null +++ b/info/Hvy-Metal.t @@ -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" diff --git a/info/Options.t b/info/Options.t index 07f165c5..99450c9c 100644 --- a/info/Options.t +++ b/info/Options.t @@ -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 index 00000000..f4ae420f --- /dev/null +++ b/info/Railroad.t @@ -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" diff --git a/info/Unit-types.t b/info/Unit-types.t index 1a0cca53..5c956734 100644 --- a/info/Unit-types.t +++ b/info/Unit-types.t @@ -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" - diff --git a/src/lib/commands/mfir.c b/src/lib/commands/mfir.c index 0e0aa697..88ec909a 100644 --- a/src/lib/commands/mfir.c +++ b/src/lib/commands/mfir.c @@ -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); diff --git a/src/lib/commands/miss.c b/src/lib/commands/miss.c index abf9d16f..f44656db 100644 --- a/src/lib/commands/miss.c +++ b/src/lib/commands/miss.c @@ -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; diff --git a/src/lib/commands/sinf.c b/src/lib/commands/sinf.c index e17cf3f7..e316f982 100644 --- a/src/lib/commands/sinf.c +++ b/src/lib/commands/sinf.c @@ -73,7 +73,10 @@ sinfra(void) pr("%4d%% ", sect.sct_effic); pr("%4d%% ", sect.sct_road); prmobcost(§, MOB_MOVE); - pr("%4d%% ", sect.sct_rail); + if (opt_RAILWAYS) + pr(sect.sct_track ? " yes " : " no "); + else + pr("%4d%% ", sect.sct_rail); prmobcost(§, MOB_RAIL); pr("%4d%% ", SCT_DEFENSE(§)); pr("%5.2f\n", sector_strength(§)); diff --git a/src/lib/commands/spy.c b/src/lib/commands/spy.c index 291ab46b..8c3151f3 100644 --- a/src/lib/commands/spy.c +++ b/src/lib/commands/spy.c @@ -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), diff --git a/src/lib/common/move.c b/src/lib/common/move.c index 18d748fe..f3377fe6 100644 --- a/src/lib/common/move.c +++ b/src/lib/common/move.c @@ -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)) diff --git a/src/lib/common/path.c b/src/lib/common/path.c index 61bf4e7b..53149a6e 100644 --- a/src/lib/common/path.c +++ b/src/lib/common/path.c @@ -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; diff --git a/src/lib/global/nsc.c b/src/lib/global/nsc.c index 205ae005..a67edc5c 100644 --- a/src/lib/global/nsc.c +++ b/src/lib/global/nsc.c @@ -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"), diff --git a/src/lib/global/options.c b/src/lib/global/options.c index 02753e45..67dd12be 100644 --- a/src/lib/global/options.c +++ b/src/lib/global/options.c @@ -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; diff --git a/src/lib/subs/landgun.c b/src/lib/subs/landgun.c index 151679a4..a6a21da9 100644 --- a/src/lib/subs/landgun.c +++ b/src/lib/subs/landgun.c @@ -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, §); + return effrange(lnd_frg(lp), lp->lnd_tech) + + (sect.sct_type == SCT_MOUNT ? 0.5 : 0.0); } int diff --git a/src/lib/subs/lndsub.c b/src/lib/subs/lndsub.c index 395ffcf2..578c1af0 100644 --- a/src/lib/subs/lndsub.c +++ b/src/lib/subs/lndsub.c @@ -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(§) && 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; diff --git a/src/lib/subs/mission.c b/src/lib/subs/mission.c index e038c12c..340f2f57 100644 --- a/src/lib/subs/mission.c +++ b/src/lib/subs/mission.c @@ -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); diff --git a/src/lib/subs/satmap.c b/src/lib/subs/satmap.c index cc4b06db..8e5fcb4f 100644 --- a/src/lib/subs/satmap.c +++ b/src/lib/subs/satmap.c @@ -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), diff --git a/src/lib/subs/sect.c b/src/lib/subs/sect.c index 541b9b9b..87dd3fed 100644 --- a/src/lib/subs/sect.c +++ b/src/lib/subs/sect.c @@ -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, §); + if (opt_RAILWAYS) + update_railway(sp, §); 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], + §); + if (SCT_IS_RAILWAY(§) && SCT_EXTENDS_RAIL(§, oldsp)) + sp->sct_track--; + if (SCT_IS_RAILWAY(§) && SCT_EXTENDS_RAIL(§, sp)) + sp->sct_track++; + if (was_railway && SCT_EXTENDS_RAIL(oldsp, §)) + sect.sct_track--; + if (is_railway && SCT_EXTENDS_RAIL(sp, §)) + sect.sct_track++; + putsect(§); + } +} + +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) { diff --git a/src/lib/update/age.c b/src/lib/update/age.c index 29dca549..98cecaab 100644 --- a/src/lib/update/age.c +++ b/src/lib/update/age.c @@ -35,6 +35,13 @@ #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; diff --git a/src/lib/update/finish.c b/src/lib/update/finish.c index da03cee1..8c2693ce 100644 --- a/src/lib/update/finish.c +++ b/src/lib/update/finish.c @@ -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++) { diff --git a/src/lib/update/human.c b/src/lib/update/human.c index 1a7b1c5f..9206edf1 100644 --- a/src/lib/update/human.c +++ b/src/lib/update/human.c @@ -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; diff --git a/src/lib/update/ship.c b/src/lib/update/ship.c index 59546ddb..cccbe260 100644 --- a/src/lib/update/ship.c +++ b/src/lib/update/ship.c @@ -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],