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:
Markus Armbruster 2008-04-15 07:57:03 +02:00 committed by Markus Armbruster
parent 11100f23e5
commit fa5fa4abcc
10 changed files with 46 additions and 79 deletions

View file

@ -284,6 +284,7 @@ ifeq ($(empthread),Windows)
$(client): src/lib/w32/getopt.o $(client): src/lib/w32/getopt.o
endif endif
$(util): src/lib/common/move.o # FIXME hack for opt_RAILWAYS
$(util): $(libs) $(util): $(libs)
lib/libas.a: $(filter src/lib/as/%, $(obj)) lib/libas.a: $(filter src/lib/as/%, $(obj))

View file

@ -627,7 +627,6 @@ extern void sathead(void);
extern int sct_postread(int, void *); extern int sct_postread(int, void *);
extern int sct_prewrite(int, void *); extern int sct_prewrite(int, void *);
extern void item_prewrite(short *); extern void item_prewrite(short *);
extern void set_railway(struct sctstr *);
extern int issector(char *); extern int issector(char *);
/* sectdamage.c */ /* sectdamage.c */
extern int sect_damage(struct sctstr *, int); extern int sect_damage(struct sctstr *, int);

View file

@ -77,7 +77,6 @@ struct sctstr {
natid sct_oldown; /* old owner of sector (for liberation) */ natid sct_oldown; /* old owner of sector (for liberation) */
unsigned char sct_updated; /* Has this sect been updated? */ unsigned char sct_updated; /* Has this sect been updated? */
unsigned char sct_off; /* Should this sector produce? */ 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_item[I_MAX+1]; /* amount of items stored here */
short sct_del[I_MAX+1]; /* delivieries */ short sct_del[I_MAX+1]; /* delivieries */
short sct_dist[I_MAX+1]; /* distribution thresholds */ short sct_dist[I_MAX+1]; /* distribution thresholds */
@ -189,7 +188,7 @@ extern struct dchrstr bigcity_dchr;
/* Can trains enter sector SP? */ /* Can trains enter sector SP? */
#define SCT_HAS_RAIL(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) : intrchr[INT_RAIL].in_enable && (sp)->sct_rail != 0)
#define MOB_MOVE 0 #define MOB_MOVE 0
@ -227,5 +226,6 @@ struct sctintrins {
extern struct sctintrins intrchr[INT_DEF + 2]; extern struct sctintrins intrchr[INT_DEF + 2];
extern int fort_fire(struct sctstr *); extern int fort_fire(struct sctstr *);
extern int sct_rail_track(struct sctstr *);
#endif #endif

View file

@ -74,7 +74,7 @@ sinfra(void)
pr("%4d%% ", sect.sct_road); pr("%4d%% ", sect.sct_road);
prmobcost(&sect, MOB_MOVE); prmobcost(&sect, MOB_MOVE);
if (opt_RAILWAYS) if (opt_RAILWAYS)
pr(sect.sct_track ? " yes " : " no "); pr(sct_rail_track(&sect) ? " yes " : " no ");
else else
pr("%4d%% ", sect.sct_rail); pr("%4d%% ", sect.sct_rail);
prmobcost(&sect, MOB_RAIL); prmobcost(&sect, MOB_RAIL);

View file

@ -224,7 +224,7 @@ spyline(struct sctstr *sp)
sp->sct_oldown, sp->sct_oldown,
roundintby((int)sp->sct_effic, 10), roundintby((int)sp->sct_effic, 10),
roundintby((int)sp->sct_road, 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((int)sp->sct_defense, 10),
roundintby(sp->sct_item[I_CIVIL], 10), roundintby(sp->sct_item[I_CIVIL], 10),
roundintby(sp->sct_item[I_MILIT], 10), roundintby(sp->sct_item[I_MILIT], 10),

View file

@ -33,6 +33,7 @@
#include <config.h> #include <config.h>
#include "file.h"
#include "misc.h" #include "misc.h"
#include "nat.h" #include "nat.h"
#include "optlist.h" #include "optlist.h"
@ -90,3 +91,33 @@ speed_factor(double effspd, int tech)
{ {
return 480.0 / (effspd + techfact(tech, effspd)); 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;
}

View file

@ -47,6 +47,7 @@
static void *nsc_ver(struct valstr *, struct natstr *, void *); static void *nsc_ver(struct valstr *, struct natstr *, void *);
static void *nsc_ver_maxnoc(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_att(struct valstr *, struct natstr *, void *);
static void *nsc_pln_def(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 *); 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}, {"uran", fldoff(sct_uran), NSC_UCHAR, 0, NULL, EF_BAD, 0},
{"oldown", fldoff(sct_oldown), NSC_NATID, 0, NULL, EF_NATION, 0}, {"oldown", fldoff(sct_oldown), NSC_NATID, 0, NULL, EF_NATION, 0},
{"off", fldoff(sct_off), NSC_UCHAR, 0, NULL, EF_BAD, 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_item), ""),
NSC_IVEC(fldoff(sct_dist), "_dist"), NSC_IVEC(fldoff(sct_dist), "_dist"),
NSC_IVEC(fldoff(sct_del), "_del"), NSC_IVEC(fldoff(sct_del), "_del"),
@ -766,6 +767,13 @@ nsc_ver_maxnoc(struct valstr *val, struct natstr *np, void *ptr)
return NULL; 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 * static void *
nsc_pln_def(struct valstr *val, struct natstr *np, void *ptr) nsc_pln_def(struct valstr *val, struct natstr *np, void *ptr)
{ {

View file

@ -285,7 +285,7 @@ satdisp_sect(struct sctstr *sp, int acc)
dchr[sp->sct_type].d_mnem, dchr[sp->sct_type].d_mnem,
sp->sct_own, roundintby((int)sp->sct_effic, acc / 2), sp->sct_own, roundintby((int)sp->sct_effic, acc / 2),
roundintby((int)sp->sct_road, 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((int)sp->sct_defense, acc / 2),
roundintby(sp->sct_item[I_CIVIL], acc), roundintby(sp->sct_item[I_CIVIL], acc),
roundintby(sp->sct_item[I_MILIT], acc), roundintby(sp->sct_item[I_MILIT], acc),

View file

@ -42,7 +42,6 @@
#include "nat.h" #include "nat.h"
#include "nsc.h" #include "nsc.h"
#include "optlist.h" #include "optlist.h"
#include "path.h"
#include "plane.h" #include "plane.h"
#include "player.h" #include "player.h"
#include "prototypes.h" #include "prototypes.h"
@ -50,7 +49,6 @@
#include "xy.h" #include "xy.h"
static int checksect(struct sctstr *); static int checksect(struct sctstr *);
static void update_railway(struct sctstr *, struct sctstr *);
int int
sct_postread(int id, void *ptr) sct_postread(int id, void *ptr)
@ -73,8 +71,6 @@ sct_prewrite(int id, void *ptr)
bridge_damaged(sp); bridge_damaged(sp);
checksect(sp); checksect(sp);
getsect(sp->sct_x, sp->sct_y, &sect); getsect(sp->sct_x, sp->sct_y, &sect);
if (opt_RAILWAYS)
update_railway(sp, &sect);
return 1; return 1;
} }
@ -132,69 +128,6 @@ checksect(struct sctstr *sp)
return 1; return 1;
} }
/* Minimal efficiency for railway and railway extension (opt_RAILWAYS) */
#define SCT_RAIL_EFF 5
#define SCT_RAIL_EXT_EFF 60
/* Is sector SP a railway? */
#define SCT_IS_RAILWAY(sp) \
(dchr[(sp)->sct_type].d_mob1 == 0 && (sp)->sct_effic >= SCT_RAIL_EFF)
/* May sector SP have a railway extension? */
#define SCT_MAY_HAVE_RAIL_EXT(sp) \
((sp)->sct_effic >= SCT_RAIL_EXT_EFF)
/* Does railway sector SP extend railway track into sector TOSP? */
#define SCT_EXTENDS_RAIL(sp, tosp) \
((sp)->sct_own == (tosp)->sct_own && SCT_MAY_HAVE_RAIL_EXT(tosp))
static void
update_railway(struct sctstr *sp, struct sctstr *oldsp)
{
struct sctstr sect;
int was_railway = SCT_IS_RAILWAY(oldsp);
int is_railway = SCT_IS_RAILWAY(sp);
int i;
if (was_railway == is_railway
&& sp->sct_own == oldsp->sct_own
&& SCT_MAY_HAVE_RAIL_EXT(sp) == SCT_MAY_HAVE_RAIL_EXT(oldsp))
return;
if (was_railway)
sp->sct_track--;
if (is_railway)
sp->sct_track++;
for (i = DIR_FIRST; i <= DIR_LAST; i++) {
getsect(sp->sct_x + diroff[i][0],
sp->sct_y + diroff[i][1],
&sect);
if (SCT_IS_RAILWAY(&sect) && SCT_EXTENDS_RAIL(&sect, oldsp))
sp->sct_track--;
if (SCT_IS_RAILWAY(&sect) && SCT_EXTENDS_RAIL(&sect, sp))
sp->sct_track++;
if (was_railway && SCT_EXTENDS_RAIL(oldsp, &sect))
sect.sct_track--;
if (is_railway && SCT_EXTENDS_RAIL(sp, &sect))
sect.sct_track++;
putsect(&sect);
}
}
void
set_railway(struct sctstr *sp)
{
int i;
struct sctstr *nsp;
sp->sct_track = !!SCT_IS_RAILWAY(sp);
for (i = DIR_FIRST; i <= DIR_LAST; i++) {
nsp = getsectp(sp->sct_x + diroff[i][0],
sp->sct_y + diroff[i][1]);
if (SCT_IS_RAILWAY(nsp) && SCT_EXTENDS_RAIL(nsp, sp))
sp->sct_track++;
}
}
int int
issector(char *arg) issector(char *arg)
{ {

View file

@ -87,11 +87,6 @@ finish_sects(int etu)
/* Wipe it clean */ /* Wipe it clean */
memset(g_distptrs, 0, WORLD_SZ() * sizeof(*g_distptrs)); 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"); logerror("delivering...\n");
/* Do deliveries */ /* Do deliveries */
for (n = 0; NULL != (sp = getsectid(n)); n++) { for (n = 0; NULL != (sp = getsectid(n)); n++) {