Skip to content

Commit

Permalink
Fix prevent_sail_through workaround (#45)
Browse files Browse the repository at this point in the history
* Fix prevent_sail_through workaround

Fix a workaround on PREVENT_SAIL_THROUGH by giving the ships to a new fleet

* If ALLOW_TRIVIAL_PORTAGE is on, giving ships to a new fleet on the other
side has not to be prevented, nor the info is needed in the report

* a small cleanup
  • Loading branch information
sharcashmo authored and artyomtrityak committed Sep 30, 2019
1 parent 3ee1ea3 commit 7f58d9d
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 43 deletions.
47 changes: 6 additions & 41 deletions monthorders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,47 +291,12 @@ Location *Game::Do1SailOrder(ARegion *reg, Object *fleet, Unit *cap)
(TerrainDefs[newreg->type].similar_type != R_OCEAN)) {
cap->Error("SAIL: Can't sail inland.");
stop = 1;
} else if (Globals->PREVENT_SAIL_THROUGH &&
(TerrainDefs[reg->type].similar_type != R_OCEAN) &&
(fleet->flying < 1) &&
(fleet->prevdir != -1) &&
(fleet->prevdir != x->dir)) {
// Check to see if sailing THROUGH land!
// always allow retracing steps
int blocked1 = 0;
int blocked2 = 0;
int d1 = fleet->prevdir;
int d2 = x->dir;
if (d1 > d2) {
int tmp = d1;
d1 = d2;
d2 = tmp;
}
for (int k = d1+1; k < d2; k++) {
ARegion *land1 = reg->neighbors[k];
if ((!land1) ||
(TerrainDefs[land1->type].similar_type !=
R_OCEAN))
blocked1 = 1;
}
int sides = NDIRS - 2 - (d2 - d1 - 1);
for (int l = d2+1; l <= d2 + sides; l++) {
int dl = l;
if (dl >= NDIRS) dl -= NDIRS;
ARegion *land2 = reg->neighbors[dl];
if ((!land2) ||
(TerrainDefs[land2->type].similar_type !=
R_OCEAN))
blocked2 = 1;
}
if ((blocked1) && (blocked2))
{
cap->Error(AString("SAIL: Could not sail ") +
DirectionStrs[x->dir] + AString(" from ") +
reg->ShortPrint(&regions) +
". Cannot sail through land.");
stop = 1;
}
} else if (fleet->SailThroughCheck(x->dir) < 1) {
cap->Error(AString("SAIL: Could not sail ") +
DirectionStrs[x->dir] + AString(" from ") +
reg->ShortPrint(&regions) +
". Cannot sail through land.");
stop = 1;
}

if (!stop) {
Expand Down
88 changes: 88 additions & 0 deletions object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,23 @@ void Object::Report(Areport *f, Faction *fac, int obs, int truesight,
temp += AString(" Sailors: ") + FleetSailingSkill(1) + "/" + GetFleetSize() + ";";
temp += AString(" MaxSpeed: ") + GetFleetSpeed(1);
}
if ((Globals->PREVENT_SAIL_THROUGH) &&
(!Globals->ALLOW_TRIVIAL_PORTAGE)) {
if ((flying < 1) &&
(TerrainDefs[region->type].similar_type != R_OCEAN)) {
int dir = 0;
int first = 1;
temp += AString("; Sail directions: ");
for (dir = 0; dir < NDIRS; dir++) {
if (SailThroughCheck(dir) == 1) {
if (first == 1) first = 0;
else temp += AString(", ");

temp += DirectionAbrs[dir];
}
}
}
}
if (describe) {
temp += AString("; ") + *describe;
}
Expand Down Expand Up @@ -586,6 +603,77 @@ int Object::FleetLoad()
return load;
}

