@@ -147,6 +147,26 @@ public void UpdateTileOwners() {
147147 foreach ( Player player in players ) {
148148 player . tileKnowledge . RecomputeActiveTiles ( ) ;
149149 player . UpdateResourcesInBorders ( map . tiles . Where ( t => t . owningCity ? . owner == player ) ) ;
150+
151+ foreach ( Tile t in player . tileKnowledge . knownTiles . Where ( t => t . owningCity == null && t . GetEdgeNeighbors ( ) . Any ( e => e . owningCity != null ) ) . ToList ( ) ) {
152+ // 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+ }
161+ // 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+ }
169+ }
150170 }
151171 }
152172
@@ -256,26 +276,46 @@ public void InvalidateCachedTradeNetwork() {
256276
257277 // Rules taken from https://forums.civfanatics.com/threads/the-eight-laws-of-border-dynamics.106882/
258278 private City ResolveTileOwnershipConflict ( City a , City b , Tile t ) {
279+ if ( a . Equals ( b ) ) return a ;
280+
259281 int aRank = a . location . rankDistanceTo ( t ) ;
260282 int bRank = b . location . rankDistanceTo ( t ) ;
261283
284+ // Law I
285+ // 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 ;
288+
289+ // Law III
262290 // The city with the lowest rank claim gets the tile.
263- if ( aRank > bRank ) {
264- return b ;
265- } else if ( aRank < bRank ) {
266- return a ;
267- }
291+ if ( aRank > bRank ) return b ;
292+ if ( aRank < bRank ) return a ;
268293
294+ // Law IV
269295 // If the ranks are equal, the city with more culture gets the tile.
270- if ( a . GetCulture ( ) < b . GetCulture ( ) ) {
271- return b ;
272- } else if ( a . GetCulture ( ) > b . GetCulture ( ) ) {
273- return a ;
274- }
296+ if ( a . GetCulture ( ) + a . GetCulturePerTurn ( ) < b . GetCulture ( ) + b . GetCulturePerTurn ( ) ) return b ;
297+ if ( a . GetCulture ( ) + a . GetCulturePerTurn ( ) > b . GetCulture ( ) + b . GetCulturePerTurn ( ) ) return a ;
275298
299+ // Law V
276300 // If the cultures are equal the oldest city gets the tile.
277- // TODO: track city age - for now we just return the first.
278- return a ;
301+ // TODO: track city age - for now we are going to skip this.
302+ // return a;
303+
304+ // Law VI
305+ // Starting North of the disputed tile, we go counter-clockwise
306+ // trying to find the first tile that has one of the competing cities.
307+ // We start at (rank - 1) because the rank distance does not necessarily reflect the actual "ring"
308+ // the city tile is in, so a tile at rank 3, could well mean it's in the 2nd ring.
309+ for ( int r = aRank - 1 ; r <= aRank ; r ++ ) {
310+ if ( r <= 0 ) continue ;
311+ Tile winner = t . FindInRing ( r , tile => tile . HasCity && ( tile . cityAtTile == a || tile . cityAtTile == b ) , false ) ;
312+ if ( winner != null ) {
313+ return winner . owningCity ;
314+ }
315+ }
316+
317+ // should never happen, if it does some part of the algorithm has gone wrong
318+ throw new Exception ( $ "Failed to resolve ownership of { t } between { a . name } and { b . name } , something went wrong") ;
279319 }
280320 }
281321}
0 commit comments