Don't store RAILWAYS track in sectors
Storing track in sectors is problematic, because we need to update adjacent sectors when updating a sector in a way that changes its capability to extend railway into its neighbors. This invalidates cached adjacent sectors, and calling code may not be prepared for that. Specifically, bridge building caches the bridge head, and writes it back later, wiping out the track update. Replace struct sctstr member sct_track by new sct_rail_track(). Make selector track virtual. Remove the code to keep sct_track up-to-date: set_railway(), update_railway(). Unfortunately, this causes cyclic dependencies between link libraries: the virtual selector needs to be referenced from src/lib/global/nsc.c, and it needs to reference stuff from src/lib/common/file.c. Hack around it in Make.mk for now.
This commit is contained in:
parent
11100f23e5
commit
fa5fa4abcc
10 changed files with 46 additions and 79 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))
|
||||
|
|
|
@ -627,7 +627,6 @@ extern void sathead(void);
|
|||
extern int sct_postread(int, void *);
|
||||
extern int sct_prewrite(int, void *);
|
||||
extern void item_prewrite(short *);
|
||||
extern void set_railway(struct sctstr *);
|
||||
extern int issector(char *);
|
||||
/* sectdamage.c */
|
||||
extern int sect_damage(struct sctstr *, int);
|
||||
|
|
|
@ -77,7 +77,6 @@ struct sctstr {
|
|||
natid sct_oldown; /* old owner of sector (for liberation) */
|
||||
unsigned char sct_updated; /* Has this sect been updated? */
|
||||
unsigned char sct_off; /* Should this sector produce? */
|
||||
unsigned char sct_track; /* nearby railways (RAILWAYS) */
|
||||
short sct_item[I_MAX+1]; /* amount of items stored here */
|
||||
short sct_del[I_MAX+1]; /* delivieries */
|
||||
short sct_dist[I_MAX+1]; /* distribution thresholds */
|
||||
|
@ -189,7 +188,7 @@ extern struct dchrstr bigcity_dchr;
|
|||
|
||||
/* Can trains enter sector SP? */
|
||||
#define SCT_HAS_RAIL(sp) \
|
||||
(opt_RAILWAYS ? (sp)->sct_track != 0 \
|
||||
(opt_RAILWAYS ? sct_rail_track((sp)) != 0 \
|
||||
: intrchr[INT_RAIL].in_enable && (sp)->sct_rail != 0)
|
||||
|
||||
#define MOB_MOVE 0
|
||||
|
@ -227,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
|
||||
|
|
|
@ -74,7 +74,7 @@ sinfra(void)
|
|||
pr("%4d%% ", sect.sct_road);
|
||||
prmobcost(§, MOB_MOVE);
|
||||
if (opt_RAILWAYS)
|
||||
pr(sect.sct_track ? " yes " : " no ");
|
||||
pr(sct_rail_track(§) ? " yes " : " no ");
|
||||
else
|
||||
pr("%4d%% ", sect.sct_rail);
|
||||
prmobcost(§, MOB_RAIL);
|
||||
|
|
|
@ -224,7 +224,7 @@ spyline(struct sctstr *sp)
|
|||
sp->sct_oldown,
|
||||
roundintby((int)sp->sct_effic, 10),
|
||||
roundintby((int)sp->sct_road, 10),
|
||||
opt_RAILWAYS ? !!sp->sct_track : roundintby(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),
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <config.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "misc.h"
|
||||
#include "nat.h"
|
||||
#include "optlist.h"
|
||||
|
@ -90,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;
|
||||
}
|
||||
|
|
|
@ -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,7 +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", fldoff(sct_track), NSC_UCHAR, 0, NULL, EF_BAD, NSC_EXTRA},
|
||||
{"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"),
|
||||
|
@ -766,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)
|
||||
{
|
||||
|
|
|
@ -285,7 +285,7 @@ satdisp_sect(struct sctstr *sp, int acc)
|
|||
dchr[sp->sct_type].d_mnem,
|
||||
sp->sct_own, roundintby((int)sp->sct_effic, acc / 2),
|
||||
roundintby((int)sp->sct_road, acc / 2),
|
||||
opt_RAILWAYS ? !!sp->sct_track : roundintby(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),
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "nat.h"
|
||||
#include "nsc.h"
|
||||
#include "optlist.h"
|
||||
#include "path.h"
|
||||
#include "plane.h"
|
||||
#include "player.h"
|
||||
#include "prototypes.h"
|
||||
|
@ -50,7 +49,6 @@
|
|||
#include "xy.h"
|
||||
|
||||
static int checksect(struct sctstr *);
|
||||
static void update_railway(struct sctstr *, struct sctstr *);
|
||||
|
||||
int
|
||||
sct_postread(int id, void *ptr)
|
||||
|
@ -73,8 +71,6 @@ sct_prewrite(int id, void *ptr)
|
|||
bridge_damaged(sp);
|
||||
checksect(sp);
|
||||
getsect(sp->sct_x, sp->sct_y, §);
|
||||
if (opt_RAILWAYS)
|
||||
update_railway(sp, §);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -132,69 +128,6 @@ checksect(struct sctstr *sp)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Minimal efficiency for railway and railway extension (opt_RAILWAYS) */
|
||||
#define SCT_RAIL_EFF 5
|
||||
#define SCT_RAIL_EXT_EFF 60
|
||||
|
||||
/* Is sector SP a railway? */
|
||||
#define SCT_IS_RAILWAY(sp) \
|
||||
(dchr[(sp)->sct_type].d_mob1 == 0 && (sp)->sct_effic >= SCT_RAIL_EFF)
|
||||
/* May sector SP have a railway extension? */
|
||||
#define SCT_MAY_HAVE_RAIL_EXT(sp) \
|
||||
((sp)->sct_effic >= SCT_RAIL_EXT_EFF)
|
||||
/* Does railway sector SP extend railway track into sector TOSP? */
|
||||
#define SCT_EXTENDS_RAIL(sp, tosp) \
|
||||
((sp)->sct_own == (tosp)->sct_own && SCT_MAY_HAVE_RAIL_EXT(tosp))
|
||||
|
||||
static void
|
||||
update_railway(struct sctstr *sp, struct sctstr *oldsp)
|
||||
{
|
||||
struct sctstr sect;
|
||||
int was_railway = SCT_IS_RAILWAY(oldsp);
|
||||
int is_railway = SCT_IS_RAILWAY(sp);
|
||||
int i;
|
||||
|
||||
if (was_railway == is_railway
|
||||
&& sp->sct_own == oldsp->sct_own
|
||||
&& SCT_MAY_HAVE_RAIL_EXT(sp) == SCT_MAY_HAVE_RAIL_EXT(oldsp))
|
||||
return;
|
||||
|
||||
if (was_railway)
|
||||
sp->sct_track--;
|
||||
if (is_railway)
|
||||
sp->sct_track++;
|
||||
|
||||
for (i = DIR_FIRST; i <= DIR_LAST; i++) {
|
||||
getsect(sp->sct_x + diroff[i][0],
|
||||
sp->sct_y + diroff[i][1],
|
||||
§);
|
||||
if (SCT_IS_RAILWAY(§) && SCT_EXTENDS_RAIL(§, oldsp))
|
||||
sp->sct_track--;
|
||||
if (SCT_IS_RAILWAY(§) && SCT_EXTENDS_RAIL(§, sp))
|
||||
sp->sct_track++;
|
||||
if (was_railway && SCT_EXTENDS_RAIL(oldsp, §))
|
||||
sect.sct_track--;
|
||||
if (is_railway && SCT_EXTENDS_RAIL(sp, §))
|
||||
sect.sct_track++;
|
||||
putsect(§);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_railway(struct sctstr *sp)
|
||||
{
|
||||
int i;
|
||||
struct sctstr *nsp;
|
||||
|
||||
sp->sct_track = !!SCT_IS_RAILWAY(sp);
|
||||
for (i = DIR_FIRST; i <= DIR_LAST; i++) {
|
||||
nsp = getsectp(sp->sct_x + diroff[i][0],
|
||||
sp->sct_y + diroff[i][1]);
|
||||
if (SCT_IS_RAILWAY(nsp) && SCT_EXTENDS_RAIL(nsp, sp))
|
||||
sp->sct_track++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
issector(char *arg)
|
||||
{
|
||||
|
|
|
@ -87,11 +87,6 @@ finish_sects(int etu)
|
|||
/* Wipe it clean */
|
||||
memset(g_distptrs, 0, WORLD_SZ() * sizeof(*g_distptrs));
|
||||
|
||||
if (opt_RAILWAYS) {
|
||||
for (n = 0; NULL != (sp = getsectid(n)); n++)
|
||||
set_railway(sp);
|
||||
}
|
||||
|
||||
logerror("delivering...\n");
|
||||
/* Do deliveries */
|
||||
for (n = 0; NULL != (sp = getsectid(n)); n++) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue