Verflucht komplizierter Fix in movement. Das kann eigentlich nur schiefgehen.

Bei der Gelegenheit mal in movement etwas Code-Massage betrieben. Das ist zwar grundsätzlich ein hoffnungsloser Fall, aber ich kann's nicht lassen.
This commit is contained in:
Enno Rehling 2004-04-12 16:21:23 +00:00
parent 2dad5d7e69
commit 9ef7e473d8
9 changed files with 822 additions and 840 deletions

View File

@ -464,7 +464,7 @@ set_movement_order(unit * u, const region * target, int moves, boolean (*allowed
region * prev = plan[position]; region * prev = plan[position];
region * next = plan[++position]; region * next = plan[++position];
direction_t dir = reldirection(prev, next); direction_t dir = reldirection(prev, next);
assert(dir!=NODIRECTION); assert(dir!=NODIRECTION && dir!=D_SPECIAL);
*c++ = ' '; *c++ = ' ';
strcpy(c, locale_string(u->faction->locale, directions[dir])); strcpy(c, locale_string(u->faction->locale, directions[dir]));
c += strlen(c); c += strlen(c);
@ -849,21 +849,6 @@ static void ponnuki(unit * u)
NULL }; NULL };
int jokes = 0; int jokes = 0;
/*
attrib * a = a_find(u->attribs, &at_direction);
if (!a) {
a_add(&u->attribs, a = a_new(&at_direction));
a->data.i = D_NORTHWEST;
}
if (rand() % 10 == 0) a->data.i = rand() % MAXDIRECTIONS;
travel(u->region, u, u->region->connect[a->data.i], false);
*/
/* Rausgenommen, übergibt irgendwann NULL, das führt zu einem
* SegFault. */
while(joke[jokes]) jokes++; while(joke[jokes]) jokes++;
if (jokes) addmessage(u->region, 0, joke[rand() % jokes], MSG_MESSAGE, ML_IMPORTANT); if (jokes) addmessage(u->region, 0, joke[rand() % jokes], MSG_MESSAGE, ML_IMPORTANT);

View File

@ -1005,9 +1005,6 @@ prices(FILE * F, const region * r, const faction * f)
rparagraph(F, buf, 0, 0); rparagraph(F, buf, 0, 0);
} }
/* ------------------------------------------------------------- */
extern const direction_t back[MAXDIRECTIONS];
/* ------------------------------------------------------------- */
boolean boolean
see_border(const border * b, const faction * f, const region * r) see_border(const border * b, const faction * f, const region * r)

View File

@ -2422,7 +2422,7 @@ aftermath(battle * b)
fset(du, UFL_MOVED); fset(du, UFL_MOVED);
leave(du->region, du); leave(du->region, du);
if (df->run.region) { if (df->run.region) {
travel(r, du, df->run.region, 1); travel(du, df->run.region, 1, NULL);
df->run.region = du->region; df->run.region = du->region;
} }
} else } else

View File

@ -56,12 +56,14 @@ typedef short spellid_t;
struct plane; struct plane;
struct spell; struct spell;
struct region; struct region;
struct region_list;
struct race; struct race;
struct ship; struct ship;
struct building; struct building;
struct faction; struct faction;
struct party; struct party;
struct unit; struct unit;
struct unit_list;
struct item; struct item;
/* item */ /* item */
struct strlist; struct strlist;
@ -724,6 +726,7 @@ enum {
D_WEST, D_WEST,
MAXDIRECTIONS, MAXDIRECTIONS,
D_PAUSE, D_PAUSE,
D_SPECIAL,
NODIRECTION = (direction_t) - 1 NODIRECTION = (direction_t) - 1
}; };

View File

