Merge up to v4.3.14. No functional change.
$(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))
/* 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 */
"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,
"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,
*/
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 */
struct emptypedstr {
short ef_type;
short uid;
+ unsigned seqno;
time_t timestamp;
};
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);
/* 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? */
/* 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 */
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);
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 # */
/* 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 */
/* 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 */
* 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);
/* 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 */
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 */
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
#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
extern struct sctintrins intrchr[INT_DEF + 2];
extern int fort_fire(struct sctstr *);
+extern int sct_rail_track(struct sctstr *);
#endif
/* 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 */
/* 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 */
/* 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 */
--- /dev/null
+.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"
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"
--- /dev/null
+.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"
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.
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
.FI
.s1
.SA "land, LandUnits"
-
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));
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) {
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)
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(§);
- }
}
if (changed)
writemap(player->cnum);
return RET_SYN;
sect->sct_x = newx;
sect->sct_y = newy;
- sect->sct_uid = XYOFFSET(newx, newy);
+ ef_set_uid(EF_SECTOR, §, XYOFFSET(newx, newy));
break;
case 'D':
if (!sarg_xy(p, &newx, &newy))
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)
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)
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))
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;
pr("Klick! ...\n");
continue;
}
+
+ lnd_unlimber(&fland);
if (target == targ_ship) {
if (chance(lnd_acc(&fland) / 100.0))
dam = ldround(dam / 2.0, 1);
/* 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);
if (dam2 < 0)
continue;
+ lnd_unlimber(&land);
(*nfiring)++;
if (!fp)
add_to_flist(list, (struct empobj *)&land, dam2, 0);
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;
pr("%4d%% ", sect.sct_effic);
pr("%4d%% ", sect.sct_road);
prmobcost(§, MOB_MOVE);
- pr("%4d%% ", sect.sct_rail);
+ if (opt_RAILWAYS)
+ pr(sct_rail_track(§) ? " yes " : " no ");
+ else
+ pr("%4d%% ", sect.sct_rail);
prmobcost(§, MOB_RAIL);
pr("%4d%% ", SCT_DEFENSE(§));
pr("%5.2f\n", sector_strength(§));
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),
/* 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, §a, 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, §b, tmp.sct_uid);
sectb.sct_dist_x = tmp.sct_x;
sectb.sct_dist_y = tmp.sct_y;
sectb.sct_coastal = tmp.sct_coastal;
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);
/*
*/
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) {
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;
}
}
- 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;
}
/*
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;
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.
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);
+ }
}
/*
#include <config.h>
+#include "file.h"
#include "misc.h"
#include "nat.h"
+#include "optlist.h"
#include "path.h"
#include "sect.h"
#include "xy.h"
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))
{
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;
+}
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;
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 *);
{"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"),
{"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},
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)
{
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;
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;
# 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
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;
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.sct_type != SCT_WATER)) {
pr("%s can not %s from that far inland!\n",
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);
}
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) {
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
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));
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) &&
if (dam2 < 0)
continue;
+ lnd_unlimber(&land);
if (defending)
nreport(land.lnd_own, N_FIRE_BACK, victim, 1);
else
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;
(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;
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);
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);
}
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;
}
}
}
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;
}
getsect(newx, newy, §);
if (shp_check_nav(§, 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],
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),
navigate = shp_check_nav(§, &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) &&
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;
#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)
{
int i;
double level;
double delta;
- int deltares;
best_tech = 0.0;
best_res = 0.0;
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;
int starved, sctwork;
int needed;
int maxpop;
+ int manna;
/* grow people & stuff */
sctwork = sp->sct_work;
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,
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 */
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;
}
/* 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],
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++;
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));
for (j = 0; j < MAXNOR; j++) {
realm.r_realm = j;
realm.r_uid = (i * MAXNOR) + j;
+ realm.r_seqno = 0;
putrealm(&realm);
}
}
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;