/* Return 1 if fleet can sail to a direction without sailing through land, or
* 0 if it cannot
*/
int Object::SailThroughCheck(int dir)
{
if (IsFleet()) {
// flying fleets always can sail through
if (flying == 1) return 1;

// from ocean sailing is always possible
if (TerrainDefs[region->type].similar_type == R_OCEAN) return 1;

// fleet is not flying and it is in a land region. Check that it
// doesn's sail inland
if (TerrainDefs[region->neighbors[dir]->type].similar_type != R_OCEAN) {
// sailing inland
return 0;
}

// sailing from land into ocean. If sail through is allowed, allow it
if (!Globals->PREVENT_SAIL_THROUGH) return 1;

// if the fleet hadn't sailed before, it can go in any direction
if (prevdir == -1) return 1;

// fleet can always sail backward
if (prevdir == dir) return 1;

// Now we have to check that fleet is not sailing through land
{
// Fleet is on land, it is not flying and comes from another region
// so check that the fleet goes not through land
int blocked1 = 0;
int blocked2 = 0;
int d1 = prevdir;
int d2 = dir;

if (d1 > d2) {
int tmp = d1;
d1 = d2;
d2 = tmp;
}

for (int k = d1+1; k < d2; k++) {
ARegion *land1 = region->neighbors[k];
if ((!land1) ||
(TerrainDefs[land1->type].similar_type !=
R_OCEAN))
blocked1 = 1;
}

int sides = NDIRS - 2 - (d2 - d1 - 1);
for (int l = d2+1; l <= d2 + sides; l++) {
int dl = l;
if (dl >= NDIRS) dl -= NDIRS;
ARegion *land2 = region->neighbors[dl];
if ((!land2) ||
(TerrainDefs[land2->type].similar_type !=
R_OCEAN))
blocked2 = 1;
}

if ((blocked1) && (blocked2))
return 0;
else
return 1;
}
}
return 0;
}

/* Returns the total skill level of all sailors.
* If report is not 0, returns the total skill level of all
* units regardless if they have sail orders (for report
Expand Down
1 change: 1 addition & 0 deletions object.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class Object : public AListElem
AString FleetDefinition();
int FleetCapacity();
int FleetLoad();
int SailThroughCheck(int dir);
int FleetSailingSkill(int);
int GetFleetSize();
int GetFleetSpeed(int);
Expand Down
31 changes: 29 additions & 2 deletions runorders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2693,9 +2693,12 @@ int Game::DoGiveOrder(ARegion *r, Unit *u, GiveOrder *o)

// give into existing fleet or form new fleet?
newfleet = 0;

// target is not in fleet or not fleet owner
if (!(t->object->IsFleet()) ||
(t->num != t->object->GetOwner()->num)) newfleet = 1;

// Set fleet variable to target fleet
if (newfleet == 1) {
// create a new fleet
fleet = new Object(r);
Expand All @@ -2705,14 +2708,38 @@ int Game::DoGiveOrder(ARegion *r, Unit *u, GiveOrder *o)
t->object->region->AddFleet(fleet);
t->MoveUnit(fleet);
}
else {
fleet = t->object;
}

if (ItemDefs[o->item].max_inventory) {
cur = t->object->GetNumShips(o->item) + amt;
if (cur > ItemDefs[o->item].max_inventory) {
u->Error(ord + ": Fleets cannot have more than "+
ItemString(o->item, ItemDefs[o->item].max_inventory) +".");
u->Error(ord + ": Fleets cannot have more than " +
ItemString(o->item, ItemDefs[o->item].max_inventory) +
".");
return 0;
}
}

// Check if fleets are compatible
if ((Globals->PREVENT_SAIL_THROUGH) &&
(!Globals->ALLOW_TRIVIAL_PORTAGE) &&
// flying ships are always transferrable
(ItemDefs[o->item].fly == 0)) {
// if target fleet had not sailed, just copy shore from source
if (fleet->prevdir == -1) {
fleet->prevdir = s->object->prevdir;
} else {
// check that source ship is compatible with its new fleet
if (s->object->SailThroughCheck(fleet->prevdir) == 0) {
u->Error(ord +
": Ships cannot be transferred through land.");
return 0;
}
}
}

s->Event(AString("Transfers ") + ItemString(o->item, amt) + " to " +
*t->object->name + ".");
if (s->faction != t->faction) {
Expand Down

0 comments on commit 7f58d9d

Please sign in to comment.