Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
98c402e
Allow bridgeable water type that is both swimmable and walkable
tothxa Oct 19, 2025
5419ebd
'src/logic/map.cc' was automatically formatted.
Oct 19, 2025
ab22dee
don't allow placing immovables on bridgeable water
tothxa Oct 19, 2025
9abfbff
don't allow flags in the water on waterways
tothxa Oct 19, 2025
05b68d0
fix roadbuilding mode steepness indicators
tothxa Oct 20, 2025
1f44742
3 files were automatically formatted.
Oct 20, 2025
2a6980f
make bridgeable a new terrain type, only make it walkable where bridg…
tothxa Oct 21, 2025
196fd0f
'src/logic/map.cc' was automatically formatted.
Oct 21, 2025
6dda7f6
add 1 default fish to bridgeable water to allow fish breeding
tothxa Oct 21, 2025
0868d7f
let AI build roads on bridgeable water, add terrain type icon in edit…
tothxa Oct 21, 2025
b5d80de
example map: reintroduce the fords in Forest Valley with bridgeable w…
tothxa Oct 22, 2025
a95e134
Merge branch 'master' into bridgeable
tothxa Nov 11, 2025
1b66102
don't change nodecaps, do everything in checkstep
tothxa Nov 14, 2025
d618873
don't allow flags on bridgeable water
tothxa Nov 14, 2025
00c48a9
Merge branch 'master' into bridgeable
tothxa Nov 14, 2025
49d7bda
update Forest Valley map: leave place for a flag between the rocks
tothxa Nov 14, 2025
4c598cb
'src/logic/map_objects/checkstep.cc' was automatically formatted.
Nov 14, 2025
e909fd9
try to shut up clang-tidy
tothxa Nov 14, 2025
b4a0e7d
Merge branch 'master' into bridgeable
Dec 22, 2025
b62b935
extend bridges of atl-emp-fri
tothxa Jan 14, 2026
6b5d65a
Merge branch 'master' into bridgeable
tothxa Jan 14, 2026
27d0886
Revert "extend bridges of atl-emp-fri"
tothxa Feb 10, 2026
c334fb1
Merge branch 'master' into bridgeable
tothxa Feb 10, 2026
f658e1a
add bridge pillars between bridge segments on bridgeable nodes
tothxa Feb 11, 2026
a95db79
3 files were automatically formatted.
Feb 11, 2026
ba1825a
clang-tidy
tothxa Feb 11, 2026
e73d68a
Merge branch 'master' into bridgeable
tothxa Feb 22, 2026
99a51c7
Merge remote-tracking branch 'codeberg/master' into bridgeable
tothxa Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added data/images/wui/editor/terrain_bridgeable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/wui/overlays/bridge_0.5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/wui/overlays/bridge_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/wui/overlays/bridge_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/wui/overlays/bridge_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file added data/maps/Forest_Valley.wmf/binary/terrain
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Automatically created by Widelands 1.2~git26575 (5372ade@master) Release
# Automatically created by Widelands 1.3~git27123 (6487353@bridgeable) Release

[global]
packet_version="1"
map_w="112"
map_h="80"
nr_players="2"
name=_"Forest Valley v2.0"
name=_"Forest Valley v2.1"
author="tvj, tothxa"
descr=_"A river valley surrounded by mountains with lots of resources except coal. Plenty of flat building space."
hint=
Expand Down
12 changes: 12 additions & 0 deletions data/maps/Forest_Valley.wmf/version
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Automatically created by Widelands 1.3~git27123 (6487353@bridgeable) Release

[global]
map_source_url=
map_release=
map_creator_version="build-19"
map_version_major="0"
map_version_minor="9"
map_version_timestamp="1761151649"
packet_version="1"
packet_compatibility="1"
minimum_required_widelands_version="1.3"
Binary file removed data/maps/Forest_Valley_v2.wmf/binary/terrain
Binary file not shown.
12 changes: 0 additions & 12 deletions data/maps/Forest_Valley_v2.wmf/version