@ -454,17 +454,20 @@ travelthru(const unit * u, region * r)
} }
static void static void
leave_trail(unit * u, region **route, region * to) leave_trail(unit * u, region * from, region_list *route)
{ {
region **ri = route;
ship * sh = u->ship; ship * sh = u->ship;
region * r = from;
while (*ri) { while (route!=NULL) {
region * r = *ri++; region * rn = route->data;
region * rn = *ri?*ri:to;
direction_t dir = reldirection(r, rn); direction_t dir = reldirection(r, rn);
attrib * a = a_find(r->attribs, &at_traveldir_new);
/* TODO: we cannot leave a trail into special directions
* if we use this kind of direction-attribute */
if (dir<MAXDIRECTIONS && dir>=0) {
traveldir * td = NULL; traveldir * td = NULL;
attrib * a = a_find(r->attribs, &at_traveldir_new);
while (a!=NULL) { while (a!=NULL) {
td = (traveldir *)a->data.v; td = (traveldir *)a->data.v;
@ -479,23 +482,25 @@ leave_trail(unit * u, region **route, region * to)
} }
td->dir = dir; td->dir = dir;
td->age = 2; td->age = 2;
}
route = route->next;
r = rn;
} }
} }
static void static void
travel_route(const unit * u, region ** route) travel_route(const unit * u, region_list * route)
{ {
region **ri = route; /* kein travelthru in der letzten region! */
while (route && route->next) {
while (*ri) { region * r = route->data;
region * r = *ri++;
travelthru(u, r); travelthru(u, r);
route = route->next;
} }
} }
ship * ship *
move_ship(ship * sh, region * from, region * to, region ** route) move_ship(ship * sh, region * from, region * to, region_list * route)
{ {
unit **iunit = &from->units; unit **iunit = &from->units;
unit **ulist = &to->units; unit **ulist = &to->units;
@ -512,7 +517,7 @@ move_ship(ship * sh, region * from, region * to, region ** route)
if (u->ship == sh) { if (u->ship == sh) {
if (!trail) { if (!trail) {
leave_trail(u, route, to); leave_trail(u, from, route);
trail = true; trail = true;
} }
if (route!=NULL) travel_route(u, route); if (route!=NULL) travel_route(u, route);
@ -537,7 +542,6 @@ drifting_ships(region * r)
direction_t d; direction_t d;
ship *sh, *sh2; ship *sh, *sh2;
unit *captain; unit *captain;
region * route[2] = { 0, 0 };
if (rterrain(r) == T_OCEAN) { if (rterrain(r) == T_OCEAN) {
for (sh = r->ships; sh;) { for (sh = r->ships; sh;) {
@ -602,15 +606,14 @@ drifting_ships(region * r)
/* Das Schiff und alle Einheiten darin werden nun von r /* Das Schiff und alle Einheiten darin werden nun von r
* nach rconnect(r, d) verschoben. Danach eine Meldung. */ * nach rconnect(r, d) verschoben. Danach eine Meldung. */
#if 0
/* ich bin fast sicher, das man das nicht braucht. (enno) */
for (f = factions; f; f = f->next)
freset(f, FL_DH);
#endif
if (fval(sh, SF_DRIFTED)) { if (fval(sh, SF_DRIFTED)) {
region_list * route = NULL;
region * to = rconnect(r, d);
/* wenn schon einmal abgetrieben, dann durchreise eintragen */ /* wenn schon einmal abgetrieben, dann durchreise eintragen */
route[0] = r; add_regionlist(&route, r);
sh = move_ship(sh, r, rconnect(r, d), route); add_regionlist(&route, to);
sh = move_ship(sh, r, to, route);
free_regionlist(route);
} else sh = move_ship(sh, r, rconnect(r, d), NULL); } else sh = move_ship(sh, r, rconnect(r, d), NULL);
if (!sh) { if (!sh) {
sh = sh2; sh = sh2;
@ -623,7 +626,7 @@ drifting_ships(region * r)
/* Alle Attribute /* Alle Attribute
* sicherheitshalber loeschen und * sicherheitshalber loeschen und
* gegebenenfalls neu setzen. */ * gegebenenfalls neu setzen. */
sh->coast = back[d]; sh->coast = dir_invert(d);
} }
damage_ship(sh, 0.02); damage_ship(sh, 0.02);
@ -910,41 +913,40 @@ cantravel(const unit *u, const region *from, const region * to, boolean (*allowe
static boolean static boolean
roadto(const region * r, const region * r2) roadto(const region * r, direction_t dir)
{ {
/* wenn es hier genug strassen gibt, und verbunden ist, und es dort /* wenn es hier genug strassen gibt, und verbunden ist, und es dort
* genug strassen gibt, dann existiert eine strasse in diese richtung */ * genug strassen gibt, dann existiert eine strasse in diese richtung */
region * r2;
direction_t i; if (dir>=MAXDIRECTIONS || dir<0) return false;
r2 = rconnect(r, dir);
if (r==NULL || r2==NULL) return false;
if (!r || !r2) return false;
for (i = 0; i != MAXDIRECTIONS; i++)
if (rconnect(r, i) == r2) {
if (terrain[rterrain(r)].roadreq==0) return false; if (terrain[rterrain(r)].roadreq==0) return false;
if (terrain[rterrain(r2)].roadreq==0) return false; if (terrain[rterrain(r2)].roadreq==0) return false;
if (rroad(r, i) < terrain[rterrain(r)].roadreq) return false; if (rroad(r, dir) < terrain[rterrain(r)].roadreq) return false;
if (rroad(r2, back[i]) < terrain[rterrain(r2)].roadreq) return false; if (rroad(r2, dir_invert(dir)) < terrain[rterrain(r2)].roadreq) return false;
return true; return true;
} }
return false;
}
direction_t * void
travel(region * first, unit * u, region * next, int flucht) travel(unit * u, region * next, int flucht, region_list ** routep)
{ {
region *current = first; region *first = u->region;
int k, m, i, dh; region *current = u->region;
int k, m = 0;
double dk; double dk;
unit *wache;
region *rv[MAXSPEED];
strlist *S; strlist *S;
unit *ut, *u2; unit *ut, *u2;
int gereist = 0; int gereist = 0;
static direction_t route[MAXSPEED]; region_list *route = NULL;
region_list **iroute = &route;
static boolean init = false; static boolean init = false;
static const curse_type * speed_ct; static const curse_type * speed_ct;
static const curse_type * fogtrap_ct; static const curse_type * fogtrap_ct;
if (routep) *routep = NULL;
if (!init) { if (!init) {
init = true; init = true;
speed_ct = ct_find("speed"); speed_ct = ct_find("speed");
@ -965,45 +967,43 @@ travel(region * first, unit * u, region * next, int flucht)
{ /* Die Einheit kann nicht fliegen, ist im Ozean, und will an Land */ { /* Die Einheit kann nicht fliegen, ist im Ozean, und will an Land */
if (!(u->race->flags & RCF_SWIM) && old_race(u->race) != RC_AQUARIAN) { if (!(u->race->flags & RCF_SWIM) && old_race(u->race) != RC_AQUARIAN) {
cmistake(u, findorder(u, u->thisorder), 44, MSG_MOVE); cmistake(u, findorder(u, u->thisorder), 44, MSG_MOVE);
return NULL; return;
} else { } else {
if (u->ship && get_item(u, I_HORSE) > 0) { if (u->ship && get_item(u, I_HORSE) > 0) {
cmistake(u, findorder(u, u->thisorder), 67, MSG_MOVE); cmistake(u, findorder(u, u->thisorder), 67, MSG_MOVE);
return NULL; return;
} }
} }
} else if (rterrain(current)!=T_OCEAN) { } else if (rterrain(current)!=T_OCEAN) {
/* An Land kein NACH wenn in dieser Runde Schiff VERLASSEN! */ /* An Land kein NACH wenn in dieser Runde Schiff VERLASSEN! */
if (leftship(u) && is_guarded(current, u, GUARD_LANDING)) { if (leftship(u) && is_guarded(current, u, GUARD_LANDING)) {
cmistake(u, findorder(u, u->thisorder), 70, MSG_MOVE); cmistake(u, findorder(u, u->thisorder), 70, MSG_MOVE);
return NULL; return;
} }
if (u->ship && !flucht && u->race->flags & RCF_SWIM) { if (u->ship && !flucht && u->race->flags & RCF_SWIM) {
cmistake(u, findorder(u, u->thisorder), 143, MSG_MOVE); cmistake(u, findorder(u, u->thisorder), 143, MSG_MOVE);
return NULL; return;
} }
} else if (rterrain(next) == T_OCEAN && u->ship && fval(u->ship, SF_MOVED)) { } else if (rterrain(next) == T_OCEAN && u->ship && fval(u->ship, SF_MOVED)) {
cmistake(u, findorder(u, u->thisorder), 13, MSG_MOVE); cmistake(u, findorder(u, u->thisorder), 13, MSG_MOVE);
return NULL; return;
} }
switch (canwalk(u)) { switch (canwalk(u)) {
case 1: case 1:
cmistake(u, findorder(u, u->thisorder), 57, MSG_MOVE); cmistake(u, findorder(u, u->thisorder), 57, MSG_MOVE);
return NULL; return;
case 2: case 2:
cmistake(u, findorder(u, u->thisorder), 56, MSG_MOVE); cmistake(u, findorder(u, u->thisorder), 56, MSG_MOVE);
return NULL; return;
case 3: case 3:
cmistake(u, findorder(u, u->thisorder), 42, MSG_MOVE); cmistake(u, findorder(u, u->thisorder), 42, MSG_MOVE);
return NULL; return;
} }
/* wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden /* wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden
* dann nacheinander ausgeführt. */ * dann nacheinander ausgeführt. */
/* im array rv[] speichern wir die Regionen ab, durch die wir wandern. */
dk = u->race->speed; dk = u->race->speed;
if (speed_ct) { if (speed_ct) {
@ -1061,8 +1061,6 @@ travel(region * first, unit * u, region * next, int flucht)
k = BP_DRAGON; k = BP_DRAGON;
} }
m = 0;
/* die nächste Region, in die man wandert, wird durch movewhere() aus /* die nächste Region, in die man wandert, wird durch movewhere() aus
* der letzten Region bestimmt. * der letzten Region bestimmt.
* *
@ -1071,15 +1069,18 @@ travel(region * first, unit * u, region * next, int flucht)
* die noch möglichen Schritte, r3 die letzte gültige, befahrene Region. */ * die noch möglichen Schritte, r3 die letzte gültige, befahrene Region. */
while (next) { while (next) {
direction_t dir = reldirection(current, next);
border * b = get_borders(current, next); border * b = get_borders(current, next);
direction_t reldir = reldirection(current, next);
while (b!=NULL) { while (b!=NULL) {
if (b->type==&bt_wisps) { if (b->type==&bt_wisps) {
wall_data * wd = (wall_data*)b->data; wall_data * wd = (wall_data*)b->data;
assert(reldir!=D_SPECIAL);
if (wd->active) { if (wd->active) {
region * rl = rconnect(current, (direction_t)((dir+MAXDIRECTIONS-1)%MAXDIRECTIONS)); /* pick left and right region: */
region * rr = rconnect(current, (direction_t)((dir+1)%MAXDIRECTIONS)); region * rl = rconnect(current, (direction_t)((reldir+MAXDIRECTIONS-1)%MAXDIRECTIONS));
region * rr = rconnect(current, (direction_t)((reldir+1)%MAXDIRECTIONS));
int j = rand() % 3; int j = rand() % 3;
if (j==0) break; if (j==0) break;
else if (j==1 && rl && landregion(rterrain(rl))==landregion(rterrain(next))) next = rl; else if (j==1 && rl && landregion(rterrain(rl))==landregion(rterrain(next))) next = rl;
@ -1091,33 +1092,29 @@ travel(region * first, unit * u, region * next, int flucht)
b = b->next; b = b->next;
} }
if (current!=next) { /* !pause */ if (current!=next) { /* !pause */
if (roadto(current, next)) if (roadto(current, reldir)) k-=BP_ROAD;
k -= BP_ROAD; else k-=BP_NORMAL;
else
k -= BP_NORMAL;
if (k<0) break; if (k<0) break;
/* r2 -> Zielregion, r3 -> Momentane Region */
if ((dir>=0 && move_blocked(u, current, dir)) if ((reldir>=0 && move_blocked(u, current, reldir))
|| curse_active(get_curse(current->attribs, fogtrap_ct))) || curse_active(get_curse(current->attribs, fogtrap_ct)))
{ {
ADDMSG(&u->faction->msgs, msg_message("leavefail", ADDMSG(&u->faction->msgs, msg_message("leavefail",
"unit region", "unit region", u, next));
u, next));
} }
if (!entrance_allowed(u, next)) { if (!entrance_allowed(u, next)) {
ADDMSG(&u->faction->msgs, msg_message("regionowned", ADDMSG(&u->faction->msgs, msg_message("regionowned",
"unit region target", "unit region target", u, current, next));
u, current, next));
break; break;
} }
if ((wache = bewegung_blockiert_von(u, current)) != (unit *) NULL if (gereist) {
&& gereist != 0) unit * wache = bewegung_blockiert_von(u, current);
{ if (wache!=NULL) {
ADDMSG(&u->faction->msgs, msg_message("moveblockedbyguard", ADDMSG(&u->faction->msgs, msg_message("moveblockedbyguard",
"unit region guard", u, current, "unit region guard", u, current, wache));
wache));
break; break;
} }
}
if (fval(u->race, RCF_ILLUSIONARY)) { if (fval(u->race, RCF_ILLUSIONARY)) {
curse * c = get_curse(next->attribs, ct_find("antimagiczone")); curse * c = get_curse(next->attribs, ct_find("antimagiczone"));
@ -1126,7 +1123,9 @@ travel(region * first, unit * u, region * next, int flucht)
add_message(&u->faction->msgs, new_message(u->faction, add_message(&u->faction->msgs, new_message(u->faction,
"illusionantimagic%u:unit", u)); "illusionantimagic%u:unit", u));
destroy_unit(u); destroy_unit(u);
return route; if (routep) *routep = route;
else free_regionlist(route);
return;
} }
} }
/* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne /* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne
@ -1134,36 +1133,36 @@ travel(region * first, unit * u, region * next, int flucht)
if (rterrain(next) == T_OCEAN && !canswim(u)) { if (rterrain(next) == T_OCEAN && !canswim(u)) {
plane *pl = getplane(next); plane *pl = getplane(next);
if (pl!=NULL && fval(pl, PFL_NOCOORDS)) { if (reldir<MAXDIRECTIONS && pl!=NULL && fval(pl, PFL_NOCOORDS)) {
add_message(&u->faction->msgs, new_message(u->faction, ADDMSG(&u->faction->msgs, msg_message("detectoceandir",
"detectoceandir%u:unit%i:direction", u, dir)); "unit direction", u, reldir));
} else { } else {
add_message(&u->faction->msgs, new_message(u->faction, ADDMSG(&u->faction->msgs, msg_message("detectocean",
"detectocean%u:unit%r:region", u, next)); "unit region", u, next));
} }
break; break;
} }
if (terrain[rterrain(next)].flags & FORBIDDEN_LAND) { if (terrain[rterrain(next)].flags & FORBIDDEN_LAND) {
plane *pl = getplane(next); plane *pl = getplane(next);
if(pl && fval(pl, PFL_NOCOORDS)) { if (reldir<MAXDIRECTIONS && pl!=NULL && fval(pl, PFL_NOCOORDS)) {
add_message(&u->faction->msgs, new_message(u->faction, ADDMSG(&u->faction->msgs, msg_message("detectforbiddendir",
"detectforbiddendir%u:unit%i:direction", u, dir)); "unit direction", u, reldir));
} else { } else {
add_message(&u->faction->msgs, new_message(u->faction, ADDMSG(&u->faction->msgs, msg_message("detectforbidden",
"detectforbidden%u:unit%r:region", u, next)); "unit region", u, next));
} }
break; break;
} }
if (old_race(u->race) == RC_INSECT && r_insectstalled(next) && if (old_race(u->race) == RC_INSECT && r_insectstalled(next) && !is_cursed(u->attribs, C_KAELTESCHUTZ,0))
!is_cursed(u->attribs, C_KAELTESCHUTZ,0)) { {
add_message(&u->faction->msgs, new_message(u->faction, ADDMSG(&u->faction->msgs, msg_message("detectforbidden",
"detectforbidden%u:unit%r:region", u, next)); "unit region", u, next));
break; break;
} }
rv[m] = next; add_regionlist(iroute, next);
route[m] = dir; iroute = &(*iroute)->next;
m++; m++;
} else { } else {
break; break;
@ -1176,7 +1175,6 @@ travel(region * first, unit * u, region * next, int flucht)
next = movewhere(current, u); next = movewhere(current, u);
} }
} }
route[m] = NODIRECTION;
if (gereist) { if (gereist) {
int mode; int mode;
@ -1206,20 +1204,20 @@ travel(region * first, unit * u, region * next, int flucht)
m--; m--;
if (m > 0) { if (m > 0) {
dh = 0; region_list *rlist;
travelthru(u, first); travelthru(u, first);
for (i = 0; i != m; i++) { for (rlist = route;rlist!=NULL;rlist=rlist->next) {
char * p; char * p;
if (dh) {
if (i == m - 1) if (rlist!=route) {
scat(" und "); if (rlist->next==NULL) scat(" und ");
else else scat(", ");
scat(", ");
} }
dh = 1; travelthru(u, rlist->data);
travelthru(u, rv[i]);
p = buf+strlen(buf); p = buf+strlen(buf);
MSG(("travelthru_trail", "region", rv[i]), p, sizeof(buf)-strlen(buf), u->faction->locale, u->faction); MSG(("travelthru_trail", "region", rlist->data), p, sizeof(buf)-strlen(buf), u->faction->locale, u->faction);
} }
} }
add_message(&u->faction->msgs, new_message( add_message(&u->faction->msgs, new_message(
@ -1248,8 +1246,7 @@ travel(region * first, unit * u, region * next, int flucht)
continue; continue;
} }
if (can_survive(ut, current)) { if (can_survive(ut, current)) {
for (i = 0; i != m; i++) travel_route(ut, route);
travelthru(ut, rv[i]);
move_unit(ut, current, NULL); move_unit(ut, current, NULL);
} else { } else {
cmistake(u, u->thisorder, 287, MSG_MOVE); cmistake(u, u->thisorder, 287, MSG_MOVE);
@ -1283,7 +1280,9 @@ travel(region * first, unit * u, region * next, int flucht)
setguard(u, GUARD_NONE); setguard(u, GUARD_NONE);
if (fval(u, UFL_FOLLOWING)) caught_target(current, u); if (fval(u, UFL_FOLLOWING)) caught_target(current, u);
return route; if (routep) *routep = route;
else free_regionlist(route);
return;
} }
static boolean static boolean
@ -1376,18 +1375,14 @@ check_working_buildingtype(const region * r, const building_type * bt)
static boolean static boolean
check_takeoff(ship *sh, region *from, region *to) check_takeoff(ship *sh, region *from, region *to)
{ {
direction_t dir;
direction_t coast, coastl, coastr;
if (rterrain(from)!=T_OCEAN && sh->coast != NODIRECTION) { if (rterrain(from)!=T_OCEAN && sh->coast != NODIRECTION) {
coast = sh->coast; direction_t coast = sh->coast;
dir = reldirection(from, to); direction_t dir = reldirection(from, to);
direction_t coastr = (direction_t)((coast+1) % MAXDIRECTIONS);
coastr = (direction_t)((coast+1) % MAXDIRECTIONS); direction_t coastl = (direction_t)((coast+MAXDIRECTIONS-1) % MAXDIRECTIONS);
coastl = (direction_t)((coast+MAXDIRECTIONS-1) % MAXDIRECTIONS);
if (dir!=coast && dir!=coastl && dir!=coastr if (dir!=coast && dir!=coastl && dir!=coastr
&& check_working_buildingtype(from, bt_find("harbour")) == false) && !check_working_buildingtype(from, bt_find("harbour")))
{ {
return false; return false;
} }
@ -1407,18 +1402,18 @@ ship_allowed(const struct ship_type * type, region * r)
return false; return false;
} }
static direction_t * static region_list *
sail(region * starting_point, unit * u, region * next_point, boolean move_on_land) sail(unit * u, region * next_point, boolean move_on_land)
{ {
region * starting_point = u->region;
region *current_point, *last_point; region *current_point, *last_point;
unit *u2, *hafenmeister; unit *u2, *hafenmeister;
item * trans = NULL; item * trans = NULL;
int st, first = 1; int st, first = 1;
int k, m, l, i, step = 0; int k, step = 0;
int stormchance; int stormchance;
region *rv[MAXSPEED + 1]; region_list *route = NULL;
region *tt[MAXSPEED + 1]; /* travelthru */ region_list **iroute = &route;
static direction_t route[MAXSPEED+1]; /* route[i] := direction from tt[i] to tt[i-1] */
static boolean init = false; static boolean init = false;
static const curse_type * fogtrap_ct; static const curse_type * fogtrap_ct;
if (!init) { if (!init) {
@ -1434,9 +1429,6 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
k = shipspeed(u->ship, u); k = shipspeed(u->ship, u);
l = 0;
m = 0;
last_point = starting_point; last_point = starting_point;
current_point = starting_point; current_point = starting_point;
@ -1444,25 +1436,21 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
* letzten Region bestimmt. * letzten Region bestimmt.
* *
* Anfangen tun wir bei starting_point. next_point ist beim ersten * Anfangen tun wir bei starting_point. next_point ist beim ersten
* Durchlauf schon gesetzt (Parameter!). l zählt gesichtete * Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gültige,
* Küstenstreifen, rv[] speichert die gesichteten Küstenstreifen, m
* zählt befahrene Felder, current_point ist die letzte gültige,
* befahrene Region. */ * befahrene Region. */
tt[step] = starting_point;
while (current_point!=next_point && m < k && next_point) while (current_point!=next_point && step < k && next_point)
{ {
direction_t dir = reldirection(current_point, next_point); direction_t dir = reldirection(current_point, next_point);
if(terrain[rterrain(next_point)].flags & FORBIDDEN_LAND) { if(terrain[rterrain(next_point)].flags & FORBIDDEN_LAND) {
plane *pl = getplane(next_point); plane *pl = getplane(next_point);
if(pl && fval(pl, PFL_NOCOORDS)) { if(pl && fval(pl, PFL_NOCOORDS)) {
add_message(&u->faction->msgs, new_message(u->faction, ADDMSG(&u->faction->msgs, msg_message("sailforbiddendir",
"sailforbiddendir%h:ship%i:direction", "ship direction", u->ship, dir));
u->ship, reldirection(current_point,next_point)));
} else { } else {
add_message(&u->faction->msgs, new_message(u->faction, ADDMSG(&u->faction->msgs, msg_message("sailforbidden",
"sailforbidden%h:ship%r:region", u->ship, next_point)); "ship region", u->ship, next_point));
} }
break; break;
} }
@ -1472,7 +1460,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
if (rterrain(current_point) != T_OCEAN if (rterrain(current_point) != T_OCEAN
&& rterrain(next_point) != T_OCEAN) { && rterrain(next_point) != T_OCEAN) {
plane *pl = getplane(next_point); plane *pl = getplane(next_point);
if(pl && fval(pl, PFL_NOCOORDS)) { if (dir<MAXDIRECTIONS && pl && fval(pl, PFL_NOCOORDS)) {
sprintf(buf, "Die %s entdeckt, daß im %s Festland ist.", sprintf(buf, "Die %s entdeckt, daß im %s Festland ist.",
shipname(u->ship), locale_string(u->faction->locale, directions[dir])); shipname(u->ship), locale_string(u->faction->locale, directions[dir]));
} else { } else {
@ -1510,7 +1498,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
/* Falls Blockade, endet die Seglerei hier */ /* Falls Blockade, endet die Seglerei hier */
if (move_blocked(u, current_point, reldirection(current_point, next_point)) if (move_blocked(u, current_point, dir)
|| curse_active(get_curse(current_point->attribs, fogtrap_ct))) { || curse_active(get_curse(current_point->attribs, fogtrap_ct))) {
add_message(&u->faction->msgs, new_message(u->faction, add_message(&u->faction->msgs, new_message(u->faction,
"sailfail%h:ship%r:region", u->ship, current_point)); "sailfail%h:ship%r:region", u->ship, current_point));
@ -1543,7 +1531,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
if(pl && fval(pl, PFL_NOCOORDS)) { if(pl && fval(pl, PFL_NOCOORDS)) {
add_message(&u->faction->msgs, new_message(u->faction, add_message(&u->faction->msgs, new_message(u->faction,
"sailforbiddendir%h:ship%i:direction", "sailforbiddendir%h:ship%i:direction",
u->ship, reldirection(current_point,next_point))); u->ship, dir));
/* sprintf(buf, "Die Mannschaft der %s weigert sich, in die Feuerwand " /* sprintf(buf, "Die Mannschaft der %s weigert sich, in die Feuerwand "
"im %s zu fahren.", "im %s zu fahren.",
shipname(u->ship), directions[dir]); */ shipname(u->ship), directions[dir]); */
@ -1580,29 +1568,18 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
} /* endif !flying */ } /* endif !flying */
/* Falls kein Problem, eines weiter ziehen */ /* Falls kein Problem, eines weiter ziehen */
route[step] = dir;
tt[step] = current_point; /* travelthrough */
fset(u->ship, SF_MOVED); fset(u->ship, SF_MOVED);
add_regionlist(iroute, next_point);
iroute = &(*iroute)->next;
step++; step++;
m++;
last_point = current_point; last_point = current_point;
current_point = next_point; current_point = next_point;
/* Falls eine Küstenregion, dann in rv[] aufnehmen (die letzte
* Küste wird nachher nicht aufgelistet werden, wenn das
* Schiff dort seine Runde beendent!). */
if (rterrain(current_point) != T_OCEAN) {
rv[l] = current_point;
l++;
}
if (rterrain(current_point) != T_OCEAN && !is_cursed(u->ship->attribs, C_SHIP_FLYING, 0)) break; if (rterrain(current_point) != T_OCEAN && !is_cursed(u->ship->attribs, C_SHIP_FLYING, 0)) break;
next_point = movewhere(current_point, u); next_point = movewhere(current_point, u);
} }
route[step] = NODIRECTION;
/* at this point, step is the number of steps made. tt[step] is the final region. */
/* Nun enthält current_point die Region, in der das Schiff seine Runde /* Nun enthält current_point die Region, in der das Schiff seine Runde
* beendet hat. Wir generieren hier ein Ereignis für den Spieler, das * beendet hat. Wir generieren hier ein Ereignis für den Spieler, das
* ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck * ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck
@ -1630,38 +1607,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
scat(regionid(starting_point)); scat(regionid(starting_point));
scat(" nach "); scat(" nach ");
scat(regionid(current_point)); scat(regionid(current_point));
/* Falls es Kuesten gibt, denen man entlang gefahren ist,
* sollen sie aufgefuehrt werden. Falls wir aber unseren Zug in
* einer Kuestenregion beendet haben, fuehren wir sie nicht mit
* auf - sie wird sowieso in allen Details im Report erwaehnt
* werden. */
if (rterrain(current_point) != T_OCEAN)
l--;
if (l > 0) {
if( is_cursed(sh->attribs, C_SHIP_FLYING, 0) )
scat(". Dabei flog es über ");
else {
scat(". Dabei segelte es entlang der ");
if (l > 1)
scat("Küsten");
else
scat("Küste");
scat(" von ");
}
for (i = 0; i != l; i++) {
scat(regionid(rv[i]));
if (i < l - 2)
scat(", ");
else if (i == l - 2)
scat(" und ");
}
}
scat("."); scat(".");
addmessage(0, u->faction, buf, MSG_MOVE, ML_INFO); addmessage(0, u->faction, buf, MSG_MOVE, ML_INFO);
/* Das Schiff und alle Einheiten darin werden nun von /* Das Schiff und alle Einheiten darin werden nun von
@ -1670,8 +1616,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
/* Verfolgungen melden */ /* Verfolgungen melden */
if (fval(u, UFL_FOLLOWING)) caught_target(current_point, u); if (fval(u, UFL_FOLLOWING)) caught_target(current_point, u);
tt[step] = NULL; sh = move_ship(sh, starting_point, current_point, route);
sh = move_ship(sh, starting_point, current_point, tt);
/* Hafengebühren ? */ /* Hafengebühren ? */
@ -1745,6 +1690,19 @@ kapitaen(region * r, ship * sh)
return NULL; return NULL;
} }
static const char *
direction_name(const region * from, const region * to, const struct locale * lang)
{
direction_t dir = reldirection(from, to);
if (dir<MAXDIRECTIONS && dir>=0) return locale_string(lang, directions[dir]);
if (dir==D_SPECIAL) {
spec_direction *sd = special_direction(from, to);
return sd->keyword;
}
assert(!"invalid direction");
return NULL;
}
/* Segeln, Wandern, Reiten /* Segeln, Wandern, Reiten
* when this routine returns a non-zero value, movement for the region needs * when this routine returns a non-zero value, movement for the region needs
* to be done again because of followers that got new MOVE orders. * to be done again because of followers that got new MOVE orders.
@ -1752,21 +1710,21 @@ kapitaen(region * r, ship * sh)
* by this routine * by this routine
*/ */
static int static int
move(region * r, unit * u, boolean move_on_land) move(unit * u, boolean move_on_land)
{ {
region *r2; region * r = u->region;
direction_t * route; region_list * route = NULL;
region * r2 = movewhere(r, u);
r2 = movewhere(r, u); if (r2==NULL) {
if (!r2) {
cmistake(u, findorder(u, u->thisorder), 71, MSG_MOVE); cmistake(u, findorder(u, u->thisorder), 71, MSG_MOVE);
return 0; return 0;
} }
else if (u->ship && fval(u, UFL_OWNER)) else if (u->ship && fval(u, UFL_OWNER)) {
route = sail(r, u, r2, move_on_land); route = sail(u, r2, move_on_land);
else } else {
route = travel(r, u, r2, 0); travel(u, r2, 0, &route);
}
if (i_get(u->items, &it_demonseye)) { if (i_get(u->items, &it_demonseye)) {
direction_t d; direction_t d;
@ -1774,7 +1732,7 @@ move(region * r, unit * u, boolean move_on_land)
region * rc = rconnect(r2,d); region * rc = rconnect(r2,d);
if (rc) { if (rc) {
sprintf(buf, "Im %s ist eine ungeheure magische Präsenz zu verspüren.", sprintf(buf, "Im %s ist eine ungeheure magische Präsenz zu verspüren.",
locale_string(u->faction->locale, directions[back[d]])); locale_string(u->faction->locale, directions[dir_invert(d)]));
addmessage(rc, NULL, buf, MSG_EVENT, ML_IMPORTANT); addmessage(rc, NULL, buf, MSG_EVENT, ML_IMPORTANT);
} }
} }
@ -1783,7 +1741,7 @@ move(region * r, unit * u, boolean move_on_land)
if (u->region!=r) fset(u, UFL_LONGACTION); if (u->region!=r) fset(u, UFL_LONGACTION);
set_string(&u->thisorder, ""); set_string(&u->thisorder, "");
if (fval(u, UFL_FOLLOWED) && route && route[0]!=NODIRECTION) { if (fval(u, UFL_FOLLOWED) && route!=NULL) {
int followers = 0; int followers = 0;
unit *up; unit *up;
for (up=r->units;up;up=up->next) { for (up=r->units;up;up=up->next) {
@ -1791,10 +1749,16 @@ move(region * r, unit * u, boolean move_on_land)
const attrib * a = a_findc(up->attribs, &at_follow); const attrib * a = a_findc(up->attribs, &at_follow);
if (a && a->data.v==u) { if (a && a->data.v==u) {
/* wir basteln ihm ein NACH */ /* wir basteln ihm ein NACH */
int k, i = 0; int k;
region_list * rlist = route;
region * from = u->region;
strcpy(buf, locale_string(up->faction->locale, keywords[K_MOVE])); strcpy(buf, locale_string(up->faction->locale, keywords[K_MOVE]));
while (route[i]!=NODIRECTION) while (rlist!=NULL) {
strcat(strcat(buf, " "), locale_string(up->faction->locale, directions[route[i++]])); strcat(strcat(buf, " "), direction_name(from, rlist->data, up->faction->locale));
from = rlist->data;
rlist = rlist->next;
}
set_string(&up->thisorder, buf); set_string(&up->thisorder, buf);
k = igetkeyword(up->thisorder, up->faction->locale); k = igetkeyword(up->thisorder, up->faction->locale);
assert(k==K_MOVE); assert(k==K_MOVE);
@ -1804,6 +1768,7 @@ move(region * r, unit * u, boolean move_on_land)
} }
return followers; return followers;
} }
if (route!=NULL) free_regionlist(route);
return 0; return 0;
} }
@ -1944,7 +1909,7 @@ piracy(unit *u)
/* Bewegung ausführen */ /* Bewegung ausführen */
igetkeyword(u->thisorder, u->faction->locale); /* NACH ignorieren */ igetkeyword(u->thisorder, u->faction->locale); /* NACH ignorieren */
return move(r, u, true); return move(u, true);
} }
static void static void
@ -2043,7 +2008,7 @@ hunt(unit *u)
igetkeyword(command, u->faction->locale); /* NACH ignorieren und Parsing initialisieren. */ igetkeyword(command, u->faction->locale); /* NACH ignorieren und Parsing initialisieren. */
/* NACH ausführen */ /* NACH ausführen */
if (move(u->region, u, false)!=0) { if (move(u, false)!=0) {
/* niemand sollte auf einen kapitän direkt ein folge haben, oder? */ /* niemand sollte auf einen kapitän direkt ein folge haben, oder? */
assert(1==0); assert(1==0);
} }
@ -2250,11 +2215,11 @@ movement(void)
} else { } else {
if (ships) { if (ships) {
if (u->ship && fval(u, UFL_OWNER)) { if (u->ship && fval(u, UFL_OWNER)) {
if (move(r, u, true)!=0) repeat = true; if (move(u, true)!=0) repeat = true;
} }
} else { } else {
if (u->ship==NULL || !fval(u, UFL_OWNER)) { if (u->ship==NULL || !fval(u, UFL_OWNER)) {
if (move(r, u, true)!=0) repeat = true; if (move(u, true)!=0) repeat = true;
} }
} }
} }

View File

@ -51,14 +51,13 @@ extern int personcapacity(const struct unit *u);
extern direction_t getdirection(const struct locale *); extern direction_t getdirection(const struct locale *);
extern void movement(void); extern void movement(void);
extern void travel(struct unit * u, struct region * r2, int flucht, struct region_list** routep);
extern direction_t * travel(struct region * r, struct unit * u, struct region * r2, int flucht);
extern struct unit *is_guarded(struct region * r, struct unit * u, unsigned int mask); extern struct unit *is_guarded(struct region * r, struct unit * u, unsigned int mask);
extern int enoughsailors(struct region * r, struct ship * sh); extern int enoughsailors(struct region * r, struct ship * sh);
extern boolean canswim(struct unit *u); extern boolean canswim(struct unit *u);
extern struct unit *kapitaen(struct region * r, struct ship * sh); extern struct unit *kapitaen(struct region * r, struct ship * sh);
extern void travelthru(const struct unit * u, struct region * r); extern void travelthru(const struct unit * u, struct region * r);
extern struct ship * move_ship(struct ship * sh, struct region * from, struct region * to, struct region ** route); extern struct ship * move_ship(struct ship * sh, struct region * from, struct region * to, struct region_list * route);
extern void follow_unit(void); extern void follow_unit(void);

View File

@ -60,7 +60,7 @@ const int delta_y[MAXDIRECTIONS] =
1, 1, 0, -1, -1, 0 1, 1, 0, -1, -1, 0
}; };
const direction_t back[MAXDIRECTIONS] = static const direction_t back[MAXDIRECTIONS] =
{ {
D_SOUTHEAST, D_SOUTHEAST,
D_SOUTHWEST, D_SOUTHWEST,
@ -70,6 +70,20 @@ const direction_t back[MAXDIRECTIONS] =
D_EAST, D_EAST,
}; };
direction_t
dir_invert(direction_t dir)
{
switch (dir) {
case D_PAUSE:
case D_SPECIAL:
return dir;
break;
default:
if (dir>=0 && dir<MAXDIRECTIONS) return back[dir];
}
assert(!"illegal direction");
return NODIRECTION;
}
const char * const char *
regionname(const region * r, const faction * f) regionname(const region * r, const faction * f)
{ {
@ -288,6 +302,7 @@ r_connect(const region * r, direction_t dir)
#ifdef FAST_CONNECT #ifdef FAST_CONNECT
region * rmodify = (region*)r; region * rmodify = (region*)r;
assert (dir>=0 && dir<MAXDIRECTIONS);
if (r->connect[dir]) return r->connect[dir]; if (r->connect[dir]) return r->connect[dir];
#endif #endif
assert(dir<MAXDIRECTIONS); assert(dir<MAXDIRECTIONS);
@ -343,21 +358,40 @@ distance(const region * r1, const region * r2)
return koor_distance(r1->x, r1->y, r2->x, r2->y); return koor_distance(r1->x, r1->y, r2->x, r2->y);
} }
direction_t static direction_t
koor_reldirection(int ax, int ay, int bx, int by) koor_reldirection(int ax, int ay, int bx, int by)
{ {
direction_t i; direction_t dir;
for (i=0;i!=MAXDIRECTIONS;++i) { for (dir=0;dir!=MAXDIRECTIONS;++dir) {
if (bx-ax == delta_x[i] && if (bx-ax == delta_x[dir] && by-ay == delta_y[dir]) return dir;
by-ay == delta_y[i]) return i;
} }
return NODIRECTION; return NODIRECTION;
} }
direction_t spec_direction *
reldirection(region * from, region * to) special_direction(const region * from, const region * to)
{ {
return koor_reldirection(from->x, from->y, to->x, to->y); spec_direction *sd;
const attrib *a = a_findc(from->attribs, &at_direction);
while (a!=NULL) {
sd = (spec_direction *)a->data.v;
if (sd->active && sd->x==to->x && sd->y==to->y) return sd;
a = a->nexttype;
}
return NULL;
}
direction_t
reldirection(const region * from, const region * to)
{
direction_t dir = koor_reldirection(from->x, from->y, to->x, to->y);
if (dir==NODIRECTION) {
spec_direction *sd = special_direction(from, to);
if (sd!=NULL) return D_SPECIAL;
}
return dir;
} }
void void

View File

@ -110,7 +110,7 @@ typedef struct region_list {
extern struct message_list * r_getmessages(const struct region * r, const struct faction * viewer); extern struct message_list * r_getmessages(const struct region * r, const struct faction * viewer);
extern struct message * r_addmessage(struct region * r, const struct faction * viewer, struct message * msg); extern struct message * r_addmessage(struct region * r, const struct faction * viewer, struct message * msg);
typedef struct { typedef struct spec_direction {
int x; int x;
int y; int y;
int duration; int duration;
@ -126,8 +126,7 @@ typedef struct {
#define region_hashkey(r) (abs((r)->x + 0x100 * (r)->y)) #define region_hashkey(r) (abs((r)->x + 0x100 * (r)->y))
int distance(const struct region*, const struct region*); int distance(const struct region*, const struct region*);
int koor_distance(int ax, int ay, int bx, int by) ; int koor_distance(int ax, int ay, int bx, int by) ;
direction_t reldirection(struct region * from, struct region * to); extern direction_t reldirection(const struct region * from, const struct region * to);
direction_t koor_reldirection(int ax, int ay, int bx, int by) ;
extern struct region * findregion(int x, int y); extern struct region * findregion(int x, int y);
extern attrib_type at_direction; extern attrib_type at_direction;
@ -151,6 +150,7 @@ void runhash(struct region * r);
void free_regionlist(region_list *rl); void free_regionlist(region_list *rl);
void add_regionlist(region_list **rl, struct region *r); void add_regionlist(region_list **rl, struct region *r);
extern struct spec_direction * special_direction(const region * from, const region * to);
int woodcount(const struct region * r); int woodcount(const struct region * r);
int deathcount(const struct region * r); int deathcount(const struct region * r);
@ -220,8 +220,7 @@ extern void terraform(struct region * r, terrain_t terrain);
extern const int delta_x[MAXDIRECTIONS]; extern const int delta_x[MAXDIRECTIONS];
extern const int delta_y[MAXDIRECTIONS]; extern const int delta_y[MAXDIRECTIONS];
extern const direction_t back[MAXDIRECTIONS]; extern direction_t dir_invert(direction_t dir);
extern int production(const struct region *r); extern int production(const struct region *r);
extern int read_region_reference(struct region ** r, FILE * F); extern int read_region_reference(struct region ** r, FILE * F);
extern void write_region_reference(const struct region * r, FILE * F); extern void write_region_reference(const struct region * r, FILE * F);

View File

@ -219,7 +219,7 @@ autoseed(struct region_list * rlist)
if (r && r->land) { if (r && r->land) {
int k; int k;
for (k=i+1;k!=nseeds;++k) if (seeds[k].region==r) { for (k=i+1;k!=nseeds;++k) if (seeds[k].region==r) {
seeds[k].next[back[d]] = seeds+i; seeds[k].next[dir_invert(d)] = seeds+i;
seeds[i].next[d] = seeds+k; seeds[i].next[d] = seeds+k;
} }
} }