Claim bridges square by square instead of all at once - #34
Conversation
A bridge held a single claim pool for the whole room: an enemy worker dancing on any one square drained the shared pool and, the tick it hit zero, every tile of the bridge changed hands at once -- however long the bridge and wherever the worker stood. The claim progress now lives per tile (BridgeTileData, mirroring how traps already track per-tile claims). A worker dances one square down and only that square changes hands: it moves into a bridge owned by the claimer, merging with an adjacent bridge of theirs through the existing checkForRoomAbsorbtion, and if the loss cuts the victim's bridge in two the room splitting takes care of the halves. The tile stays a bridge tile throughout, so pathing is never interrupted and flood fill does not change. The stream format still carries one claim value per bridge (the sum of the per-tile values, shared out evenly on load), so existing level files and saves load unchanged. Portals keep their whole-room claim. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| // bridge gets a copy of the tile data, this one keeps the original marked | ||
| // destroyed so seats that still think this bridge covers the tile can keep | ||
| // asking it. The tile stays a bridge tile throughout, so pathing across it | ||
| // is never interrupted for anybody and no flood fill has to change. |
There was a problem hiding this comment.
Still I don't get it why we should mark orignal Tile as destroyed .... WHY ?
There was a problem hiding this comment.
Because the tile is not destroyed for the old bridge's owner's knowledge of the world — it is destroyed for the old room's bookkeeping, and that distinction is exactly what the rest of the codebase uses mCoveredTilesDestroyed + mHP = 0 for whenever a building loses a tile without disappearing:
- Fog of war. The enemy seat may have seen the bridge earlier but have no vision of the square right now. That seat's view still says "this tile is covered by that bridge", and it keeps asking that room about it. The destroyed entry keeps those queries valid, and when the old bridge is eventually removed,
Room::removeFromGameMapwalksmCoveredTilesDestroyedto send each seatnotifyBuildingRemovedFromGameMap— without the entry, a stale-vision seat would never be told and would keep a dangling reference to a dead room. - Save/load.
Building::exportToStreamserialisesmCoveredTiles + mCoveredTilesDestroyed— the destroyed list is part of the room's persistent footprint, so a game saved mid-claim round-trips. - It is the established handover protocol, not something new in this PR.
Building::removeCoveredTiledoes the identical three lines (erase from covered, push to destroyed,mHP = 0);Room::absorbRoommarks every absorbed tile destroyed with the in-code comment "It will get removed from gamemap when enemy vision will be cleared"; andcheckForSplit()from Split a room in two when it stops holding together #23 — already merged — hands tiles to the split-off room the same way. This PR just follows the same convention for the claim handover.
Note the tile itself is fine throughout — it stays a walkable bridge tile, covered by the new bridge. "Destroyed" here only means "no longer mine, but remember I used to cover it until everyone has been told".
|
ForgottenTreasures2.level.txt |
|
You might need to remove the last filetype extension -- 'txt' |
|
I will be without computer for two weeks. Cannot reply right now. |
|
Reproduced with your level, tracked it down — the bridges aren't gone, they've stopped rendering, and the cause is a pre-existing client bug that this PR's per-tile claiming makes visible: #36. What happens: on that map each keeper's wooden bridge sits right next to the other keeper's portal, so enemy workers start claim-dancing on bridge squares within the first minute. Every claimed square triggers a tile recolour on the client, and With #36 applied on top, your level behaves as intended: loading it in the editor and in skirmish looks identical to the old code, and when the enemy workers claim the bridge the squares change to the claimer's colour one at a time, all 27 planks staying visible through 14 handovers in my test run. |
Proposal 3 of the set following the mechanics discussion in #23 — Tom's "I prefer the bridge is to be taken square by square".
Until now a bridge held a single claim pool for the whole room (
RoomBridge::mClaimedValue): a worker dancing on any one square drained the shared pool, and the tick it hit zero the entire bridge — every tile, however long — flipped to the claimer at once. That is the "claim a whole bridge while standing on one square" behaviour Tom noticed.With this PR each bridge tile carries its own claim progress (
BridgeTileData::mClaimedValue, mirroring how traps already do per-tile claiming):checkForRoomAbsorbtion).Save compatibility: the stream format still carries one claim value per bridge (now the sum of the per-tile values, distributed evenly on load), so existing level files and saves load unchanged.
Deliberately not changed: portals (
RoomPortal/RoomPortalWave) keep their whole-room claim — a portal is one logical entity, and taking it square-by-square would mean two players sharing a portal, which seems like its own design discussion.Validated: builds and the full test suite passes via
ctest. The tile-transfer path reuses the same machinery the merged room splitting already exercises (aa-TestRoomSplit); a dedicated dancing-worker scenario test would need a new level fixture and is left for when the mechanic is agreed on.🤖 Generated with Claude Code