This file was deleted.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 14 additions & 7 deletions data/tribes/initialization/atlanteans/units.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,19 @@
--
-- **name**: A string containing the internal name of the tribe.
--
-- **animations**: Global animations. Contains subtables for ``frontier``, ``flag``, and ``pinned_note``.
-- Each animation needs the parameter ``hotspot`` (2 integer coordinates),
-- and may also define ``fps`` (integer frames per second).
--
-- **animation_directory**: The location of the animation png files.
--
-- **bridges**: Contains animations for ``normal_e``, ``normal_se``, ``normal_sw``,
-- ``busy_e``, ``busy_se`` and ``busy_sw``.
-- **animations**: Global animations. Contains subtables for:
--
-- * ``frontier``
-- * ``flag``
-- * ``pinned_note``
-- * ``bridge_normal_e``, ``bridge_normal_se``, ``bridge_normal_sw``
-- * ``bridge_busy_e``, ``bridge_busy_se``, ``bridge_busy_sw``
-- * (optional) ``bridge_pillar_normal``, ``bridge_pillar_busy`` .. versionadded:: 1.4
--
-- Each animation needs the parameter ``hotspot`` (2 integer coordinates),
-- and may also define ``fps`` (integer frames per second).
--
-- **bridge_height**: The height in pixels of each bridge at it's summit at 1x scale.
--
Expand Down Expand Up @@ -349,7 +354,9 @@ wl.Descriptions():new_tribe {
bridge_normal_se = { hotspot = {8, 8} },
bridge_busy_se = { hotspot = {8, 8} },
bridge_normal_sw = { hotspot = {40, 8} },
bridge_busy_sw = { hotspot = {40, 8} }
bridge_busy_sw = { hotspot = {40, 8} },
bridge_pillar_normal = { hotspot = {14, 9} },
bridge_pillar_busy = { hotspot = {14, 9} },
},
spritesheets = {
flag = {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion data/tribes/initialization/empire/units.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ wl.Descriptions():new_tribe {
bridge_normal_se = { hotspot = {8, 8} },
bridge_busy_se = { hotspot = {8, 8} },
bridge_normal_sw = { hotspot = {40, 8} },
bridge_busy_sw = { hotspot = {40, 8} }
bridge_busy_sw = { hotspot = {40, 8} },
bridge_pillar_normal = { hotspot = {14, 9} },
bridge_pillar_busy = { hotspot = {14, 9} },
},
spritesheets = {
frontier = {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion data/tribes/initialization/frisians/units.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ wl.Descriptions():new_tribe {
bridge_normal_se = { hotspot = {8, 8} },
bridge_busy_se = { hotspot = {8, 8} },
bridge_normal_sw = { hotspot = {40, 8} },
bridge_busy_sw = { hotspot = {40, 8} }
bridge_busy_sw = { hotspot = {40, 8} },
bridge_pillar_normal = { hotspot = {18, 13} },
bridge_pillar_busy = { hotspot = {18, 13} },
},
spritesheets = {
flag = {
Expand Down
1 change: 1 addition & 0 deletions data/world/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ local result = {
"summer_snow",
"lava",
"summer_water",
"summer_bridgeable_water",
}
},
{
Expand Down
19 changes: 19 additions & 0 deletions data/world/terrains/summer/bridgeable_water/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
push_textdomain("world")

wl.Descriptions():new_terrain_type{
name = "summer_bridgeable_water",
descname = _("Bridgeable Water"),
is = "bridgeable",
valid_resources = {"resource_fish"},
default_resource = "resource_fish",
default_resource_amount = 1,
textures = path.list_files(path.dirname(__file__) .. "bridgeable_??.png"),
dither_layer = 181,
fps = 10,
temperature = 100,
humidity = 999,
fertility = 1,
enhancement = { diking = "summer_beach" }
}

pop_textdomain()
3 changes: 3 additions & 0 deletions data/world/terrains/summer/bridgeable_water/register.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
return {
summer_bridgeable_water = {}
}
49 changes: 33 additions & 16 deletions src/ai/ai_help_structs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ constexpr int kNeuronsPos = 1;
constexpr int kFNeuronsPos = 2;

// CheckStepRoadAI
// TODO(tothxa): Unify with main CheckStepRoad
CheckStepRoadAI::CheckStepRoadAI(Widelands::Player* const pl, uint8_t const mc, bool const oe)
: player(pl), movecaps(mc), open_end(oe) {
}
Expand All @@ -55,9 +56,20 @@ bool CheckStepRoadAI::allowed(const Widelands::Map& map,
return false;
}

// Calculate cost and passability
// Check passability
if ((endcaps & movecaps) == 0) {
return false;
// Check exceptions
if ((movecaps & Widelands::MOVECAPS_WALK) != 0) {
if ((endcaps & Widelands::BUILDCAPS_BRIDGE) == 0) {
return false;
}
} else {
assert((movecaps & Widelands::MOVECAPS_SWIM) != 0);
if (((endcaps & Widelands::MOVECAPS_WALK) == 0) ||
((player->get_buildcaps(start) & Widelands::MOVECAPS_SWIM) == 0)) {
return false;
}
}
}

// Check for blocking immovables
Expand All @@ -82,17 +94,16 @@ bool CheckStepRoadAI::reachable_dest(const Widelands::Map& map,
const Widelands::FCoords& dest) const {
Widelands::NodeCaps const caps = dest.field->nodecaps();

if ((caps & movecaps) == 0) {
if (((movecaps & Widelands::MOVECAPS_SWIM) == 0) ||
((caps & Widelands::MOVECAPS_WALK) == 0)) {
return false;
}
if (!map.can_reach_by_water(dest)) {
return false;
}
if ((caps & movecaps) != 0) {
return true;
}

return true;
if ((movecaps & Widelands::MOVECAPS_WALK) != 0) {
return (caps & Widelands::BUILDCAPS_BRIDGE) != 0;
}

assert((movecaps & Widelands::MOVECAPS_SWIM) != 0);
return map.can_reach_by_water(dest);
}

// CheckStepOwnTerritory
Expand All @@ -105,7 +116,7 @@ CheckStepOwnTerritory::CheckStepOwnTerritory(Widelands::Player* const pl,
// Defines when movement is allowed:
// 1. startfield is walkable (or it is the first step)
// And endfield either:
// 2a. is walkable
// 2a. is walkable or bridgeable
// 2b. has our PlayerImmovable (building or flag)
bool CheckStepOwnTerritory::allowed(const Widelands::Map& map,
Widelands::FCoords start,
Expand All @@ -121,13 +132,19 @@ bool CheckStepOwnTerritory::allowed(const Widelands::Map& map,
return false;
}

// TODO(tothxa): Needs changing if the AI is made to handle waterways
if ((movecaps & Widelands::MOVECAPS_WALK) == 0) {
NEVER_HERE();
}

// Start field must be walkable
if ((startcaps & movecaps) == 0) {
if (((startcaps & movecaps) == 0) && ((startcaps & Widelands::BUILDCAPS_BRIDGE) == 0)) {
return false;
}

// Endfield can not be water
if ((endcaps & Widelands::MOVECAPS_SWIM) != 0) {
if (((endcaps & Widelands::MOVECAPS_SWIM) != 0) &&
((endcaps & Widelands::BUILDCAPS_BRIDGE) == 0)) {
return false;
}

Expand All @@ -138,10 +155,10 @@ bool CheckStepOwnTerritory::allowed(const Widelands::Map& map,
bool CheckStepOwnTerritory::reachable_dest(const Widelands::Map& map,
const Widelands::FCoords& dest) const {
const uint8_t endcaps = player->get_buildcaps(dest);
if (Widelands::BaseImmovable const* const imm = map.get_immovable(dest)) {
if (Widelands::BaseImmovable const* const imm = map.get_immovable(dest); imm != nullptr) {
return imm->descr().type() >= Widelands::MapObjectType::FLAG;
}
return (endcaps & Widelands::MOVECAPS_WALK) != 0;
return (endcaps & (Widelands::MOVECAPS_WALK | Widelands::BUILDCAPS_BRIDGE)) != 0;
}

// We are looking for fields we can walk on
Expand Down
8 changes: 4 additions & 4 deletions src/economy/road.cc
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,8 @@ bool Road::notify_ware(Game& game, FlagId const flagid) {
return false;
}

// This returns true if and only if this is road covers the specified edge and
// both triangles adjacent to that edge are unwalkable
// This returns true if and only if this road covers the specified edge and
// both triangles adjacent to that edge are water or unwalkable
bool Road::is_bridge(const EditorGameBase& egbase, const FCoords& field, uint8_t dir) const {
const Map& map = egbase.map();

Expand Down Expand Up @@ -439,9 +439,9 @@ bool Road::is_bridge(const EditorGameBase& egbase, const FCoords& field, uint8_t
NEVER_HERE();
}
return ((egbase.descriptions().get_terrain_descr(fd.field->terrain_d())->get_is() &
TerrainDescription::Is::kUnwalkable) != 0) &&
(TerrainDescription::Is::kWater | TerrainDescription::Is::kUnwalkable)) != 0) &&
((egbase.descriptions().get_terrain_descr(fr.field->terrain_r())->get_is() &
TerrainDescription::Is::kUnwalkable) != 0);
(TerrainDescription::Is::kWater | TerrainDescription::Is::kUnwalkable)) != 0);
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/graphic/gl/fields_to_draw.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ void FieldsToDraw::reset(const Widelands::EditorGameBase& egbase,

f.ln_index = calculate_index(fx - 1, fy);
f.rn_index = calculate_index(fx + 1, fy);
f.tln_index = calculate_index(fx + (fy & 1) - 1, fy - 1);
f.trn_index = calculate_index(fx + (fy & 1), fy - 1);
f.bln_index = calculate_index(fx + (fy & 1) - 1, fy + 1);
f.brn_index = calculate_index(fx + (fy & 1), fy + 1);
Expand Down
13 changes: 11 additions & 2 deletions src/graphic/gl/fields_to_draw.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,15 @@ class FieldsToDraw {
// neighbor is not contained.
int ln_index;
int rn_index;
int tln_index;
int trn_index;
int bln_index;
int brn_index;

[[nodiscard]] inline bool all_neighbors_valid() const {
return ln_index != kInvalidIndex && rn_index != kInvalidIndex &&
trn_index != kInvalidIndex && bln_index != kInvalidIndex &&
brn_index != kInvalidIndex;
tln_index != kInvalidIndex && trn_index != kInvalidIndex &&
bln_index != kInvalidIndex && brn_index != kInvalidIndex;
}
};

Expand All @@ -94,6 +95,14 @@ class FieldsToDraw {
return &fields_[index];
}

// Returns the field at 'index' if it is valid, otherwise returns nullptr.
[[nodiscard]] inline const Field* check_field(const int index) const {
if (index == kInvalidIndex) {
return nullptr;
}
return &fields_[index];
}

// Calculates the index of the given field with ('fx', 'fy') being geometric
// coordinates in the map. Returns INVALID_INDEX if this field is not in the
// fields_to_draw.
Expand Down
3 changes: 2 additions & 1 deletion src/logic/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ class Field {
Buildhelp_Big = 3,
Buildhelp_Mine = 4,
Buildhelp_Port = 5,
Buildhelp_None = 6
Buildhelp_Bridge = 6,
Buildhelp_None = 7
};

using Height = uint8_t;
Expand Down
Loading
Loading