public AdjacencyTable BuildAdjacencyTable( Rectangle region, ProvinceList provinces ) { const int Offset = 2; // 1 is too small, it seems... AdjacencyTable table = new AdjacencyTable(); // Build a matrix of provinces by walking over the map and marking each adjacency in the matrix. int[,] matrix = new int[Province.InternalCount,Province.InternalCount]; int[,] rivers = new int[Province.InternalCount,Province.InternalCount]; // Fix region if ( region.Right > Lightmap.BaseWidth ) region.Width = Lightmap.BaseWidth - region.X; if ( region.Bottom > Lightmap.BaseHeight ) region.Height = Lightmap.BaseHeight - region.Y; ushort[] histogram = null; // Enlarge region (only if it's not encompassing the whole map). // This is necessary to detect changed on the border of the region specified... if ( region.X != 0 || region.Y != 0 || region.Width < Lightmap.BaseWidth || region.Width < Lightmap.BaseHeight ) { // Need to enlarge the region so that it *completely* encompasses all provinces in the original region // First, Get a map of all the IDs in the original region histogram = GetHistogram( region ); // Get all ids in the region ushort[] ids = GetIDs( region, false ); ProvinceBoundBox[] boxes = CalculateBoundBoxes(); for ( int i=0; i<ids.Length; ++i ) { region = Rectangle.Union( region, boxes[ids[i]].Box ); } // Fix region, again. if ( region.Right > Lightmap.BaseWidth ) region.Width = Lightmap.BaseWidth - region.X; if ( region.Bottom > Lightmap.BaseHeight ) region.Height = Lightmap.BaseHeight - region.Y; } int id1, id2; int[] places = new int[] { Offset*2, 0, 0, -Offset*2, Offset*4, -Offset*2, Offset*2, -Offset*4, Offset*6, -Offset*4, Offset*4, -Offset*6, Offset*8, -Offset*6, Offset*6, -Offset*8 }; for ( int y=region.Top; y<region.Bottom; ++y ) { // Walk over zones on this row int zleft = lines[y].LookupZoneIndex( region.Left ); int zright = lines[y].LookupZoneIndex( region.Right ); for ( int z=zleft; z<=zright; ++z ) { // Skip if we're TI if ( lines[y].GetZone( z ).ID == Province.TerraIncognitaID ) continue; // Process this zone. int left = lines[y].GetZone( z ).X; int right = left + lines[y].GetZoneLength( z ); for ( int x=left; x<right; ++x ) { #region Left/Right check // -- Left/right check first id1 = this[x-Offset,y]; id2 = this[x+Offset,y]; if ( id1 != Province.TerraIncognitaID && id2 != Province.TerraIncognitaID ) { if ( provinces[id2].IsRiver() ) { // The right one is a river... ++matrix[id1,id2]; ++matrix[id2,id1]; // Look for land... for ( int i=0; i<places.Length; i+=2 ) { id2 = this[x+places[i],y+places[i+1]]; if ( provinces[id2].IsLand() ) { ++matrix[id1,id2]; ++matrix[id2,id1]; // Also mark river adjacency ++rivers[id1,id2]; ++rivers[id2,id1]; break; } } // If not found, don't mark a thing } else { ++matrix[id1,id2]; ++matrix[id2,id1]; } } #endregion #region Up/down check // -- Up/down check next id1 = this[x,y-Offset]; id2 = this[x,y+Offset]; if ( id1 != 0 && id2 != 0 ) { if ( provinces[id2].IsRiver() ) { // The bottom one is a river... ++matrix[id1,id2]; ++matrix[id2,id1]; // Look further down for land... for ( int i=0; i<places.Length; i+=2 ) { id2 = this[x+(-places[i+1]),y+places[i]]; if ( provinces[id2].IsLand() ) { ++matrix[id1,id2]; ++matrix[id2,id1]; // Also mark river adjacency ++rivers[id1,id2]; ++rivers[id2,id1]; break; } } // If not found, don't mark a thing } else { ++matrix[id1,id2]; ++matrix[id2,id1]; } } #endregion } } } // Walk over the matrix, and build an actual list of adjacencies for each province. const int Threshold = 8; // we need a certain amount of matches to have adjacency... // Start iterating at 1, no need to incorporate TI... for ( ushort ph=1; ph<Province.Count; ++ph ) { // Skip ids not present in the original region if ( histogram != null && histogram[ph] <= 0 ) continue; // Do "normal" adjacencies first for ( ushort pv=1; pv<Province.Count; ++pv ) { if ( ph == pv || provinces[pv].IsRiver() ) continue; // Check for the threshold if ( matrix[ph,pv] <= Threshold ) continue; table.Add( ph, new Adjacent( pv, rivers[ph,pv] == matrix[ph,pv] ? AdjacencyType.River : AdjacencyType.Normal ) ); } // Do "river" adjacencies next for ( ushort pv=1; pv<Province.Count; ++pv ) { if ( ph == pv || !provinces[pv].IsRiver() ) continue; // Check for the threshold if ( matrix[ph,pv] <= Threshold ) continue; table.Add( ph, new Adjacent( pv, AdjacencyType.Normal ) ); } } return table; }