context: using System;
  using System.Collections;
  using System.Collections.Generic;
  using Server.Commands;
  using Server.Mobiles;
  
  namespace Server
  {
  	public class VendorGenerator
  	{
  		public static void Initialize()
  		{
  			CommandSystem.Register( "VendorGen", AccessLevel.Administrator, new CommandEventHandler( VendorGenerator.VendorGen_OnCommand ) );
  		}
  
  		private static Rectangle2D[] m_BritRegions = new Rectangle2D[]
  			{
  				new Rectangle2D( new Point2D( 250, 750 ), new Point2D( 775, 1330 ) ),
  				new Rectangle2D( new Point2D( 525, 2095 ), new Point2D( 925, 2430 ) ),
  				new Rectangle2D( new Point2D( 1025, 2155 ), new Point2D( 1265, 2310 ) ),
  				new Rectangle2D( new Point2D( 1635, 2430 ), new Point2D( 1705, 2508 ) ),
  				new Rectangle2D( new Point2D( 1775, 2605 ), new Point2D( 2165, 2975 ) ),
  				new Rectangle2D( new Point2D( 1055, 3520 ), new Point2D( 1570, 4075 ) ),
  				new Rectangle2D( new Point2D( 2860, 3310 ), new Point2D( 3120, 3630 ) ),
  				new Rectangle2D( new Point2D( 2470, 1855 ), new Point2D( 3950, 3045 ) ),
  				new Rectangle2D( new Point2D( 3425, 990 ), new Point2D( 3900, 1455 ) ),
  				new Rectangle2D( new Point2D( 4175, 735 ), new Point2D( 4840, 1600 ) ),
  				new Rectangle2D( new Point2D( 2375, 330 ), new Point2D( 3100, 1045 ) ),
  				new Rectangle2D( new Point2D( 2100, 1090 ), new Point2D( 2310, 1450 ) ),
  				new Rectangle2D( new Point2D( 1495, 1400 ), new Point2D( 1550, 1475 ) ),
  				new Rectangle2D( new Point2D( 1085, 1520 ), new Point2D( 1415, 1910 ) ),
  				new Rectangle2D( new Point2D( 1410, 1500 ), new Point2D( 1745, 1795 ) ),
  				new Rectangle2D( new Point2D( 5120, 2300 ), new Point2D( 6143, 4095 ) )
  			};
  
  		private static Rectangle2D[] m_IlshRegions = new Rectangle2D[]
  			{
  				new Rectangle2D( new Point2D( 0, 0 ), new Point2D( 288*8, 200*8 ) )
  			};
  
  		[Usage( "VendorGen" )]
  		[Description( "Generates vendors based on display cases and floor plans. Analyzes the map files, slow." )]
  		private static void VendorGen_OnCommand( CommandEventArgs e )
  		{
  			Process( Map.Trammel, m_BritRegions );
  			Process( Map.Felucca, m_BritRegions );
  			Process( Map.Ilshenar, m_IlshRegions );
  		}
  
  		private static bool GetFloorZ( Map map, int x, int y, out int z )
  		{
  			LandTile lt = map.Tiles.GetLandTile( x, y );
  
  			if ( IsFloor( lt.ID ) && map.CanFit( x, y, lt.Z, 16, false, false ) )
  			{
  				z = lt.Z;
  				return true;
  			}
  
  			StaticTile[] tiles = map.Tiles.GetStaticTiles( x, y );
  
  			for ( int i = 0; i < tiles.Length; ++i )
  			{
  				StaticTile t = tiles[i];
  				ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
  
  				if ( IsStaticFloor( t.ID ) && map.CanFit( x, y, t.Z + (id.Surface ? id.CalcHeight : 0), 16, false, false ) )
  				{
  					z = t.Z + (id.Surface ? id.CalcHeight : 0);
  					return true;
  				}
  			}
  
  			z = 0;
  			return false;
  		}
  
  		private static bool IsFloor( Map map, int x, int y, bool canFit )
  		{
  			LandTile lt = map.Tiles.GetLandTile( x, y );
  
  			if ( IsFloor( lt.ID ) && (canFit||CanFit( map, x, y, lt.Z )) )
  				return true;
  
  			StaticTile[] tiles = map.Tiles.GetStaticTiles( x, y );
  
  			for ( int i = 0; i < tiles.Length; ++i )
  			{
  				StaticTile t = tiles[i];
  				ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
  
  				if ( IsStaticFloor( t.ID ) && (canFit||CanFit( map, x, y, t.Z + (id.Surface ? id.CalcHeight : 0) )) )
  					return true;
  			}
  
  			return false;
  		}
  
  		private static bool IsFloor( int itemID )
  		{
  			itemID &= TileData.MaxLandValue;
  
  			return ( itemID >= 0x406 && itemID <= 0x51A );
  		}
  
  		private static bool IsStaticFloor( int itemID )
  		{
  			return ( itemID >= 0x495 && itemID <= 0x514 )
  				|| ( itemID >= 0x519 && itemID <= 0x53A );
  		}
  
  		private static bool IsDisplayCase( int itemID )
  		{
  			return ( itemID >= 0xB00 && itemID <= 0xB02 )
  				|| ( itemID >= 0xB06 && itemID <= 0xB0A )
  				|| ( itemID >= 0xB0D && itemID <= 0xB17 );
  		}
  
  		private static void Process( Map map, Rectangle2D[] regions )
  		{
  			m_ShopTable = new Hashtable();
  			m_ShopList = new ArrayList();
  
  			World.Broadcast( 0x35, true, "Generating vendor spawns for {0}, please wait.", map );
  			
  			for ( int i = 0; i < regions.Length; ++i )
  				for ( int x = 0; x < map.Width; ++x )
  					for ( int y = 0; y < map.Height; ++y )
  						CheckPoint( map, regions[i].X + x, regions[i].Y + y );
  
  			for ( int i = 0; i < m_ShopList.Count; ++i )
  			{
  				ShopInfo si = (ShopInfo)m_ShopList[i];
  
  				int xTotal = 0;
  				int yTotal = 0;
  
  				bool hasSpawner = false;
  
  				for ( int j = 0; !hasSpawner && j < si.m_Floor.Count; ++j )
  				{
  					Point2D fp = (Point2D)si.m_Floor[j];
  
  					xTotal += fp.X;
  					yTotal += fp.Y;
  
  					IPooledEnumerable eable = map.GetItemsInRange( new Point3D( fp.X, fp.Y, 0 ), 0 );
  
  					foreach ( Item item in eable )
  					{
  						if ( item is Spawner )
  						{
  							hasSpawner = true;
  							break;
  						}
  					}
  
  					eable.Free();
  
  					if ( hasSpawner )
  						break;
  				}
  
  				if ( hasSpawner )
  					continue;
  
  				int xAvg = xTotal / si.m_Floor.Count;
  				int yAvg = yTotal / si.m_Floor.Count;
  
  				ArrayList names = new ArrayList();
  				ShopFlags flags = si.m_Flags;
  
  				if ( (flags & ShopFlags.Armor) != 0 )
  					names.Add( "armorer" );
  
  				if ( (flags & ShopFlags.MetalWeapon) != 0 )
  					names.Add( "weaponsmith" );
  
  				if ( (flags & ShopFlags.ArcheryWeapon) != 0 )
  					names.Add( "bowyer" );
  
  				if ( (flags & ShopFlags.Scroll) != 0 )
  					names.Add( "mage" );
  
  				if ( (flags & ShopFlags.Spellbook) != 0 )
  					names.Add( "mage" );
  
  				if ( (flags & ShopFlags.Bread) != 0 )
  					names.Add( "baker" );
  
  				if ( (flags & ShopFlags.Jewel) != 0 )
  					names.Add( "jeweler" );
  
  				if ( (flags & ShopFlags.Potion) != 0 )
  				{
  					names.Add( "herbalist" );
  					names.Add( "alchemist" );
  					names.Add( "mage" );
  				}
  
  				if ( (flags & ShopFlags.Reagent) != 0 )
  				{
  
gt: 					names.Add( "mage" );