@@ -133,8 +133,8 @@ public void UpdateTileOwners() {
133133 foreach ( Tile t in city . GetTilesWithinBorders ( ) ) {
134134 // If another city has claim to this tile, we need to resolve
135135 // that conflict.
136- if ( t . owningCity != null ) {
137- t . owningCity = ResolveTileOwnershipConflict ( t . owningCity , city , t ) ;
136+ if ( t . owningCity != null && ResolveTileOwnershipConflict ( t . owningCity , city , t , out City winnerCity ) ) {
137+ t . owningCity = winnerCity ;
138138 t . owningCity . owner . tileKnowledge . AddTilesToKnown ( t , recomputeActiveTiles ) ;
139139 continue ;
140140 }
@@ -150,26 +150,29 @@ public void UpdateTileOwners() {
150150
151151 foreach ( Tile t in player . tileKnowledge . knownTiles . Where ( t => t . owningCity == null && t . GetEdgeNeighbors ( ) . Any ( e => e . owningCity != null ) ) . ToList ( ) ) {
152152 // Law VII
153- if ( t . neighbors . TryGetValue ( TileDirection . NORTHWEST , out Tile tnw )
154- && t . neighbors . TryGetValue ( TileDirection . SOUTHEAST , out Tile tse )
155- && tnw . owningCity != null && tse . owningCity != null
156- && tnw . owningCity . owner == tse . owningCity . owner ) {
157- t . owningCity = ResolveTileOwnershipConflict ( tnw . owningCity , tse . owningCity , t ) ;
158- t . owningCity . owner . tileKnowledge . AddTilesToKnown ( t ) ;
159- continue ;
160- }
153+ TryResolveOpposingNeighbors ( t , TileDirection . NORTHWEST , TileDirection . SOUTHEAST ) ;
154+ if ( t . owningCity != null ) continue ;
161155 // Law VIII
162- if ( t . neighbors . TryGetValue ( TileDirection . NORTHEAST , out Tile tne )
163- && t . neighbors . TryGetValue ( TileDirection . SOUTHWEST , out Tile tsw )
164- && tne . owningCity != null && tsw . owningCity != null
165- && tne . owningCity . owner == tsw . owningCity . owner ) {
166- t . owningCity = ResolveTileOwnershipConflict ( tne . owningCity , tsw . owningCity , t ) ;
167- t . owningCity . owner . tileKnowledge . AddTilesToKnown ( t ) ;
168- }
156+ TryResolveOpposingNeighbors ( t , TileDirection . NORTHEAST , TileDirection . SOUTHWEST ) ;
169157 }
170158 }
171159 }
172160
161+ private void TryResolveOpposingNeighbors ( Tile t , TileDirection dirA , TileDirection dirB ) {
162+ if ( ! t . neighbors . TryGetValue ( dirA , out Tile a ) || ! t . neighbors . TryGetValue ( dirB , out Tile b ) ) return ;
163+ if ( a . owningCity == null || b . owningCity == null ) return ;
164+ if ( a . owningCity . owner != b . owningCity . owner ) return ;
165+ if ( ! ResolveTileOwnershipConflict ( a . owningCity , b . owningCity , t , out City winnerCity ) ) return ;
166+
167+ // Law II
168+ if ( t . baseTerrainType . Key == "ocean" && t . rankDistanceTo ( winnerCity . location ) > 2 ) {
169+ t . owningCity = null ;
170+ return ;
171+ }
172+ t . owningCity = winnerCity ;
173+ winnerCity . owner . tileKnowledge . AddTilesToKnown ( t ) ;
174+ }
175+
173176 public void UpdateTileOwnersOnCityDestruction ( City city ) {
174177 city . location . owningCity = null ;
175178
@@ -275,26 +278,27 @@ public void InvalidateCachedTradeNetwork() {
275278 }
276279
277280 // Rules taken from https://forums.civfanatics.com/threads/the-eight-laws-of-border-dynamics.106882/
278- private City ResolveTileOwnershipConflict ( City a , City b , Tile t ) {
279- if ( a . Equals ( b ) ) return a ;
281+ private bool ResolveTileOwnershipConflict ( City a , City b , Tile t , out City owner ) {
282+ owner = null ;
283+ if ( a . Equals ( b ) ) { owner = a ; return true ; }
280284
281285 int aRank = a . location . rankDistanceTo ( t ) ;
282286 int bRank = b . location . rankDistanceTo ( t ) ;
283287
284288 // Law I
285289 // Cities can claim tiles of rank n+1, where n is the city's expansion level
286- if ( a . GetBorderExpansionLevel ( ) + 1 < aRank && b . GetBorderExpansionLevel ( ) + 1 >= bRank ) return b ;
287- if ( b . GetBorderExpansionLevel ( ) + 1 < bRank && a . GetBorderExpansionLevel ( ) + 1 >= aRank ) return a ;
290+ if ( a . GetBorderExpansionLevel ( ) + 1 < aRank && b . GetBorderExpansionLevel ( ) + 1 >= bRank ) { owner = b ; return true ; }
291+ if ( b . GetBorderExpansionLevel ( ) + 1 < bRank && a . GetBorderExpansionLevel ( ) + 1 >= aRank ) { owner = a ; return true ; }
288292
289293 // Law III
290294 // The city with the lowest rank claim gets the tile.
291- if ( aRank > bRank ) return b ;
292- if ( aRank < bRank ) return a ;
295+ if ( aRank > bRank ) { owner = b ; return true ; }
296+ if ( aRank < bRank ) { owner = a ; return true ; }
293297
294298 // Law IV
295299 // If the ranks are equal, the city with more culture gets the tile.
296- if ( a . GetCulture ( ) + a . GetCulturePerTurn ( ) < b . GetCulture ( ) + b . GetCulturePerTurn ( ) ) return b ;
297- if ( a . GetCulture ( ) + a . GetCulturePerTurn ( ) > b . GetCulture ( ) + b . GetCulturePerTurn ( ) ) return a ;
300+ if ( a . GetCulture ( ) + a . GetCulturePerTurn ( ) < b . GetCulture ( ) + b . GetCulturePerTurn ( ) ) { owner = b ; return true ; }
301+ if ( a . GetCulture ( ) + a . GetCulturePerTurn ( ) > b . GetCulture ( ) + b . GetCulturePerTurn ( ) ) { owner = a ; return true ; }
298302
299303 // Law V
300304 // If the cultures are equal the oldest city gets the tile.
@@ -309,9 +313,9 @@ private City ResolveTileOwnershipConflict(City a, City b, Tile t) {
309313 for ( int r = aRank - 1 ; r <= aRank ; r ++ ) {
310314 if ( r <= 0 ) continue ;
311315 Tile winner = t . FindInRing ( r , tile => tile . HasCity && ( tile . cityAtTile == a || tile . cityAtTile == b ) , false ) ;
312- if ( winner != null ) {
313- return winner . owningCity ;
314- }
316+ if ( winner == null ) continue ;
317+ owner = winner . owningCity ;
318+ return true ;
315319 }
316320
317321 // should never happen, if it does some part of the algorithm has gone wrong
0 commit comments