Compare commits
54 commits
master
...
hvy-metal-
Author | SHA1 | Date | |
---|---|---|---|
342ab5c22a | |||
59bdc1cbcc | |||
321d6d74c7 | |||
9398627ec4 | |||
cb1c9f6a19 | |||
a87f73a3b5 | |||
3afc1b1989 | |||
b9b0710128 | |||
80b57b2f95 | |||
3c3912420b | |||
18ae6c5f78 | |||
6aefeea2a1 | |||
1713f2d303 | |||
84d40a6057 | |||
fbefc139f4 | |||
c40dd61bf0 | |||
2b90a5230d | |||
0a7437bc43 | |||
d0210443ff | |||
a4b550a1a2 | |||
07d2c38a73 | |||
b8bdc32b3c | |||
dfcc13abdd | |||
080e8db899 | |||
2410535a05 | |||
d3a2130b26 | |||
e1283b118a | |||
7dc0f48868 | |||
e2eccc5740 | |||
c083a25277 | |||
6e69d6d9de | |||
5a2440c9d4 | |||
45a6b9a1d7 | |||
542460c787 | |||
312b28f5fa | |||
e7aa3627c4 | |||
8fe67826e6 | |||
05e5adfac8 | |||
cf4639fa74 | |||
b707e2cca8 | |||
4e962406ff | |||
f7d6181717 | |||
b313b61cd4 | |||
e917a60371 | |||
12e34aeeb4 | |||
fa5fa4abcc | |||
11100f23e5 | |||
b437b7b5ec | |||
95298986cc | |||
dc9d847b8b | |||
2aec870a14 | |||
e3658ff2f0 | |||
![]() |
9f1b4e2c81 | ||
![]() |
5d0f5e69ee |
74 changed files with 766 additions and 243 deletions
1
Make.mk
1
Make.mk
|
@ -284,6 +284,7 @@ ifeq ($(empthread),Windows)
|
|||
$(client): src/lib/w32/getopt.o
|
||||
endif
|
||||
|
||||
$(util): src/lib/common/move.o # FIXME hack for opt_RAILWAYS
|
||||
$(util): $(libs)
|
||||
|
||||
lib/libas.a: $(filter src/lib/as/%, $(obj))
|
||||
|
|
|
@ -44,6 +44,7 @@ struct comstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short com_uid;
|
||||
unsigned com_seqno;
|
||||
time_t com_timestamp;
|
||||
natid com_owner;
|
||||
/* end of part matching struct empobj */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -57,6 +57,7 @@ struct empobj {
|
|||
*/
|
||||
short ef_type;
|
||||
short uid;
|
||||
unsigned seqno;
|
||||
time_t timestamp;
|
||||
/* end of part matching struct emptypedstr */
|
||||
natid own; /* valid if EFF_OWNER is in table's flags */
|
||||
|
|
|
@ -67,6 +67,7 @@ struct empfile {
|
|||
struct emptypedstr {
|
||||
short ef_type;
|
||||
short uid;
|
||||
unsigned seqno;
|
||||
time_t timestamp;
|
||||
};
|
||||
|
||||
|
@ -187,6 +188,7 @@ extern int ef_close(int);
|
|||
extern int ef_flush(int);
|
||||
extern void ef_blank(int, int, void *);
|
||||
extern int ef_write(int, int, void *);
|
||||
extern void ef_set_uid(int, void *, int);
|
||||
extern int ef_extend(int, int);
|
||||
extern int ef_ensure_space(int, int, int);
|
||||
extern int ef_truncate(int, int);
|
||||
|
|
|
@ -40,6 +40,7 @@ struct gamestr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short game_uid;
|
||||
unsigned game_seqno;
|
||||
time_t game_timestamp;
|
||||
/* end of part matching struct empobj */
|
||||
char game_upd_disable; /* updates disabled? */
|
||||
|
|
|
@ -34,13 +34,17 @@
|
|||
#ifndef JOURNAL_H
|
||||
#define JOURNAL_H
|
||||
|
||||
struct player; /* FIXME temporary hack */
|
||||
|
||||
int journal_startup(void);
|
||||
void journal_shutdown(void);
|
||||
int journal_reopen(void);
|
||||
void journal_login(void);
|
||||
void journal_logout(void);
|
||||
void journal_prng(unsigned);
|
||||
void journal_output(struct player *, int, char *);
|
||||
void journal_input(char *);
|
||||
void journal_command(char *);
|
||||
void journal_update(int);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,7 @@ struct lndstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short lnd_uid; /* unit id (land unit) */
|
||||
unsigned lnd_seqno;
|
||||
time_t lnd_timestamp; /* Last time this unit was touched */
|
||||
natid lnd_own; /* owner's country num */
|
||||
coord lnd_x; /* x location in abs coords */
|
||||
|
@ -190,6 +191,7 @@ extern int lnd_hardtarget(struct lndstr *);
|
|||
extern int lnd_mar_one_sector(struct emp_qelem *, int, natid, int);
|
||||
extern int lnd_support(natid, natid, coord, coord, int);
|
||||
extern int lnd_can_attack(struct lndstr *);
|
||||
extern void lnd_unlimber(struct lndstr *lp);
|
||||
extern int lnd_fortify (struct lndstr *lp, int hard_amt);
|
||||
extern void lnd_set_tech(struct lndstr *, int);
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ struct lonstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short l_uid;
|
||||
unsigned l_seqno;
|
||||
time_t l_timestamp;
|
||||
/* end of part matching struct empobj */
|
||||
natid l_loner; /* loan shark */
|
||||
|
|
|
@ -40,7 +40,8 @@
|
|||
struct loststr {
|
||||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
int lost_uid;
|
||||
short 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 */
|
||||
|
|
|
@ -70,6 +70,7 @@ struct realmstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short r_uid; /* realm table index */
|
||||
unsigned r_seqno;
|
||||
time_t r_timestamp; /* Last time this realm was touched */
|
||||
natid r_cnum; /* country number */
|
||||
/* end of part matching struct empobj */
|
||||
|
@ -82,6 +83,7 @@ struct natstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short nat_uid; /* equals nat_cnum */
|
||||
unsigned nat_seqno;
|
||||
time_t nat_timestamp;
|
||||
natid nat_cnum; /* our country number */
|
||||
/* end of part matching struct empobj */
|
||||
|
|
|
@ -48,6 +48,7 @@ struct nwsstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short nws_uid;
|
||||
unsigned nws_seqno;
|
||||
time_t nws_timestamp;
|
||||
/* end of part matching struct empobj */
|
||||
natid nws_ano; /* "actor" country # */
|
||||
|
|
|
@ -44,6 +44,7 @@ struct nukstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short nuk_uid;
|
||||
unsigned nuk_seqno;
|
||||
time_t nuk_timestamp; /* Last time this nuke was touched */
|
||||
natid nuk_own;
|
||||
coord nuk_x, nuk_y; /* current loc of device */
|
||||
|
|
|
@ -48,6 +48,7 @@ struct plnstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short pln_uid; /* plane unit id */
|
||||
unsigned pln_seqno;
|
||||
time_t pln_timestamp; /* Last time this plane was touched */
|
||||
natid pln_own; /* owning country */
|
||||
coord pln_x; /* plane x-y */
|
||||
|
|
|
@ -76,8 +76,9 @@ struct player {
|
|||
int simulation; /* e.g. budget command */
|
||||
double dolcost;
|
||||
time_t curup; /* when last input was received */
|
||||
int aborted; /* interrupt cookie received? */
|
||||
int aborted; /* interrupt cookie or EOF received? */
|
||||
int eof; /* EOF (cookie or real) received? */
|
||||
int recvfail; /* #recvclient() failures */
|
||||
int curid; /* for pr, cur. line's id, -1 none */
|
||||
char *map; /* pointer to in-mem map */
|
||||
char *bmap; /* pointer to in-mem bmap */
|
||||
|
|
|
@ -282,8 +282,6 @@ extern int logreopen(void);
|
|||
extern void logerror(char *, ...) ATTRIBUTE((format (printf, 1, 2)));
|
||||
/* more in misc.h */
|
||||
/* mapdist.c */
|
||||
extern int diffx(int, int);
|
||||
extern int diffy(int, int);
|
||||
extern int deltax(int, int);
|
||||
extern int deltay(int, int);
|
||||
extern int mapdist(int, int, int, int);
|
||||
|
@ -710,6 +708,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);
|
||||
|
|
|
@ -46,6 +46,7 @@ struct sctstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short sct_uid; /* equals XYOFFSET(sct_x, sct_y) */
|
||||
unsigned sct_seqno;
|
||||
time_t sct_timestamp; /* Last time this sector was written to */
|
||||
natid sct_own; /* owner's country num */
|
||||
coord sct_x; /* x coord of sector */
|
||||
|
@ -102,6 +103,7 @@ enum d_navigation {
|
|||
struct dchrstr {
|
||||
unsigned char d_uid;
|
||||
char d_mnem; /* map symbol */
|
||||
unsigned char d_terrain; /* terrain sector type */
|
||||
int d_prd; /* product type */
|
||||
int d_peffic; /* process efficiency, in percent */
|
||||
float d_mob0, d_mob1; /* movement cost at 0 and 100% eff */
|
||||
|
@ -169,6 +171,9 @@ extern struct dchrstr dchr[SCT_TYPE_MAX + 2];
|
|||
extern struct dchrstr bigcity_dchr;
|
||||
#define IS_BIG_CITY(type) (dchr[(type)].d_pkg == UPKG)
|
||||
|
||||
#define IS_BRIDGE_HEAD(type) \
|
||||
((type) == SCT_BHEAD || (type) == SCT_HIWAY || (type) == SCT_BTOWER)
|
||||
|
||||
/* Minimal efficiency of sectors that can be knocked down (bridges) */
|
||||
#define SCT_MINEFF 20
|
||||
|
||||
|
@ -181,6 +186,11 @@ extern struct dchrstr bigcity_dchr;
|
|||
|
||||
#define FORTEFF 5 /* forts must be 5% efficient to fire. */
|
||||
|
||||
/* Can trains enter sector SP? */
|
||||
#define SCT_HAS_RAIL(sp) \
|
||||
(opt_RAILWAYS ? sct_rail_track((sp)) != 0 \
|
||||
: intrchr[INT_RAIL].in_enable && (sp)->sct_rail != 0)
|
||||
|
||||
#define MOB_MOVE 0
|
||||
#define MOB_MARCH 1
|
||||
#define MOB_RAIL 2
|
||||
|
@ -216,5 +226,6 @@ struct sctintrins {
|
|||
extern struct sctintrins intrchr[INT_DEF + 2];
|
||||
|
||||
extern int fort_fire(struct sctstr *);
|
||||
extern int sct_rail_track(struct sctstr *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,6 +65,7 @@ struct shpstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short shp_uid; /* unit id (ship #) */
|
||||
unsigned shp_seqno;
|
||||
time_t shp_timestamp; /* Last time this ship was touched. */
|
||||
natid shp_own; /* owner's country num */
|
||||
coord shp_x; /* x location in abs coords */
|
||||
|
|
|
@ -44,6 +44,7 @@ struct trdstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short trd_uid;
|
||||
unsigned trd_seqno;
|
||||
time_t trd_timestamp;
|
||||
natid trd_owner;
|
||||
/* end of part matching struct empobj */
|
||||
|
|
|
@ -41,6 +41,7 @@ struct trtstr {
|
|||
/* initial part must match struct empobj */
|
||||
short ef_type;
|
||||
short trt_uid;
|
||||
unsigned trt_seqno;
|
||||
time_t trt_timestamp;
|
||||
/* end of part matching struct empobj */
|
||||
natid trt_cna; /* proposer */
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
#define XYOFFSET(x, y) (((y) * WORLD_X + (x)) / 2)
|
||||
|
||||
#define XNORM(x) \
|
||||
(((x) < 0) ? (WORLD_X - (-(x) % WORLD_X)) : ((x) % WORLD_X))
|
||||
(((x) < 0) ? (WORLD_X - 1 - ((-(x) - 1) % WORLD_X)) : ((x) % WORLD_X))
|
||||
#define YNORM(y) \
|
||||
(((y) < 0) ? (WORLD_Y - (-(y) % WORLD_Y)) : ((y) % WORLD_Y))
|
||||
(((y) < 0) ? (WORLD_Y - 1 - ((-(y) - 1) % WORLD_Y)) : ((y) % WORLD_Y))
|
||||
|
||||
struct range {
|
||||
coord lx; /* low-range x,y */
|
||||
|
|
43
info/BTU.t
43
info/BTU.t
|
@ -14,7 +14,7 @@ do.
|
|||
BTUs are generated in real-time based on the number of civilians that
|
||||
are in your capital. Every time you log out and in again, the server
|
||||
calculates how long you've been away, and based on that time awards
|
||||
you a certain number of BTUs.
|
||||
you a certain number of BTUs. The same happens at the update.
|
||||
.s1
|
||||
Here is the procedure for determining how many BTUs you get:
|
||||
.nf
|
||||
|
@ -27,43 +27,46 @@ they are automatically set back to the maximum.
|
|||
|
||||
(2) Find out how many civs are required to make one BTU in one time unit.
|
||||
The "version" command will tell you how many civilians are required to
|
||||
produce one BTU in one Empire Time Unit (ETU).
|
||||
produce one BTU in one Empire Time Unit (ETU) in a perfectly efficient
|
||||
capital.
|
||||
|
||||
(3) Calculate how many BTUs your cap produces in one time unit.
|
||||
(3) Calculate how efficiently your capital makes BTUs. A proper
|
||||
capital's BTU efficiency is sector efficiency times work percentage,
|
||||
but at least 0.5%. A mountain capital's BTU efficiency is always
|
||||
0.5%.
|
||||
|
||||
(4) Calculate how many BTUs your capital produces in one time unit.
|
||||
Divide the number of civs generating BTUs (step 1) by the number of
|
||||
civs required to produce one BTU in one time unit (step 2). If your
|
||||
capital is in a mountain or has zero efficiency, then multiply by
|
||||
1/200. Otherwise, multiply by (sector efficiency) / 100. Note that
|
||||
0% capitals and mountains generate BTUs as if they were 0.5% capitals.
|
||||
civs required to produce one BTU in one time unit (step 2). Multiply
|
||||
by efficiency (step 3).
|
||||
|
||||
(4) Find out how many time units have passed.
|
||||
(5) Find out how many time units have passed since you last got BTUs.
|
||||
A fixed number of ETUs elapse between updates. The \*Qversion\*U
|
||||
command shows how many.
|
||||
|
||||
(5) Calculate how many BTUs you get.
|
||||
Multiply the number of BTUs your cap produces in one ETU (step 3) by
|
||||
the number of ETUs which have passed (step 4). This is how many BTUs
|
||||
(6) Calculate how many BTUs you get.
|
||||
Multiply the number of BTUs your cap produces in one ETU (step 4) by
|
||||
the number of ETUs which have passed (step 5). This is how many BTUs
|
||||
you get. Note that there is a limit to how many BTUs you can have at
|
||||
any given time. This number is usually 640 but can be changed by the deity.
|
||||
|
||||
EXAMPLE: say you had a 100% capital containing 500 civs.
|
||||
Suppose that version said:
|
||||
EXAMPLE: say your capital is in perfect condition (100% efficiency and
|
||||
work), and has 500 civilians. Suppose that version said:
|
||||
|
||||
It takes 25.00 civilians to produce a BTU in one time unit
|
||||
|
||||
Then first you would divide 500 by 25 to get 20. Now since your cap
|
||||
is 100% efficient, you would multiply 20 by (100/100) and so the civs
|
||||
in your cap would produce 20 BTUs per time unit. Now suppose that
|
||||
is 100% efficient and 100% working, its BTU efficiency is 100% * 100%
|
||||
= 100%, i.e. your capital makes 20 BTUs per ETU. Now suppose that
|
||||
version said:
|
||||
|
||||
An update consists of 60 empire time units.
|
||||
|
||||
and suppose that exactly that many had passed since the last time you
|
||||
logged on.
|
||||
Lastly, we multiply 20 by 60 to get 1200 BTUs. But since the
|
||||
maximum is 640, we would have 640 BTUs. Note that if your capital had
|
||||
been in a mountain sector, then you would have only gotten 6 BTUs in
|
||||
24 hours.
|
||||
got BTUs. You multiply 20 by 60 and get 1200 BTUs. But since the
|
||||
maximum is 640, you'd have 640 BTUs. Note that if your capital were a
|
||||
mountain sector, it would make only 20 * 0.5% = 0.1 BTUs per time
|
||||
unit. You'd get only 6 BTUs then.
|
||||
.fi
|
||||
.s1
|
||||
.SA "Innards, version, Time, Playing"
|
||||
|
|
|
@ -32,7 +32,7 @@ sector is too small, or if the sector starves, disloyalty will
|
|||
increase.
|
||||
.s1
|
||||
If a sector is a conquered sector,
|
||||
a star \*Q*\*U will be shown in the appropriate column
|
||||
the old owner will be shown in the appropriate column
|
||||
on the census report.
|
||||
Friendly sectors allow enlistment of military,
|
||||
as well as the ability to move the civilians freely about.
|
||||
|
|
120
info/Hvy-Metal.t
Normal file
120
info/Hvy-Metal.t
Normal file
|
@ -0,0 +1,120 @@
|
|||
.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 info
|
||||
\*QRailroad\*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, ship flak and ship missile
|
||||
defense is disabled, because its bugs interfere with Hvy Metal
|
||||
modifications. Same for automatic supply of land units on loading
|
||||
them onto ships or land units.
|
||||
.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"
|
|
@ -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"
|
||||
|
|
|
@ -22,7 +22,7 @@ Sector-types:
|
|||
(Petrol is per 10 units; others per unit)
|
||||
|
||||
Products:
|
||||
Item $ Lcm Hcm Iron Dust Oil Rad Tech Production Eff.
|
||||
Item $ Lcm Hcm Iron Dust Oil Food Tech Production Eff.
|
||||
Shells: 3 2 1 0 0 0 0 20 (tech-20)/(tech-10)
|
||||
Guns: 30 5 10 0 0 1 0 20 (tech-20)/(tech-10)
|
||||
Iron: 0 0 0 0 0 0 0 0 0
|
||||
|
@ -30,6 +30,7 @@ Dust: 0 0 0 0 0 0 0 0 0
|
|||
Bars: 10 0 0 0 5 0 0 0 0
|
||||
Food: 0 0 0 0 0 0 0 0 (tech+10)/(tech+20)
|
||||
Oil: 0 0 0 0 0 0 0 0 (tech+10)/(tech+20)
|
||||
Biofuel 10 0 0 0 0 0 5 150 (tech+150)/(tech+230)
|
||||
Petrol 1 0 0 0 0 1 0 20 (tech-20)/(tech-10)
|
||||
Lcm: 0 0 0 1 0 0 0 0 (tech+10)/(tech+20)
|
||||
Hcm: 0 0 0 2 0 0 0 0 (tech+10)/(tech+20)
|
||||
|
|
27
info/Railroad.t
Normal file
27
info/Railroad.t
Normal file
|
@ -0,0 +1,27 @@
|
|||
.TH Concept "Railroad"
|
||||
.NA Railroad "How railroads work"
|
||||
.LV Expert
|
||||
Trains are land units with capability \*Qtrain\*U. They can't be
|
||||
loaded on land units, but they can be loaded on ships, subject to the
|
||||
usual restrictions for non-light and heavy land units.
|
||||
.s1
|
||||
Unlike other units, trains can enter a sector only if it has
|
||||
(operational) railroad track.
|
||||
.s1
|
||||
If option RAILWAYS is disabled, a sector has railroad track as long as
|
||||
its rail infrastructure efficiency is non-zero. Train mobility cost
|
||||
depends on rail infrastructure efficiency (see \*Qinfo Mobility\*U).
|
||||
Spy and satellite reports show approximate rail infrastructure
|
||||
efficiency in column \*Qrl eff\*U.
|
||||
.s1
|
||||
If option RAILWAYS is enabled, all highway-like sectors are railways,
|
||||
and the track is operational as long as the sector is at least 5%
|
||||
efficient. A sector is highway-like if its mobility cost at 100% is
|
||||
zero (column mob cost in \*Qshow sect s\*u). Operational railways
|
||||
additionally extend track into adjacent sectors that are at least 60%
|
||||
efficient and owned by the same nation. 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"
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -154,13 +154,8 @@ add(void)
|
|||
sect.sct_defense = 0;
|
||||
sect.sct_own = 0;
|
||||
sect.sct_oldown = 0;
|
||||
if (sect.sct_type == SCT_BSPAN ||
|
||||
sect.sct_type == SCT_BTOWER)
|
||||
sect.sct_newtype = sect.sct_type = SCT_WATER;
|
||||
else if (sect.sct_type != SCT_MOUNT &&
|
||||
sect.sct_type != SCT_PLAINS)
|
||||
sect.sct_newtype = sect.sct_type = SCT_RURAL;
|
||||
/* No dist path */
|
||||
sect.sct_newtype = sect.sct_type
|
||||
= dchr[sect.sct_type].d_terrain;
|
||||
sect.sct_dist_x = sect.sct_x;
|
||||
sect.sct_dist_y = sect.sct_y;
|
||||
memset(sect.sct_item, 0, sizeof(sect.sct_item));
|
||||
|
|
|
@ -528,12 +528,10 @@ build_bridge(struct sctstr *sp, short *vec)
|
|||
char buf[1024];
|
||||
|
||||
if (opt_EASY_BRIDGES == 0) { /* must have a bridge head or tower */
|
||||
if (sp->sct_type != SCT_BTOWER) {
|
||||
if (sp->sct_type != SCT_BHEAD)
|
||||
return 0;
|
||||
if (sp->sct_newtype != SCT_BHEAD)
|
||||
return 0;
|
||||
}
|
||||
if (!IS_BRIDGE_HEAD(sp->sct_type))
|
||||
return 0;
|
||||
if (sp->sct_newtype != sp->sct_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sp->sct_effic < 60 && !player->god) {
|
||||
|
|
|
@ -92,12 +92,17 @@ desi(void)
|
|||
pr("Only %s can make a %s!\n", cname(0), dchr[des].d_name);
|
||||
continue;
|
||||
}
|
||||
if (dchr[des].d_terrain != dchr[sect.sct_type].d_terrain) {
|
||||
pr("You can't change a %s into a %s\n",
|
||||
dchr[sect.sct_type].d_name, dchr[des].d_name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (sect.sct_type == des && sect.sct_newtype == des)
|
||||
continue;
|
||||
if (sect.sct_type == SCT_SANCT)
|
||||
breaksanct++;
|
||||
if ((des == SCT_HARBR || des == SCT_BHEAD) && !sect.sct_coastal) {
|
||||
if (des == SCT_HARBR && !sect.sct_coastal) {
|
||||
pr("%s does not border on water.\n",
|
||||
xyas(nstr.x, nstr.y, player->cnum));
|
||||
if (player->god)
|
||||
|
@ -129,11 +134,8 @@ desi(void)
|
|||
if (sect.sct_x == cap_x && sect.sct_y == cap_y
|
||||
&& des != SCT_CAPIT && des != SCT_SANCT && des != SCT_MOUNT)
|
||||
pr("You have redesignated your capital!\n");
|
||||
if (opt_EASY_BRIDGES == 0) { /* may cause a bridge fall */
|
||||
if (n != SCT_BHEAD)
|
||||
continue;
|
||||
if (!opt_EASY_BRIDGES && IS_BRIDGE_HEAD(n))
|
||||
bridgefall(§);
|
||||
}
|
||||
}
|
||||
if (changed)
|
||||
writemap(player->cnum);
|
||||
|
|
|
@ -191,12 +191,16 @@ edit(void)
|
|||
return err;
|
||||
break;
|
||||
case 'l':
|
||||
if (!check_sect_ok(§))
|
||||
return RET_FAIL;
|
||||
if ((err = doland(thing, arg, ptr, §)) != RET_OK)
|
||||
return err;
|
||||
if (!putsect(§))
|
||||
return RET_FAIL;
|
||||
break;
|
||||
case 's':
|
||||
if (!check_ship_ok(&ship))
|
||||
return RET_FAIL;
|
||||
if ((err = doship(thing, arg, ptr, &ship)) != RET_OK)
|
||||
return err;
|
||||
if (!ef_ensure_space(EF_SHIP, ship.shp_uid, 50))
|
||||
|
@ -205,6 +209,8 @@ edit(void)
|
|||
return RET_FAIL;
|
||||
break;
|
||||
case 'u':
|
||||
if (!check_land_ok(&land))
|
||||
return RET_FAIL;
|
||||
if ((err = dounit(thing, arg, ptr, &land)) != RET_OK)
|
||||
return err;
|
||||
if (!ef_ensure_space(EF_LAND, land.lnd_uid, 50))
|
||||
|
@ -213,6 +219,8 @@ edit(void)
|
|||
return RET_FAIL;
|
||||
break;
|
||||
case 'p':
|
||||
if (!check_plane_ok(&plane))
|
||||
return RET_FAIL;
|
||||
if ((err = doplane(thing, arg, ptr, &plane)) != RET_OK)
|
||||
return err;
|
||||
if (!ef_ensure_space(EF_PLANE, plane.pln_uid, 50))
|
||||
|
@ -584,7 +592,7 @@ doland(char op, int arg, char *p, struct sctstr *sect)
|
|||
return RET_SYN;
|
||||
sect->sct_x = newx;
|
||||
sect->sct_y = newy;
|
||||
sect->sct_uid = XYOFFSET(newx, newy);
|
||||
ef_set_uid(EF_SECTOR, §, XYOFFSET(newx, newy));
|
||||
break;
|
||||
case 'D':
|
||||
if (!sarg_xy(p, &newx, &newy))
|
||||
|
@ -767,7 +775,7 @@ doship(char op, int arg, char *p, struct shpstr *ship)
|
|||
ship->shp_rflags = arg;
|
||||
break;
|
||||
case 'U':
|
||||
ship->shp_uid = arg;
|
||||
ef_set_uid(EF_SHIP, ship, arg);
|
||||
break;
|
||||
case 'O':
|
||||
if (ship->shp_own)
|
||||
|
@ -871,7 +879,7 @@ dounit(char op, int arg, char *p, struct lndstr *land)
|
|||
land->lnd_land = arg;
|
||||
break;
|
||||
case 'U':
|
||||
land->lnd_uid = arg;
|
||||
ef_set_uid(EF_LAND, land, arg);
|
||||
break;
|
||||
case 'O':
|
||||
if (land->lnd_own)
|
||||
|
@ -994,7 +1002,7 @@ doplane(char op, int arg, char *p, struct plnstr *plane)
|
|||
plane->pln_nuketype = arg;
|
||||
break;
|
||||
case 'U':
|
||||
plane->pln_uid = arg;
|
||||
ef_set_uid(EF_PLANE, plane, arg);
|
||||
break;
|
||||
case 'l':
|
||||
if (!sarg_xy(p, &newx, &newy))
|
||||
|
|
|
@ -87,14 +87,6 @@ fly(void)
|
|||
cno = -1;
|
||||
if (pln_onewaymission(&target, &cno, &wantflags) < 0)
|
||||
return RET_SYN;
|
||||
if (cno < 0) {
|
||||
dst_ptr = ⌖
|
||||
dst_type = EF_SECTOR;
|
||||
} else {
|
||||
getship(cno, &ship);
|
||||
dst_ptr = &ship;
|
||||
dst_type = EF_SHIP;
|
||||
}
|
||||
|
||||
if (ip && ip->i_uid == I_CIVIL && target.sct_own != target.sct_oldown) {
|
||||
pr("Can't fly civilians into occupied sectors.\n");
|
||||
|
@ -142,6 +134,14 @@ fly(void)
|
|||
pr("No planes got through fighter defenses\n");
|
||||
} else {
|
||||
getsect(tx, ty, &target);
|
||||
if (cno < 0) {
|
||||
dst_ptr = ⌖
|
||||
dst_type = EF_SECTOR;
|
||||
} else {
|
||||
getship(cno, &ship);
|
||||
dst_ptr = &ship;
|
||||
dst_type = EF_SHIP;
|
||||
}
|
||||
pln_dropoff(&bomb_list, ip, tx, ty, dst_ptr, dst_type);
|
||||
pln_newlanding(&bomb_list, tx, ty, cno);
|
||||
pln_newlanding(&esc_list, tx, ty, cno);
|
||||
|
|
|
@ -603,7 +603,14 @@ load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy,
|
|||
land.lnd_ship = sp->shp_uid;
|
||||
land.lnd_harden = 0;
|
||||
land.lnd_mission = 0;
|
||||
#if 0
|
||||
/*
|
||||
* FIXME if this supplies from the sector, the putsect in
|
||||
* load() / lload() duplicates those supplies, causing a
|
||||
* seqno mismatch
|
||||
*/
|
||||
resupply_all(&land);
|
||||
#endif
|
||||
sp->shp_nland++;
|
||||
putland(land.lnd_uid, &land);
|
||||
if (!has_supply(&land))
|
||||
|
@ -1034,7 +1041,10 @@ load_land_land(struct sctstr *sectp, struct lndstr *lp, int noisy,
|
|||
land.lnd_land = lp->lnd_uid;
|
||||
land.lnd_harden = 0;
|
||||
land.lnd_mission = 0;
|
||||
#if 0
|
||||
/* FIXME same issue as in load_land_ship() */
|
||||
resupply_all(&land);
|
||||
#endif
|
||||
lp->lnd_nland++;
|
||||
putland(land.lnd_uid, &land);
|
||||
if (!has_supply(&land))
|
||||
|
|
|
@ -188,7 +188,7 @@ multifire(void)
|
|||
}
|
||||
fx = fship.shp_x;
|
||||
fy = fship.shp_y;
|
||||
} else if (type == EF_SECTOR) {
|
||||
} else {
|
||||
if (!getsect(item.sect.sct_x, item.sect.sct_y, &fsect))
|
||||
continue;
|
||||
if (item.sect.sct_own != player->cnum)
|
||||
|
@ -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,7 @@ multifire(void)
|
|||
pr("Klick! ...\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (target == targ_ship) {
|
||||
if (chance(lnd_acc(&fland) / 100.0))
|
||||
dam = ldround(dam / 2.0, 1);
|
||||
|
@ -687,6 +694,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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -47,7 +47,7 @@ orig(void)
|
|||
struct natstr *np;
|
||||
|
||||
p = getstarg(player->argp[1], "New origin (sector or country) : ", buf);
|
||||
if (!p)
|
||||
if (!p || !*p)
|
||||
return RET_SYN;
|
||||
if (!isalpha(*p) && strchr(p, ',')) {
|
||||
/* sector */
|
||||
|
|
|
@ -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(sct_rail_track(§) ? " yes " : " no ");
|
||||
else
|
||||
pr("%4d%% ", sect.sct_rail);
|
||||
prmobcost(§, MOB_RAIL);
|
||||
pr("%4d%% ", SCT_DEFENSE(§));
|
||||
pr("%5.2f\n", sector_strength(§));
|
||||
|
|
|
@ -224,7 +224,7 @@ spyline(struct sctstr *sp)
|
|||
sp->sct_oldown,
|
||||
roundintby((int)sp->sct_effic, 10),
|
||||
roundintby((int)sp->sct_road, 10),
|
||||
roundintby((int)sp->sct_rail, 10),
|
||||
opt_RAILWAYS ? !!sct_rail_track(sp) : roundintby(sp->sct_rail, 10),
|
||||
roundintby((int)sp->sct_defense, 10),
|
||||
roundintby(sp->sct_item[I_CIVIL], 10),
|
||||
roundintby(sp->sct_item[I_MILIT], 10),
|
||||
|
|
|
@ -63,14 +63,14 @@ swaps(void)
|
|||
/* change the location of secta to that of sectb */
|
||||
secta.sct_x = sectb.sct_x;
|
||||
secta.sct_y = sectb.sct_y;
|
||||
secta.sct_uid = sectb.sct_uid;
|
||||
ef_set_uid(EF_SECTOR, §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;
|
||||
|
|
|
@ -173,6 +173,8 @@ pln_zap_transient_flags(void)
|
|||
|
||||
/* laziness: assumes plane file is EFF_MEM */
|
||||
for (i = 0; (pp = getplanep(i)) != NULL; i++) {
|
||||
if (!pp->pln_own)
|
||||
continue;
|
||||
if (pp->pln_flags & PLN_LAUNCHED
|
||||
&& (plchr[pp->pln_type].pl_flags & (P_M | P_O)) != P_O) {
|
||||
pp->pln_flags &= ~PLN_LAUNCHED;
|
||||
|
|
|
@ -48,7 +48,10 @@
|
|||
|
||||
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 unsigned get_seqno(struct empfile *, int);
|
||||
static void new_seqno(struct empfile *, void *);
|
||||
static void do_blank(struct empfile *, void *, int, int);
|
||||
|
||||
/*
|
||||
|
@ -300,11 +303,28 @@ ef_read(int type, int id, void *into)
|
|||
*/
|
||||
static int
|
||||
fillcache(struct empfile *ep, int id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (CANT_HAPPEN(!ep->cache))
|
||||
return -1;
|
||||
|
||||
ret = do_read(ep, ep->cache, id, MIN(ep->csize, ep->fids - id));
|
||||
if (ret >= 0) {
|
||||
/* cache changed */
|
||||
ep->baseid = id;
|
||||
ep->cids = ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
do_read(struct empfile *ep, void *buf, int id, int count)
|
||||
{
|
||||
int n, ret;
|
||||
char *p;
|
||||
|
||||
if (CANT_HAPPEN(ep->fd < 0 || !ep->cache))
|
||||
if (CANT_HAPPEN(ep->fd < 0 || id < 0 || count < 0))
|
||||
return -1;
|
||||
|
||||
if (lseek(ep->fd, id * ep->size, SEEK_SET) == (off_t)-1) {
|
||||
|
@ -313,21 +333,21 @@ fillcache(struct empfile *ep, int id)
|
|||
return -1;
|
||||
}
|
||||
|
||||
p = ep->cache;
|
||||
n = MIN(ep->csize, ep->fids - id) * ep->size;
|
||||
p = buf;
|
||||
n = count * ep->size;
|
||||
while (n > 0) {
|
||||
ret = read(ep->fd, p, n);
|
||||
if (ret < 0) {
|
||||
if (errno != EINTR) {
|
||||
logerror("Error reading %s elt %d (%s)",
|
||||
ep->file,
|
||||
id + (int)((p - ep->cache) / ep->size),
|
||||
id + (int)((p - (char *)buf) / ep->size),
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
} else if (ret == 0) {
|
||||
logerror("Unexpected EOF reading %s elt %d",
|
||||
ep->file, id + (int)((p - ep->cache) / ep->size));
|
||||
ep->file, id + (int)((p - (char *)buf) / ep->size));
|
||||
break;
|
||||
} else {
|
||||
p += ret;
|
||||
|
@ -335,12 +355,7 @@ fillcache(struct empfile *ep, int id)
|
|||
}
|
||||
}
|
||||
|
||||
if (p == ep->cache)
|
||||
return -1; /* nothing read, old cache still ok */
|
||||
|
||||
ep->baseid = id;
|
||||
ep->cids = (p - ep->cache) / ep->size;
|
||||
return ep->cids;
|
||||
return (p - (char *)buf) / ep->size;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -425,6 +440,7 @@ ef_write(int type, int id, void *from)
|
|||
ep->prewrite(id, from);
|
||||
if (CANT_HAPPEN((ep->flags & EFF_MEM) ? id >= ep->fids : id > ep->fids))
|
||||
return 0; /* not implemented */
|
||||
new_seqno(ep, from);
|
||||
if (!(ep->flags & EFF_PRIVATE)) {
|
||||
if (do_write(ep, from, id, 1, time(NULL)) < 0)
|
||||
return 0;
|
||||
|
@ -442,6 +458,77 @@ ef_write(int type, int id, void *from)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change element id.
|
||||
* BUF is an element of table TYPE.
|
||||
* ID is its new element ID.
|
||||
* If table is EFF_TYPED, change id and sequence number stored in BUF.
|
||||
* Else do nothing.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return sequence number of element ID in table EP.
|
||||
* Return zero if table is not EFF_TYPED (it has no sequence number
|
||||
* then).
|
||||
*/
|
||||
static unsigned
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment sequence number in BUF, which is about to be written to EP.
|
||||
* Do nothing if table is not EFF_TYPED (it has no sequence number
|
||||
* then).
|
||||
*/
|
||||
static void
|
||||
new_seqno(struct empfile *ep, void *buf)
|
||||
{
|
||||
struct emptypedstr *elt = buf;
|
||||
unsigned old_seqno;
|
||||
|
||||
if (!(ep->flags & EFF_TYPED))
|
||||
return;
|
||||
old_seqno = get_seqno(ep, elt->uid);
|
||||
if (CANT_HAPPEN(old_seqno != elt->seqno))
|
||||
old_seqno = MAX(old_seqno, elt->seqno);
|
||||
elt->seqno = old_seqno + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extend table TYPE by COUNT elements.
|
||||
* Any pointers obtained from ef_ptr() become invalid.
|
||||
|
@ -504,9 +591,17 @@ ef_extend(int type, int count)
|
|||
void
|
||||
ef_blank(int type, int id, void *buf)
|
||||
{
|
||||
struct empfile *ep;
|
||||
struct emptypedstr *elt;
|
||||
|
||||
if (ef_check(type) < 0)
|
||||
return;
|
||||
do_blank(&empfile[type], buf, id, 1);
|
||||
ep = &empfile[type];
|
||||
do_blank(ep, buf, id, 1);
|
||||
if (ep->flags & EFF_TYPED) {
|
||||
elt = buf;
|
||||
elt->seqno = get_seqno(ep, elt->uid);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -41,34 +41,6 @@
|
|||
#include "optlist.h"
|
||||
#include "prototypes.h"
|
||||
|
||||
int
|
||||
diffx(int x1, int x2)
|
||||
{
|
||||
int dx;
|
||||
|
||||
dx = x1 - x2;
|
||||
dx = dx % WORLD_X;
|
||||
if (dx > WORLD_X / 2)
|
||||
dx = dx - WORLD_X;
|
||||
if (dx < -WORLD_X / 2)
|
||||
dx = dx + WORLD_X;
|
||||
return dx;
|
||||
}
|
||||
|
||||
int
|
||||
diffy(int y1, int y2)
|
||||
{
|
||||
int dy;
|
||||
|
||||
dy = y1 - y2;
|
||||
dy = dy % WORLD_Y;
|
||||
if (dy > WORLD_Y / 2)
|
||||
dy = dy - WORLD_Y;
|
||||
if (dy < -WORLD_Y / 2)
|
||||
dy = dy + WORLD_Y;
|
||||
return dy;
|
||||
}
|
||||
|
||||
int
|
||||
deltax(int x1, int x2)
|
||||
{
|
||||
|
|
|
@ -33,8 +33,10 @@
|
|||
|
||||
#include <config.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "misc.h"
|
||||
#include "nat.h"
|
||||
#include "optlist.h"
|
||||
#include "path.h"
|
||||
#include "sect.h"
|
||||
#include "xy.h"
|
||||
|
@ -48,6 +50,12 @@ sector_mcost(struct sctstr *sp, int mobtype)
|
|||
if (base < 0)
|
||||
return -1.0;
|
||||
|
||||
if (mobtype == MOB_RAIL && opt_RAILWAYS) {
|
||||
if (!SCT_HAS_RAIL(sp))
|
||||
return -1;
|
||||
mobtype = MOB_MARCH;
|
||||
}
|
||||
|
||||
/* linear function in eff, d_mob0 at 0%, d_mob1 at 100% */
|
||||
base += (dchr[sp->sct_type].d_mob1 - base) * sp->sct_effic / 100;
|
||||
if (CANT_HAPPEN(base < 0))
|
||||
|
@ -83,3 +91,33 @@ speed_factor(double effspd, int tech)
|
|||
{
|
||||
return 480.0 / (effspd + techfact(tech, effspd));
|
||||
}
|
||||
|
||||
/* Minimal efficiency for railway and railway extension (opt_RAILWAYS) */
|
||||
#define SCT_RAIL_EFF 5
|
||||
#define SCT_RAIL_EXT_EFF 60
|
||||
|
||||
/* Is sector SP a railway? */
|
||||
#define SCT_IS_RAILWAY(sp) \
|
||||
(dchr[(sp)->sct_type].d_mob1 == 0 && (sp)->sct_effic >= SCT_RAIL_EFF)
|
||||
/* May sector SP have a railway extension? */
|
||||
#define SCT_MAY_HAVE_RAIL_EXT(sp) \
|
||||
((sp)->sct_effic >= SCT_RAIL_EXT_EFF)
|
||||
/* Does railway sector SP extend railway track into sector TOSP? */
|
||||
#define SCT_EXTENDS_RAIL(sp, tosp) \
|
||||
((sp)->sct_own == (tosp)->sct_own && SCT_MAY_HAVE_RAIL_EXT(tosp))
|
||||
|
||||
int
|
||||
sct_rail_track(struct sctstr *sp)
|
||||
{
|
||||
int i, res;
|
||||
struct sctstr *nsp;
|
||||
|
||||
res = !!SCT_IS_RAILWAY(sp);
|
||||
for (i = DIR_FIRST; i <= DIR_LAST; i++) {
|
||||
nsp = getsectp(sp->sct_x + diroff[i][0],
|
||||
sp->sct_y + diroff[i][1]);
|
||||
if (SCT_IS_RAILWAY(nsp) && SCT_EXTENDS_RAIL(nsp, sp))
|
||||
res++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want)
|
|||
val->val_as.lng = -1;
|
||||
if (CANT_HAPPEN(((struct natstr *)ptr)->ef_type != EF_NATION))
|
||||
break;
|
||||
if (!opt_HIDDEN && cnum != NATID_BAD) {
|
||||
if (opt_HIDDEN && cnum != NATID_BAD) {
|
||||
natp = getnatp(cnum);
|
||||
if (natp->nat_stat != STAT_GOD
|
||||
&& !(getcontact(natp, idx) && getcontact(ptr, idx)))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
|
||||
static void *nsc_ver(struct valstr *, struct natstr *, void *);
|
||||
static void *nsc_ver_maxnoc(struct valstr *, struct natstr *, void *);
|
||||
static void *nsc_sct_track(struct valstr *, struct natstr *, void *);
|
||||
static void *nsc_pln_att(struct valstr *, struct natstr *, void *);
|
||||
static void *nsc_pln_def(struct valstr *, struct natstr *, void *);
|
||||
static void *nsc_lnd_att(struct valstr *, struct natstr *, void *);
|
||||
|
@ -153,6 +154,7 @@ struct castr sect_ca[] = {
|
|||
{"uran", fldoff(sct_uran), NSC_UCHAR, 0, NULL, EF_BAD, 0},
|
||||
{"oldown", fldoff(sct_oldown), NSC_NATID, 0, NULL, EF_NATION, 0},
|
||||
{"off", fldoff(sct_off), NSC_UCHAR, 0, NULL, EF_BAD, 0},
|
||||
{"track", 0, NSC_LONG, 0, nsc_sct_track, EF_BAD, NSC_EXTRA},
|
||||
NSC_IVEC(fldoff(sct_item), ""),
|
||||
NSC_IVEC(fldoff(sct_dist), "_dist"),
|
||||
NSC_IVEC(fldoff(sct_del), "_del"),
|
||||
|
@ -178,6 +180,7 @@ struct castr dchr_ca[] = {
|
|||
{"uid", fldoff(d_uid), NSC_UCHAR, 0, NULL, EF_SECTOR_CHR, 0},
|
||||
{"name", fldoff(d_name), NSC_STRING, 0, NULL, EF_BAD, 0},
|
||||
{"mnem", fldoff(d_mnem), NSC_STRINGY, 1, NULL, EF_BAD, NSC_CONST},
|
||||
{"terrain", fldoff(d_terrain), NSC_UCHAR, 0, NULL, EF_SECTOR_CHR, 0},
|
||||
{"prd", fldoff(d_prd), NSC_INT, 0, NULL, EF_PRODUCT, 0},
|
||||
{"peffic", fldoff(d_peffic), NSC_INT, 0, NULL, EF_BAD, 0},
|
||||
{"mob0", fldoff(d_mob0), NSC_FLOAT, 0, NULL, EF_BAD, 0},
|
||||
|
@ -764,6 +767,13 @@ nsc_ver_maxnoc(struct valstr *val, struct natstr *np, void *ptr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
nsc_sct_track(struct valstr *val, struct natstr *np, void *ptr)
|
||||
{
|
||||
val->val_as.lng = sct_rail_track(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
nsc_pln_def(struct valstr *val, struct natstr *np, void *ptr)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
# sect.config: Sector characteristics
|
||||
#
|
||||
# Known contributors to this file:
|
||||
# Markus Armbruster, 2006
|
||||
# Markus Armbruster, 2006-2008
|
||||
#
|
||||
# Derived from sect.c; known contributors:
|
||||
# Dave Pare, 1986
|
||||
|
@ -38,14 +38,19 @@
|
|||
# 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
|
||||
|
@ -56,41 +61,41 @@
|
|||
# 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
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "com.h"
|
||||
#include "empio.h"
|
||||
#include "file.h"
|
||||
#include "journal.h"
|
||||
#include "match.h"
|
||||
#include "misc.h"
|
||||
#include "nat.h"
|
||||
|
@ -102,6 +103,7 @@ dispatch(char *buf, char *redir)
|
|||
uprnf(buf);
|
||||
pr("\n");
|
||||
}
|
||||
journal_command(command->c_form);
|
||||
switch (command->c_addr()) {
|
||||
case RET_OK:
|
||||
player->btused += command->c_cost;
|
||||
|
|
|
@ -110,9 +110,8 @@ player_main(struct player *p)
|
|||
}
|
||||
|
||||
while (status()) {
|
||||
if (command() == 0 && !player->aborted)
|
||||
break;
|
||||
player->aborted = 0;
|
||||
command();
|
||||
player->aborted = player->eof;
|
||||
empth_yield();
|
||||
}
|
||||
/* #*# I put the following line in to prevent server crash -KHS */
|
||||
|
@ -157,13 +156,9 @@ status(void)
|
|||
int old_nstat, minute;
|
||||
char buf[128];
|
||||
|
||||
if (player->state == PS_SHUTDOWN)
|
||||
if (player->eof || player->state == PS_SHUTDOWN)
|
||||
return 0;
|
||||
natp = getnatp(player->cnum);
|
||||
if (io_error(player->iop) || io_eof(player->iop)) {
|
||||
putnat(natp);
|
||||
return 0;
|
||||
}
|
||||
if (player->dolcost > 100.0)
|
||||
pr("That just cost you $%.2f\n", player->dolcost);
|
||||
else if (player->dolcost < -100.0)
|
||||
|
|
|
@ -46,10 +46,11 @@
|
|||
* Else receive one line and store it in CMD[SIZE].
|
||||
* This may block for input, yielding the processor. Flush buffered
|
||||
* output when blocking, to make sure player sees the prompt.
|
||||
* If the player's connection has the I/O error indicator set, or the
|
||||
* line is "aborted", set the player's aborted flag and return -2.
|
||||
* If the player's connection has the EOF indicator set, or the line
|
||||
* is "ctld", set the player's eof flag and return -1.
|
||||
* If the player's connection has the I/O error or EOF indicator set,
|
||||
* or the line is "ctld", set the player's eof and aborted flag and
|
||||
* return -1.
|
||||
* If the line is "aborted", set the player's aborted flag and return
|
||||
* -2.
|
||||
* Else return the length of the line.
|
||||
* Design bug: there is no way to indicate truncation of a long line.
|
||||
*/
|
||||
|
@ -59,13 +60,13 @@ recvclient(char *cmd, int size)
|
|||
int count;
|
||||
|
||||
count = -1;
|
||||
while (!player->aborted && !player->eof) {
|
||||
while (!player->aborted) {
|
||||
/* Try to get a line of input */
|
||||
count = io_gets(player->iop, cmd, size);
|
||||
if (count >= 0) {
|
||||
/* got it */
|
||||
if (strcmp(cmd, "ctld") == 0)
|
||||
player->eof = 1;
|
||||
player->aborted = player->eof = 1;
|
||||
if (strcmp(cmd, "aborted") == 0)
|
||||
player->aborted = 1;
|
||||
journal_input(cmd);
|
||||
|
@ -84,16 +85,23 @@ recvclient(char *cmd, int size)
|
|||
|
||||
/* Await more input */
|
||||
io_input(player->iop, IO_WAIT);
|
||||
if (io_error(player->iop))
|
||||
player->aborted = 1;
|
||||
else if (io_eof(player->iop))
|
||||
player->eof = 1;
|
||||
if (io_error(player->iop) || io_eof(player->iop))
|
||||
player->aborted = player->eof = 1;
|
||||
}
|
||||
|
||||
if (player->eof)
|
||||
return -1;
|
||||
if (player->aborted)
|
||||
return -2;
|
||||
if (player->aborted) {
|
||||
player->recvfail++;
|
||||
if (player->recvfail > 255) {
|
||||
/*
|
||||
* Looks like the thread is stuck in a loop that fails to
|
||||
* check errors; oops once, then slow it down drastically.
|
||||
*/
|
||||
CANT_HAPPEN(player->recvfail == 256);
|
||||
empth_sleep(time(NULL) + 60);
|
||||
}
|
||||
return player->eof ? -1 : -2;
|
||||
}
|
||||
|
||||
player->recvfail = 0;
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -770,12 +770,18 @@ ac_doflak(struct emp_qelem *list, struct sctstr *from)
|
|||
|
||||
gun = MIN(FLAK_GUN_MAX, from->sct_item[I_GUN]);
|
||||
shell = from->sct_item[I_SHELL];
|
||||
#if 0
|
||||
/*
|
||||
* FIXME can supply from itself, causing seqno mismatch oops
|
||||
* further down
|
||||
*/
|
||||
if (gun > shell * 2) {
|
||||
shell += supply_commod(from->sct_own, from->sct_x, from->sct_y,
|
||||
I_SHELL, (gun + 1) / 2 - shell);
|
||||
from->sct_item[I_SHELL] = shell;
|
||||
putsect(from);
|
||||
}
|
||||
#endif
|
||||
if (gun > shell * 2)
|
||||
gun = shell * 2;
|
||||
|
||||
|
@ -823,12 +829,19 @@ ac_shipflak(struct emp_qelem *list, coord x, coord y)
|
|||
gun = shp_usable_guns(&ship);
|
||||
if (gun) {
|
||||
shell = ship.shp_item[I_SHELL];
|
||||
#if 0
|
||||
/*
|
||||
* FIXME if this supplies the ship while it is being
|
||||
* interdicted, we get a seqno mismatch when interdiction
|
||||
* damage is applied.
|
||||
*/
|
||||
if (shell <= 0) {
|
||||
shell = supply_commod(ship.shp_own, ship.shp_x, ship.shp_y,
|
||||
I_SHELL, 1);
|
||||
ship.shp_item[I_SHELL] = shell;
|
||||
putship(ship.shp_uid, &ship);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (gun == 0 || shell == 0)
|
||||
continue;
|
||||
|
|
|
@ -461,6 +461,7 @@ att_abort(int combat_mode, struct combat *off, struct combat *def)
|
|||
if (att_get_combat(off, 0) < 0)
|
||||
return abort_attack();
|
||||
if (off->type == EF_SHIP &&
|
||||
!(off->x == def->x && off->y == def->y) &&
|
||||
(!getsect(off->x, off->y, §) ||
|
||||
sect.sct_type != SCT_WATER)) {
|
||||
pr("%s can not %s from that far inland!\n",
|
||||
|
@ -1007,6 +1008,12 @@ ask_olist(int combat_mode, struct combat *off, struct combat *def,
|
|||
pr("Land units are not able to board this kind of ship\n");
|
||||
return;
|
||||
}
|
||||
if (def->type == EF_SHIP
|
||||
&& (def->shp_mcp->m_flags & (M_SUPPLY | M_SUB)) != M_SUPPLY
|
||||
&& !(lcp->l_flags & L_LIGHT)) {
|
||||
pr("Only light land units can board this kind of ship\n");
|
||||
continue;
|
||||
}
|
||||
if (land.lnd_mobil <= 0) {
|
||||
pr("%s is out of mobility, and cannot %s\n",
|
||||
prland(&land), att_mode[combat_mode]);
|
||||
|
@ -1229,11 +1236,8 @@ get_dlist(struct combat *def, struct emp_qelem *list, int a_spy,
|
|||
continue;
|
||||
if (def->type == EF_LAND && land.lnd_land != def->lnd_uid)
|
||||
continue;
|
||||
if (!list) { /* Just estimating the enemy strength */
|
||||
intelligence_report(player->cnum, &land, a_spy,
|
||||
"Scouts report defending unit:");
|
||||
continue;
|
||||
}
|
||||
intelligence_report(player->cnum, &land, a_spy,
|
||||
"Scouts report defending unit:");
|
||||
if (!(llp = malloc(sizeof(struct ulist)))) {
|
||||
logerror("Malloc failed in attack!\n");
|
||||
abort_attack();
|
||||
|
|
|
@ -70,7 +70,7 @@ bridge_damaged(struct sctstr *sp)
|
|||
des = sp->sct_type;
|
||||
if (des == SCT_BSPAN || des == SCT_BTOWER)
|
||||
knockdown(sp);
|
||||
if ((des == SCT_BHEAD || des == SCT_BTOWER) && !opt_EASY_BRIDGES)
|
||||
if (IS_BRIDGE_HEAD(des) && !opt_EASY_BRIDGES)
|
||||
bridgefall(sp);
|
||||
}
|
||||
|
||||
|
@ -98,17 +98,16 @@ bridgefall(struct sctstr *sp)
|
|||
if (nnx == sp->sct_x && nny == sp->sct_y)
|
||||
continue;
|
||||
getsect(nnx, nny, &bh_sect);
|
||||
if (bh_sect.sct_type == SCT_BHEAD &&
|
||||
bh_sect.sct_newtype == SCT_BHEAD)
|
||||
break;
|
||||
if (bh_sect.sct_type == SCT_BTOWER)
|
||||
break;
|
||||
/* With EASY_BRIDGES, it just has to be next to any
|
||||
land */
|
||||
if (opt_EASY_BRIDGES) {
|
||||
if (bh_sect.sct_type != SCT_WATER &&
|
||||
bh_sect.sct_type != SCT_BSPAN)
|
||||
break;
|
||||
} else {
|
||||
if (IS_BRIDGE_HEAD(bh_sect.sct_type)
|
||||
&& bh_sect.sct_newtype == bh_sect.sct_type)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j > 6) {
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
* prng NAME SEED
|
||||
* login CNUM HOSTADDR USER
|
||||
* logout CNUM
|
||||
* command NAME
|
||||
* input INPUT
|
||||
* output THREAD ID OUTPUT
|
||||
* update ETU
|
||||
*/
|
||||
|
||||
|
@ -64,6 +66,9 @@
|
|||
static char journal_fname[] = "journal.log";
|
||||
static FILE *journal;
|
||||
|
||||
static void journal_entry(char *fmt, ...) ATTRIBUTE((format (printf, 1, 2)));
|
||||
static void journal_output_1(struct player *, int, char *, char *, int);
|
||||
|
||||
static FILE *
|
||||
journal_open(void)
|
||||
{
|
||||
|
@ -80,7 +85,11 @@ journal_entry(char *fmt, ...)
|
|||
|
||||
if (journal) {
|
||||
time(&now);
|
||||
fprintf(journal, "%.24s %p ", ctime(&now), empth_self());
|
||||
fprintf(journal, "%.24s ", ctime(&now));
|
||||
if (player && player->state == PS_PLAYING)
|
||||
fprintf(journal, "%d ", player->cnum);
|
||||
else
|
||||
fprintf(journal, "%p ", empth_self());
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
|
||||
|
@ -93,7 +102,8 @@ journal_entry(char *fmt, ...)
|
|||
fprintf(journal, "\\%03o", *p);
|
||||
}
|
||||
fputs("\n", journal);
|
||||
fflush(journal);
|
||||
if (fmt[0] != 'o') /* FIXME disgusting hack */
|
||||
fflush(journal);
|
||||
if (ferror(journal)) {
|
||||
logerror("Error writing journal (%s)", strerror(errno));
|
||||
clearerr(journal);
|
||||
|
@ -162,12 +172,61 @@ journal_logout(void)
|
|||
journal_entry("logout %d", player->cnum);
|
||||
}
|
||||
|
||||
void
|
||||
journal_output(struct player *pl, int id, char *output)
|
||||
{
|
||||
static char buf[1024];
|
||||
static struct player *bpl;
|
||||
static int bid;
|
||||
char *s, *e;
|
||||
|
||||
if (keep_journal < 2)
|
||||
return;
|
||||
|
||||
if (buf[0] && (pl != bpl && id != bid)) {
|
||||
journal_output_1(bpl, bid, buf, "", -1);
|
||||
buf[0] = 0;
|
||||
}
|
||||
|
||||
for (s = output; (e = strchr(s, '\n')); s = e + 1) {
|
||||
journal_output_1(pl, id, buf, s, (int)(e + 1 - s));
|
||||
buf[0] = 0;
|
||||
}
|
||||
if (strlen(buf) + strlen(s) < 1024) {
|
||||
strcpy(buf + strlen(buf), s);
|
||||
bpl = pl;
|
||||
bid = id;
|
||||
} else {
|
||||
journal_output_1(pl, id, buf, s, -1);
|
||||
buf[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
journal_output_1(struct player *pl, int id,
|
||||
char *buf1, char *buf2, int buf2prec)
|
||||
{
|
||||
if (pl && pl->state == PS_PLAYING)
|
||||
journal_entry("output %d %d %s%.*s",
|
||||
pl->cnum, id, buf1, buf2prec, buf2);
|
||||
else
|
||||
journal_entry("output %p %id %s%.*s",
|
||||
pl, id, buf1, buf2prec, buf2);
|
||||
}
|
||||
|
||||
void
|
||||
journal_input(char *input)
|
||||
{
|
||||
journal_entry("input %s", input);
|
||||
}
|
||||
|
||||
void
|
||||
journal_command(char *cmd)
|
||||
{
|
||||
char *eptr = strchr(cmd, ' ');
|
||||
journal_entry("command %.*s", eptr ? (int)(eptr - cmd) : -1, cmd);
|
||||
}
|
||||
|
||||
void
|
||||
journal_update(int etu)
|
||||
{
|
||||
|
|
|
@ -207,6 +207,7 @@ lnd_fire(struct lndstr *lp)
|
|||
I_SHELL, ammo - shells);
|
||||
if (shells == 0)
|
||||
return -1;
|
||||
lnd_unlimber(lp);
|
||||
d = landunitgun(lp->lnd_effic, guns);
|
||||
if (shells < ammo) {
|
||||
d *= (double)shells / (double)ammo;
|
||||
|
@ -287,7 +288,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
|
||||
|
|
|
@ -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) &&
|
||||
|
@ -1170,31 +1173,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;
|
||||
|
|
|
@ -344,10 +344,10 @@ build_mission_list_type(struct genlist *mi, coord x, coord y, int mission,
|
|||
if (getrel(getnatp(gp->own), sect.sct_own) > AT_WAR) {
|
||||
|
||||
/*
|
||||
* If the player->owner of the unit isn't at war
|
||||
* If the owner of the unit isn't at war
|
||||
* with the victim, and doesn't own the
|
||||
* sect being acted upon, and isn't the
|
||||
* old player->owner of that sect, bounce them.
|
||||
* old owner of that sect, bounce them.
|
||||
*/
|
||||
if (sect.sct_type != SCT_WATER &&
|
||||
sect.sct_own != gp->own &&
|
||||
|
@ -412,6 +412,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
|||
natid plane_owner = 0;
|
||||
int md, range, air_dam = 0;
|
||||
double prb, hitchance, vrange;
|
||||
int targeting_ships = *s == 's'; /* "subs" or "ships" FIXME gross! */
|
||||
|
||||
getsect(x, y, §);
|
||||
|
||||
|
@ -436,6 +437,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,12 +450,12 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
|||
if (dam2 < 0)
|
||||
continue;
|
||||
|
||||
if (sect.sct_type == SCT_WATER) {
|
||||
if (targeting_ships) {
|
||||
if (chance(lnd_acc(lp) / 100.0))
|
||||
dam2 = ldround(dam2 / 2.0, 1);
|
||||
}
|
||||
dam += dam2;
|
||||
if (sect.sct_type == SCT_WATER)
|
||||
if (targeting_ships)
|
||||
nreport(lp->lnd_own, N_SHP_SHELL, victim, 1);
|
||||
else
|
||||
nreport(lp->lnd_own, N_SCT_SHELL, victim, 1);
|
||||
|
@ -487,10 +492,8 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
|||
continue;
|
||||
}
|
||||
if (mcp->m_flags & M_SUB) {
|
||||
/* If we aren't shooting at "subs" or "ships" don't fire at all from
|
||||
a sub. */
|
||||
if (*s != 's')
|
||||
continue;
|
||||
if (!targeting_ships)
|
||||
continue; /* subs interdict only ships */
|
||||
range = roundrange(torprange(sp));
|
||||
if (md > range)
|
||||
continue;
|
||||
|
@ -547,7 +550,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
|||
if (chance(prb))
|
||||
dam2 /= 2;
|
||||
dam += dam2;
|
||||
if (sect.sct_type == SCT_WATER)
|
||||
if (targeting_ships)
|
||||
nreport(sp->shp_own, N_SHP_SHELL, victim, 1);
|
||||
else
|
||||
nreport(sp->shp_own, N_SCT_SHELL, victim, 1);
|
||||
|
@ -680,7 +683,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
|||
|
||||
if (air_dam > 0) {
|
||||
dam += air_dam;
|
||||
if (sect.sct_type == SCT_WATER)
|
||||
if (targeting_ships)
|
||||
nreport(plane_owner, N_SHP_BOMB, victim, 1);
|
||||
else
|
||||
nreport(plane_owner, N_SCT_BOMB, victim, 1);
|
||||
|
|
|
@ -194,6 +194,9 @@ msl_sel(struct emp_qelem *list, coord x, coord y, natid victim,
|
|||
continue;
|
||||
if (mission && plane.pln_mission != mission)
|
||||
continue;
|
||||
if (mission &&
|
||||
plane.pln_radius < mapdist(x, y, plane.pln_opx, plane.pln_opy))
|
||||
continue;
|
||||
if (getrel(getnatp(plane.pln_own), victim) >= NEUTRAL)
|
||||
continue;
|
||||
/* missiles go one way, so we can use all the range */
|
||||
|
|
|
@ -111,7 +111,7 @@ delete_old_news(void)
|
|||
for (j = 0; getnews(i + j, &news); j++) {
|
||||
if (news.nws_vrb == 0)
|
||||
break;
|
||||
news.nws_uid = j;
|
||||
ef_set_uid(EF_NEWS, &news, j);
|
||||
putnews(j, &news);
|
||||
}
|
||||
CANT_HAPPEN(i + j != news_tail);
|
||||
|
|
|
@ -89,6 +89,9 @@ nuk_prewrite(int n, void *ptr)
|
|||
}
|
||||
|
||||
getnuke(n, &nuke);
|
||||
if (nuke.nuk_plane != np->nuk_plane)
|
||||
logerror("phantom nuke debug: nuk#%d plane %d->%d",
|
||||
np->nuk_uid, nuke.nuk_plane, np->nuk_plane);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -132,6 +132,9 @@ pln_prewrite(int n, void *ptr)
|
|||
}
|
||||
}
|
||||
getplane(n, &plane);
|
||||
if (plane.pln_nuketype != pp->pln_nuketype)
|
||||
logerror("phantom nuke debug: pln#%d nuketype %d->%d",
|
||||
pp->pln_uid, plane.pln_nuketype, pp->pln_nuketype);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -559,6 +559,7 @@ pln_arm(struct emp_qelem *list, int dist, char mission, struct ichrstr *ip,
|
|||
next = qp->q_forw;
|
||||
plp = (struct plist *)qp;
|
||||
pp = &plp->plane;
|
||||
getplane(pp->pln_uid, pp);
|
||||
if ((pp->pln_flags & PLN_LAUNCHED)
|
||||
|| pln_equip(plp, ip, flags, mission) < 0) {
|
||||
emp_remque(qp);
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "com.h"
|
||||
#include "empio.h"
|
||||
#include "file.h"
|
||||
#include "journal.h"
|
||||
#include "misc.h"
|
||||
#include "nat.h"
|
||||
#include "player.h"
|
||||
|
@ -124,6 +125,7 @@ pr_id(struct player *p, int id, char *format, ...)
|
|||
|
||||
if (p->curid >= 0) {
|
||||
io_puts(p->iop, "\n");
|
||||
journal_output(p, p->curid, "\n");
|
||||
p->curid = -1;
|
||||
}
|
||||
va_start(ap, format);
|
||||
|
@ -245,6 +247,7 @@ pr_player(struct player *pl, int id, char *buf)
|
|||
bp += len;
|
||||
}
|
||||
}
|
||||
journal_output(pl, id, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -299,6 +302,7 @@ upr_player(struct player *pl, int id, char *buf)
|
|||
io_puts(pl->iop, printbuf);
|
||||
}
|
||||
}
|
||||
journal_output(pl, id, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -251,6 +251,7 @@ retreat_ship1(struct shpstr *sp, char code, int orig)
|
|||
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],
|
||||
|
|
|
@ -177,15 +177,8 @@ satmap(int x, int y, int eff, int range, int flags, int type)
|
|||
}
|
||||
/* If we are imaging *and* drawing the map */
|
||||
if ((flags & P_I) && (type == EF_BAD)) {
|
||||
/* Figure out where to put the ship */
|
||||
/* First, figure out the distance from the two */
|
||||
rx = diffx((int)ship.shp_x, x);
|
||||
ry = diffy((int)ship.shp_y, y);
|
||||
/* Next, determine which direction to add it to the center */
|
||||
/* We can only do this if imaging and we have gotten the center
|
||||
up above by imaging the sectors. */
|
||||
rx = deltax(x, ns.range.lx) + rx;
|
||||
ry = deltay(y, ns.range.ly) + ry;
|
||||
rx = deltx(&ns.range, ship.shp_x);
|
||||
ry = delty(&ns.range, ship.shp_y);
|
||||
/* &~0x20 makes it a cap letter */
|
||||
rad[ry][rx] = (*mchr[(int)ship.shp_type].m_name) & ~0x20;
|
||||
}
|
||||
|
@ -230,15 +223,8 @@ satmap(int x, int y, int eff, int range, int flags, int type)
|
|||
}
|
||||
/* If we are imaging *and* drawing the map */
|
||||
if ((flags & P_I) && (type == EF_BAD)) {
|
||||
/* Figure out where to put the unit */
|
||||
/* First, figure out the distance from the two */
|
||||
rx = diffx((int)land.lnd_x, x);
|
||||
ry = diffy((int)land.lnd_y, y);
|
||||
/* Next, determine which direction to add it to the center */
|
||||
/* We can only do this if imaging and we have gotten the center
|
||||
up above by imaging the sectors. */
|
||||
rx = deltax(x, ns.range.lx) + rx;
|
||||
ry = deltay(y, ns.range.ly) + ry;
|
||||
rx = deltx(&ns.range, land.lnd_x);
|
||||
ry = delty(&ns.range, land.lnd_y);
|
||||
/* &~0x20 makes it a cap letter */
|
||||
rad[ry][rx] = (*lchr[(int)land.lnd_type].l_name) & ~0x20;
|
||||
}
|
||||
|
@ -285,7 +271,7 @@ satdisp_sect(struct sctstr *sp, int acc)
|
|||
dchr[sp->sct_type].d_mnem,
|
||||
sp->sct_own, roundintby((int)sp->sct_effic, acc / 2),
|
||||
roundintby((int)sp->sct_road, acc / 2),
|
||||
roundintby((int)sp->sct_rail, acc / 2),
|
||||
opt_RAILWAYS ? !!sct_rail_track(sp) : roundintby(sp->sct_rail, acc / 2),
|
||||
roundintby((int)sp->sct_defense, acc / 2),
|
||||
roundintby(sp->sct_item[I_CIVIL], acc),
|
||||
roundintby(sp->sct_item[I_MILIT], acc),
|
||||
|
|
|
@ -237,13 +237,13 @@ shp_sweep(struct emp_qelem *ship_list, int verbose, int takemob, natid actor)
|
|||
}
|
||||
sect.sct_mines = mines;
|
||||
mlp->unit.ship.shp_item[I_SHELL] = shells;
|
||||
putship(mlp->unit.ship.shp_uid, &mlp->unit.ship);
|
||||
putsect(§);
|
||||
if (shp_check_one_mines(mlp)) {
|
||||
stopping = 1;
|
||||
emp_remque(qp);
|
||||
free(qp);
|
||||
}
|
||||
putship(mlp->unit.ship.shp_uid, &mlp->unit.ship);
|
||||
putsect(§);
|
||||
}
|
||||
if (changed)
|
||||
writemap(actor);
|
||||
|
@ -753,6 +753,7 @@ shp_nav_one_sector(struct emp_qelem *list, int dir, natid actor,
|
|||
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) &&
|
||||
|
@ -867,12 +868,18 @@ shp_missile_defense(coord dx, coord dy, natid bombown, int hardtarget)
|
|||
shell = ship.shp_item[I_SHELL];
|
||||
if (ship.shp_item[I_MILIT] < 1) /* do we have mil? */
|
||||
continue;
|
||||
#if 0
|
||||
/*
|
||||
* FIXME can supply from itself, causing seqno mismatch oops
|
||||
* further down
|
||||
*/
|
||||
if (shell < 2) { /* do we need shells */
|
||||
shell += supply_commod(ship.shp_own, ship.shp_x, ship.shp_y,
|
||||
I_SHELL, 2);
|
||||
if (shell < 2)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (ship.shp_item[I_GUN] < 1) /* we need at least 1 gun */
|
||||
continue;
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ resupply_commod(struct lndstr *lp, i_type type)
|
|||
int
|
||||
supply_commod(int own, int x, int y, i_type type, int total_wanted)
|
||||
{
|
||||
if (total_wanted < 0)
|
||||
if (total_wanted <= 0)
|
||||
return 0;
|
||||
return s_commod(own, x, y, type, total_wanted, !player->simulation);
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ supply_commod(int own, int x, int y, i_type type, int total_wanted)
|
|||
static int
|
||||
try_supply_commod(int own, int x, int y, i_type type, int total_wanted)
|
||||
{
|
||||
if (total_wanted < 0)
|
||||
if (total_wanted <= 0)
|
||||
return 0;
|
||||
|
||||
return s_commod(own, x, y, type, total_wanted, 0);
|
||||
|
@ -361,6 +361,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
|
|||
save = land;
|
||||
land.lnd_item[type] = 0;
|
||||
putland(land.lnd_uid, &land);
|
||||
save.lnd_seqno = land.lnd_seqno;
|
||||
|
||||
land.lnd_item[type] =
|
||||
save.lnd_item[type] + s_commod(own, land.lnd_x, land.lnd_y,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -61,6 +61,7 @@ do_feed(struct sctstr *sp, struct natstr *np, short *vec,
|
|||
int starved, sctwork;
|
||||
int needed;
|
||||
int maxpop;
|
||||
int manna;
|
||||
|
||||
/* grow people & stuff */
|
||||
sctwork = sp->sct_work;
|
||||
|
@ -72,12 +73,16 @@ do_feed(struct sctstr *sp, struct natstr *np, short *vec,
|
|||
maxpop));
|
||||
|
||||
if (sp->sct_type != SCT_SANCT) {
|
||||
manna = 0;
|
||||
if (opt_NOFOOD == 0) {
|
||||
needed = (int)ceil(food_needed(vec, etu));
|
||||
if (vec[I_FOOD] < needed) {
|
||||
/* need to grow "emergency rations" */
|
||||
work_avail -= 2 * growfood(sp, vec, work_avail / 2, etu);
|
||||
/* It's twice as hard to grow those than norm */
|
||||
if (vec[I_FOOD] == 0)
|
||||
/* Conjure up 1f to make life easier for the player */
|
||||
manna = vec[I_FOOD] = 1;
|
||||
}
|
||||
if (vec[I_FOOD] < needed && sp->sct_own == sp->sct_oldown) {
|
||||
/* steal food from warehouses, headquarters,
|
||||
|
@ -109,7 +114,21 @@ do_feed(struct sctstr *sp, struct natstr *np, short *vec,
|
|||
if (!player->simulation)
|
||||
sp->sct_work = sctwork;
|
||||
grow_people(sp, etu, np, &work_avail, sctwork, vec);
|
||||
/* age che */
|
||||
if (!player->simulation) {
|
||||
int oldche = sp->sct_che;
|
||||
sp->sct_che = age_people(sp->sct_che, etu);
|
||||
if (sp->sct_che_target == sp->sct_own && sp->sct_loyal < 40)
|
||||
/* make them fade away eventually, for playability */
|
||||
sp->sct_che /= 2;
|
||||
if (sp->sct_che != oldche)
|
||||
logerror("che in %d,%d aged from %d to %d",
|
||||
sp->sct_x, sp->sct_y, oldche, sp->sct_che);
|
||||
}
|
||||
}
|
||||
if (manna)
|
||||
/* Take away food we conjured up */
|
||||
vec[I_FOOD] = 0;
|
||||
} else
|
||||
sctwork = sp->sct_work = 100;
|
||||
/* Here is where we truncate extra people, always */
|
||||
|
@ -141,13 +160,7 @@ growfood(struct sctstr *sp, short *vec, int work, int etu)
|
|||
food = MIN(food_workers, food_fertil);
|
||||
if (food > ITEM_MAX - vec[I_FOOD])
|
||||
food = ITEM_MAX - vec[I_FOOD];
|
||||
/*
|
||||
* Be nice; grow minimum one food unit.
|
||||
* This makes life simpler for the player.
|
||||
*/
|
||||
vec[I_FOOD] += food;
|
||||
if (vec[I_FOOD] == 0)
|
||||
vec[I_FOOD] = 1;
|
||||
work_used = food / fcrate;
|
||||
return work_used;
|
||||
}
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -1098,6 +1098,7 @@ write_sects(void)
|
|||
sct->sct_type = SCT_MOUNT;
|
||||
sct->sct_elev = total;
|
||||
sct->sct_newtype = sct->sct_type;
|
||||
sct->sct_dterr = own[sct->sct_x][y] + 1;
|
||||
if (ORE)
|
||||
add_resources(sct);
|
||||
sct++;
|
||||
|
|
|
@ -155,6 +155,7 @@ main(int argc, char *argv[])
|
|||
for (i = 1; i < MAXNOC; i++) {
|
||||
nat.ef_type = EF_NATION;
|
||||
nat.nat_cnum = nat.nat_uid = i;
|
||||
nat.nat_seqno = 0;
|
||||
putnat((&nat));
|
||||
}
|
||||
memset(&realm, 0, sizeof(realm));
|
||||
|
@ -164,6 +165,7 @@ main(int argc, char *argv[])
|
|||
for (j = 0; j < MAXNOR; j++) {
|
||||
realm.r_realm = j;
|
||||
realm.r_uid = (i * MAXNOR) + j;
|
||||
realm.r_seqno = 0;
|
||||
putrealm(&realm);
|
||||
}
|
||||
}
|
||||
|
@ -209,6 +211,7 @@ file_sct_init(coord x, coord y, struct sctstr *ptr)
|
|||
|
||||
sp->ef_type = EF_SECTOR;
|
||||
sp->sct_uid = XYOFFSET(x, y);
|
||||
sp->sct_seqno = 0;
|
||||
sp->sct_x = x;
|
||||
sp->sct_y = y;
|
||||
sp->sct_dist_x = x;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue