Inheritance: InventoryItem
        /// <summary>
        /// Generates a map based on the maplet assigned
        /// </summary>
        /// <param name="maplet">The maplet to generate</param>
        /// <param name="parentWallID">The wall that the parent has</param>
        /// <param name="parentTileID">The ID of the tiles used in the parent maplet item</param>
        /// <param name="enemyType">The type of actor which is dominant in this map</param>
        /// <param name="owner">The owner of the map. Any maplet items which don't belong will be hidden</param>
        /// <param name="actors">The actors which we have generated</param>
        /// <param name="actorType">The type of actors to generate</param>
        /// <returns></returns>
        public MapBlock[,] GenerateMap(int parentTileID, int? parentWallID, Maplet maplet, bool preferSides, string actorType, OwningFactions owner,
            out Actor[] actors, out MapletActorWanderArea[] wAreas, out MapletPatrolPoint[] patrolRoutes, out MapletFootpathNode[] footpathNodes)
        {
            List<Actor> actorList = new List<Actor>();
            List<MapletActorWanderArea> wanderAreas = new List<MapletActorWanderArea>();
            List<MapletPatrolPoint> patrolRouteList = new List<MapletPatrolPoint>();
            List<MapletFootpathNode> footpathNodeList = new List<MapletFootpathNode>();

            PlanningMapItemType[,] planningMap = new PlanningMapItemType[maplet.SizeX, maplet.SizeY];

            //Step 1: Plan how the map will look

            //Step 1a: Set all tiles to available, and set the frame to walls if there's a wall
            planningMap = this.CreateBlueprint(maplet);

            //Step 1b: Put in the tiles in the actual map, and the walls if they are present
            MapBlock[,] generatedMap = new MapBlock[maplet.SizeX, maplet.SizeY];
            ItemFactory.ItemFactory factory = new ItemFactory.ItemFactory();

            int tileID = 0;

            if (maplet.Tiled)
            {
                if (maplet.TileID.HasValue)
                {
                    tileID = maplet.TileID.Value;
                }
                else
                {
                    //Load the tileID from the factory
                    factory.CreateItem(Archetype.TILES, maplet.TileTag, out tileID);
                }

            }
            else
            {
                tileID = parentTileID;
            }

            //That's the tiles done
            for (int x = 0; x < generatedMap.GetLength(0); x++)
            {
                for (int y = 0; y < generatedMap.GetLength(1); y++)
                {
                    MapItem tile = factory.CreateItem("tile", tileID);
                    tile.Coordinate = new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL);

                    MapBlock block = new MapBlock();
                    block.Tile = tile;

                    generatedMap[x, y] = block;
                }
            }

            //Do the walls now if they are required
            int? wallID = null;
            int tempWallID = -1;

            if (parentWallID.HasValue)
            {
                MapItem wall = factory.CreateItem("MUNDANEITEMS", parentWallID.Value);
                wallID = parentWallID;
            }
            else
            {
                MapItem wall = factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "wall", out tempWallID);
                wallID = tempWallID;
            }

            if (maplet.Walled && wallID.HasValue)
            {
                //wall the edge tiles
                for (int x = 0; x < maplet.SizeX; x++)
                {
                    generatedMap[x, 0].PutItemOnBlock(factory.CreateItem("mundaneitems", wallID.Value));
                    generatedMap[x, maplet.SizeY - 1].PutItemOnBlock(factory.CreateItem("mundaneitems", wallID.Value));

                    if (maplet.WindowProbability.HasValue && maplet.WindowProbability.Value > 0)
                    {
                        if (random.Next(100) < maplet.WindowProbability.Value)
                        {
                            int itemID;
                            //Put a window :)
                            generatedMap[x, 0].ForcePutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "window", out itemID));
                        }
                        else if (random.Next(100) < maplet.WindowProbability.Value)
                        {
                            int itemID;
                            //Put a window :)
                            generatedMap[x, maplet.SizeY - 1].ForcePutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "window", out itemID));
                        }
                    }
                }

                for (int y = 0; y < maplet.SizeY; y++)
                {
                    generatedMap[0, y].PutItemOnBlock(factory.CreateItem("mundaneitems", wallID.Value));
                    generatedMap[maplet.SizeX - 1, y].PutItemOnBlock(factory.CreateItem("mundaneitems", wallID.Value));

                    if (maplet.WindowProbability.HasValue && maplet.WindowProbability.Value > 0)
                    {
                        if (random.Next(100) < maplet.WindowProbability.Value)
                        {
                            int itemID;
                            //Put a window :)
                            generatedMap[0, y].ForcePutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "window", out itemID));
                        }
                        else if (random.Next(100) < maplet.WindowProbability.Value)
                        {
                            int itemID;
                            //Put a window :)
                            generatedMap[maplet.SizeX - 1, y].ForcePutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "window", out itemID));
                        }
                    }
                }

            }

            //Step 1c: Determine where we'll put the maplets
            foreach (MapletContentsMaplet childMaplet in maplet.MapletContents.Where(mc => (mc is MapletContentsMaplet)).OrderByDescending(mc => mc.ProbabilityPercentage).ThenBy(mc => random.Next()))
            {
                //Calculate the probability of putting the item in, and how many items we're putting
                for (int i = 0; i < childMaplet.MaxAmount; i++)
                {
                    if (random.NextDouble() * 100 <= childMaplet.ProbabilityPercentage)
                    {
                        //Does it fit?
                        int x = -1;
                        int y = -1;
                        PlanningMapItemType[,] newMap;

                        //Convert the child maplet into a planning map
                        PlanningMapItemType[,] childMapletBlueprint = this.CreateBlueprint(childMaplet.Maplet);
                        //mark the areas covered by the blueprint as being held by that blueprint

                        if (childMaplet.Position == PositionAffinity.FIXED)
                        {
                            if (Fits(planningMap, childMapletBlueprint, childMaplet.x.Value, childMaplet.y.Value, out newMap))
                            {
                                //it fits, generate it - <3 Recursion
                                Actor[] childActors = null;

                                MapletActorWanderArea[] wanderA = null;
                                MapletPatrolPoint[] patrolPoints = null;
                                MapletFootpathNode[] fpNodes = null;

                                MapBlock[,] childMap = this.GenerateMap(tileID, wallID.Value, childMaplet.Maplet, childMaplet.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.SIDES, actorType, owner, out childActors, out wanderA, out patrolPoints, out fpNodes);

                                //Add the child actors
                                actorList.AddRange(childActors);

                                //Update any actors's locations should they have any
                                foreach (var actor in childActors)
                                {
                                    if (actor.MissionStack.Count() > 0)
                                    {
                                        var wander = actor.MissionStack.Peek() as WanderMission;

                                        if (wander != null)
                                        {
                                            wander.WanderPoint.X += childMaplet.x.Value;
                                            wander.WanderPoint.Y += childMaplet.y.Value;

                                            wander.WanderRectangle = new Rectangle(wander.WanderRectangle.X + childMaplet.x.Value, wander.WanderRectangle.Y + childMaplet.y.Value, wander.WanderRectangle.Width, wander.WanderRectangle.Height);
                                        }

                                    }
                                }

                                //Update any wander areas too
                                foreach (var area in wanderA)
                                {
                                    area.WanderRect = new Rectangle(area.WanderRect.X + childMaplet.x.Value, area.WanderRect.Y + childMaplet.y.Value, area.WanderRect.Width, area.WanderRect.Height);
                                    area.WanderPoint.X += childMaplet.x.Value;
                                    area.WanderPoint.Y += childMaplet.y.Value;
                                }

                                //and patrol points
                                foreach (var point in patrolPoints)
                                {
                                    point.Point.X += childMaplet.x.Value;
                                    point.Point.Y += childMaplet.y.Value;
                                }

                                foreach (var n in fpNodes)
                                {
                                    n.Point.X += childMaplet.x.Value;
                                    n.Point.Y += childMaplet.y.Value;
                                }

                                //And add them
                                wanderAreas.AddRange(wanderA);
                                patrolRouteList.AddRange(patrolPoints);
                                footpathNodeList.AddRange(fpNodes);

                                //Join the two maps together
                                generatedMap = this.JoinMaps(generatedMap, childMap, childMaplet.x.Value, childMaplet.y.Value);
                            }
                        }
                        else
                        {
                            if (Fits(planningMap, childMapletBlueprint, childMaplet.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.SIDES, childMaplet.FirstFit, childMaplet.Padding, out x, out y, out newMap))
                            {
                                //it fits, generate it - <3 Recursion
                                Actor[] childActors = null;
                                MapletActorWanderArea[] wanderA = null;
                                MapletPatrolPoint[] patrolPoints = null;
                                MapletFootpathNode[] fpNodes = null;

                                MapBlock[,] childMap = this.GenerateMap(tileID, wallID.Value, childMaplet.Maplet, childMaplet.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.SIDES, actorType, owner, out childActors, out wanderA, out patrolPoints, out fpNodes);

                                //Add the child actors
                                actorList.AddRange(childActors);

                                //Update any actors's locations should they have any
                                foreach (var actor in childActors)
                                {
                                    if (actor.MissionStack.Count() > 0)
                                    {
                                        var wander = actor.MissionStack.Peek() as WanderMission;

                                        if (wander != null)
                                        {
                                            wander.WanderPoint.X += x;
                                            wander.WanderPoint.Y += y;

                                            wander.WanderRectangle = new Rectangle(wander.WanderRectangle.X + x, wander.WanderRectangle.Y + y, wander.WanderRectangle.Width, wander.WanderRectangle.Height);
                                        }

                                    }
                                }

                                //Update any wander areas too
                                foreach (var area in wanderA)
                                {
                                    area.WanderRect = new Rectangle(area.WanderRect.X + x, area.WanderRect.Y + y, area.WanderRect.Width, area.WanderRect.Height);
                                    area.WanderPoint.X += x;
                                    area.WanderPoint.Y += y;
                                }

                                //and patrol routes
                                foreach (var point in patrolPoints)
                                {
                                    point.Point.X += x;
                                    point.Point.Y += y;
                                }

                                foreach (var n in fpNodes)
                                {
                                    n.Point.X += x;
                                    n.Point.Y += y;
                                }

                                //And add them
                                wanderAreas.AddRange(wanderA);
                                patrolRouteList.AddRange(patrolPoints);
                                footpathNodeList.AddRange(fpNodes);

                                //Join the two maps together
                                generatedMap = this.JoinMaps(generatedMap, childMap, x, y);
                            }
                        }
                    }
                }
            }

            //Step 2: Put the items into the map

            //Lets list places we can put it in
            List<MapBlock> candidateBlocks = new List<MapBlock>();

            for (int x = 0; x < planningMap.GetLength(0); x++)
            {
                for (int y = 0; y < planningMap.GetLength(1); y++)
                {
                    if (planningMap[x, y] == PlanningMapItemType.FREE)
                    {
                        candidateBlocks.Add(generatedMap[x, y]);
                    }

                }
            }
            List<MapBlock> edgeBlocks = new List<MapBlock>();

            //Lets also get the edge mapblocks - for those who prefer being on the edge
            for (int x = 0; x < planningMap.GetLength(0); x++)
            {
                if (!maplet.Walled)
                {
                    if (planningMap[x, 0] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[x, 0]);
                    }

                    if (planningMap[x, planningMap.GetLength(1) - 1] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[x, planningMap.GetLength(1) - 1]);
                    }
                }
                else
                {
                    if (planningMap[x, 1] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[x, 1]);
                    }

                    if (planningMap[x, planningMap.GetLength(1) - 2] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[x, planningMap.GetLength(1) - 2]);
                    }
                }

            }

            //Doing the y parts
            for (int y = 0; y < planningMap.GetLength(1); y++)
            {
                if (!maplet.Walled)
                {
                    if (planningMap[0, y] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[0, y]);
                    }

                    if (planningMap[planningMap.GetLength(0) - 1, y] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[planningMap.GetLength(0) - 1, y]);
                    }
                }
                else
                {
                    if (planningMap[1, y] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[1, y]);
                    }

                    if (planningMap[planningMap.GetLength(0) - 2, y] == PlanningMapItemType.FREE)
                    {
                        edgeBlocks.Add(generatedMap[planningMap.GetLength(0) - 2, y]);
                    }

                }

            }

            //go through the maplet contents

            //Get the smallest x and y coordinate in the candidate blocks so we can use it for fixed things

            int smallestX = -1;
            int smallestY = -1;

            try
            {
                smallestX = candidateBlocks.Select(b => b.Tile.Coordinate.X).Min();
                smallestY = candidateBlocks.Select(b => b.Tile.Coordinate.Y).Min();
            }
            catch
            {
                //No space :(

            }

            foreach (MapletContents contents in maplet.MapletContents.Where(mc => mc is MapletContentsItem || mc is MapletContentsItemTag || mc is MapletContentsItemSpecial).OrderByDescending(mc => mc.ProbabilityPercentage))
            {
                //We'll see if we even put this at all
                MapItem itemPlaced = null;

                for (int i = 0; i < contents.MaxAmount; i++)
                {
                    //lets see what the probability of putting it in is
                    if ((random.NextDouble() * 100) <= contents.ProbabilityPercentage)
                    {
                        //Put it in
                        if (contents is MapletContentsItem)
                        {
                            MapletContentsItem mapletContent = (MapletContentsItem)contents;
                            itemPlaced = factory.CreateItem(mapletContent.ItemCategory, mapletContent.ItemID);
                        }
                        else
                            if (contents is MapletContentsItemTag)
                            {
                                MapletContentsItemTag mapletContent = (MapletContentsItemTag)contents;
                                int tempInt;
                                itemPlaced = factory.CreateItem(mapletContent.Category, mapletContent.Tag, out tempInt);
                                //I CHANGED THIS
                                itemPlaced.OwnedBy = mapletContent.Factions;
                            }
                            else
                                if (contents is MapletContentsItemSpecial)
                                {
                                    //what type is it
                                    switch ((contents as MapletContentsItemSpecial).Type)
                                    {
                                        case "StairsUp":
                                            itemPlaced = new DungeonStairs(true); break;
                                        case "StairsDown":
                                            itemPlaced = new DungeonStairs(false); break;
                                        case "SummoningCircle":
                                            itemPlaced = new SummoningCircle(); break;
                                        case "TreasureChest":
                                            itemPlaced = new TreasureChest(); break;
                                        case "Altar":
                                            itemPlaced = new Altar(); break;
                                        case "WishingWell":
                                            itemPlaced = new WishingWell(); break;
                                        case "Potion":
                                            var potionType = (PotionType[]) Enum.GetValues(typeof(PotionType));
                                            var potion = potionType.GetRandom();
                                            itemPlaced = new Potion(potion);
                                            break;
                                        default:
                                            throw new NotImplementedException("No code for " + (contents as MapletContentsItemSpecial).Type + " can be found");
                                    }
                                }

                        if (candidateBlocks.Count != 0)
                        {
                            //Lets decide where to put it

                            if (contents.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.SIDES && edgeBlocks.Count != 0)
                            {
                                //pick a place at random and add it to the maplet
                                int position = random.Next(edgeBlocks.Count);

                                edgeBlocks[position].PutItemOnBlock(itemPlaced);

                                if (!contents.AllowItemsOnTop)
                                {
                                    //remove it from both
                                    candidateBlocks.Remove(edgeBlocks[position]);
                                    edgeBlocks.RemoveAt(position);
                                }
                            }

                            if (contents.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.MIDDLE && candidateBlocks.Except(edgeBlocks).Count() != 0)
                            {
                                //pick a place at random and add it to the maplet
                                int position = random.Next(candidateBlocks.Except(edgeBlocks).Count());

                                MapBlock block = candidateBlocks.Except(edgeBlocks).ToArray()[position];

                                block.PutItemOnBlock(itemPlaced);

                                if (!contents.AllowItemsOnTop)
                                {
                                    //remove it from both
                                    candidateBlocks.Remove(block);
                                    edgeBlocks.Remove(block);
                                }
                            }

                            if (contents.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.ANYWHERE)
                            {
                                //pick a place at random and add it to the maplet
                                int position = random.Next(candidateBlocks.Count);

                                candidateBlocks[position].PutItemOnBlock(itemPlaced);

                                if (!contents.AllowItemsOnTop)
                                {
                                    //remove it from both
                                    edgeBlocks.Remove(candidateBlocks[position]);
                                    candidateBlocks.RemoveAt(position);
                                }
                            }

                            if (contents.Position == DRObjects.LocalMapGeneratorObjects.Enums.PositionAffinity.FIXED)
                            {
                                //Fix it in a particular position.
                                MapCoordinate coordinate = new MapCoordinate(smallestX + contents.x.Value, smallestY + contents.y.Value, 0, DRObjects.Enums.MapType.LOCAL);

                                var selectedBlock = candidateBlocks.Where(cb => cb.Tile.Coordinate.Equals(coordinate)).FirstOrDefault();

                                if (selectedBlock != null)
                                { //maybe someone put something there already
                                    selectedBlock.PutItemOnBlock(itemPlaced);
                                }

                                if (!contents.AllowItemsOnTop)
                                {
                                    //and remoev it from both
                                    candidateBlocks.Remove(selectedBlock);
                                    edgeBlocks.Remove(selectedBlock);
                                }
                            }
                        }
                    }
                }

            }

            //Step 3: Stripe through the map except for the current maplet's walls - work out where the walls are, and for each wall segment, put a door in
            #region Wall Segments
            List<Line> wallSegments = new List<Line>();

            for (int x = 1; x < planningMap.GetLength(0) - 1; x++)
            {
                //lets see if we find a wall Segment
                Line wallSegment = null;

                for (int y = 1; y < planningMap.GetLength(1) - 1; y++)
                {
                    if (planningMap[x, y] == PlanningMapItemType.WALL)
                    {
                        //Three possibilities exist. Either this is the start of a wall segment
                        //Or this is a continuation of a wall segment
                        //Or this is the end of a wall segment
                        // -> Because there is an intersection
                        // -> Because there was an active wall segment and there is no wall in this one
                        if (wallSegment == null)
                        {
                            //Its a start
                            wallSegment = new Line(new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), null);
                        }
                        else
                        {
                            //Continuation or end
                            //Check if there's an interesection
                            //Go up one and down one. If there is the maplet's walls there won't be a door - but then there'll be a double wall anyway which makes no sense
                            if (planningMap[x + 1, y] == PlanningMapItemType.WALL || planningMap[x - 1, y] == PlanningMapItemType.WALL)
                            {
                                //terminate the wall - and start a new one
                                wallSegment.End = new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL);
                                wallSegments.Add(wallSegment);

                                wallSegment = new Line(new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), null);
                            }
                            else
                            {
                                //do nothing, its a continuation
                            }
                        }

                    }
                    else
                    {
                        //Mayhaps a line has stopped?
                        if (wallSegment != null)
                        {
                            //It has - lets terminate it
                            wallSegment.End = new MapCoordinate(x, y - 1, 0, DRObjects.Enums.MapType.LOCAL);
                            wallSegments.Add(wallSegment);

                            wallSegment = null;
                        }

                    }

                }

                //Check if there's an active line - maybe it reaches till the end of the maplet
                if (wallSegment != null)
                {
                    wallSegment.End = new MapCoordinate(x, (planningMap.GetLength(1) - 1), 0, DRObjects.Enums.MapType.LOCAL);
                    wallSegments.Add(wallSegment);
                    wallSegment = null;
                }
            }

            //Now stripe in the other direction
            for (int y = 1; y < planningMap.GetLength(1) - 1; y++)
            {
                //lets see if we find a wall Segment
                Line wallSegment = null;

                for (int x = 1; x < planningMap.GetLength(0) - 1; x++)
                {
                    if (planningMap[x, y] == PlanningMapItemType.WALL)
                    {
                        //Three possibilities exist. Either this is the start of a wall segment
                        //Or this is a continuation of a wall segment
                        //Or this is the end of a wall segment
                        // -> Because there is an intersection
                        // -> Because there was an active wall segment and there is no wall in this one
                        if (wallSegment == null)
                        {
                            //Its a start
                            wallSegment = new Line(new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), null);
                        }
                        else
                        {
                            //Continuation or end
                            //Check if there's an interesection
                            //Go up one and down one. If there is the maplet's walls there won't be a door - but then there'll be a double wall anyway which makes no sense
                            if (planningMap[x, y + 1] == PlanningMapItemType.WALL || planningMap[x, y - 1] == PlanningMapItemType.WALL)
                            {
                                //terminate the wall - and start a new one
                                wallSegment.End = new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL);
                                wallSegments.Add(wallSegment);

                                wallSegment = new Line(new MapCoordinate(x, y, 0, DRObjects.Enums.MapType.LOCAL), null);
                            }
                            else
                            {
                                //do nothing, its a continuation
                            }
                        }

                    }
                    else
                    {
                        //Mayhaps a line has stopped?
                        if (wallSegment != null)
                        {
                            //It has - lets terminate it
                            wallSegment.End = new MapCoordinate(x - 1, y, 0, DRObjects.Enums.MapType.LOCAL);
                            wallSegments.Add(wallSegment);

                            wallSegment = null;
                        }

                    }

                }

                //Check if there's an active line - maybe it reaches till the end of the maplet
                if (wallSegment != null)
                {
                    wallSegment.End = new MapCoordinate(planningMap.GetLength(0) - 1, y, 0, DRObjects.Enums.MapType.LOCAL);
                    wallSegments.Add(wallSegment);
                    wallSegment = null;
                }
            }

            #endregion Wall Segments

            #region Doors

            //Get all wall segments larger than 0, and we can put a door there

            foreach (Line segment in wallSegments.Where(ws => ws.Length() > 1))
            {
                //Put a door somewhere, as long as its not the start or end
                //Oh and remove the wall

                MapBlock block = null;

                if (segment.Start.X == segment.End.X)
                {
                    //Get the entirety of the segment
                    List<int> possibleYs = new List<int>();

                    int smallerY = Math.Min(segment.Start.Y, segment.End.Y);
                    int largerY = Math.Max(segment.Start.Y, segment.End.Y);

                    //Check in the real map whether the tile next to it is free for walking in
                    for (int y = smallerY + 1; y <= largerY; y++)
                    {
                        if (generatedMap[segment.Start.X - 1, y].MayContainItems && generatedMap[segment.Start.X + 1, y].MayContainItems)
                        {
                            possibleYs.Add(y);
                        }
                    }

                    //Now check whether there's a possible y, and pick a random one from it
                    if (possibleYs.Count != 0)
                    {
                        block = generatedMap[segment.Start.X, possibleYs[random.Next(possibleYs.Count - 1)]];
                    }
                    else
                    {
                        //nothing to do - take smallest
                        block = generatedMap[segment.Start.X, segment.Start.Y + 1];
                    }
                }
                else
                {
                    List<int> possibleXs = new List<int>();

                    int smallerX = Math.Min(segment.Start.X, segment.End.X);
                    int largerX = Math.Max(segment.Start.X, segment.End.X);

                    //Check in the real map whether the tile next to it is free for walking in
                    for (int x = smallerX + 1; x <= largerX; x++)
                    {
                        if (generatedMap[x, segment.Start.Y - 1].MayContainItems && generatedMap[x, segment.Start.Y + 1].MayContainItems)
                        {
                            possibleXs.Add(x);
                        }
                    }

                    //Now check whether there's a possible x, and pick a random one from it
                    if (possibleXs.Count != 0)
                    {
                        block = generatedMap[possibleXs[random.Next(possibleXs.Count - 1)], segment.Start.Y];
                    }
                    else
                    {
                        //nothing to do - take the smallest one
                        block = generatedMap[segment.Start.X + 1, segment.Start.Y];
                    }

                }

                try
                {
                    if (block != null)
                    {
                        block.RemoveTopItem();
                        int doorID = -1;
                        block.PutItemOnBlock(factory.CreateItem(DRObjects.Enums.Archetype.MUNDANEITEMS, "door", out doorID));
                    }
                }
                catch { }
            }

            #endregion

            #region Enemies

            //Now lets create enemies :)
            foreach (var mc in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletActor))).OrderByDescending(o => o.ProbabilityPercentage))
            {
                var actor = mc as MapletActor;

                for (int i = 0; i < actor.MaxAmount; i++)
                {
                    //Check the random
                    if (random.Next(100) < actor.ProbabilityPercentage)
                    {
                        int actorID = 0;

                        string enemyType = actor.UseLocalType ? actorType : actor.EnemyType;

                        //For now set gear cost to 0
                        Actor newActor = ActorGeneration.CreateActor(enemyType, actor.EnemyTag, null, 10, 0, null, out actorID);

                        if (actor.VendorType.HasValue)
                        {
                            GenerateVendor(newActor, actor);
                        }

                        //Generate the map character
                        var mapCharacter = factory.CreateItem("enemies", actorID);

                        newActor.MapCharacter = mapCharacter;

                        if (!actor.Factions.HasFlag(owner))
                        {
                            //inactive character
                            newActor.MapCharacter.IsActive = false;
                        }

                        (mapCharacter as LocalCharacter).Actor = newActor;

                        //Lets position them randomly
                        for (int attempt = 0; attempt < 150; attempt++)
                        {
                            //Try 150 times
                            int x = random.Next(maplet.SizeX);
                            int y = random.Next(maplet.SizeY);

                            if (generatedMap[x, y].MayContainItems)
                            {
                                //Put it there
                                mapCharacter.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL);
                                generatedMap[x, y].ForcePutItemOnBlock(mapCharacter);
                                actorList.Add(newActor);

                                //What mission does he have?
                                if (actor.EnemyMission == ActorMissionType.WANDER)
                                {
                                    newActor.MissionStack.Push(new WanderMission()
                                        {
                                            LoiterPercentage = 80,
                                            WanderPoint = new MapCoordinate(mapCharacter.Coordinate),
                                            WanderRectangle = new Rectangle(0, 0, generatedMap.GetLength(0), generatedMap.GetLength(1))
                                        });
                                }

                                break;
                            }
                        }
                    }
                }
            }

            #endregion

            #region Wander Areas

            foreach (var mc in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletActorWanderArea))))
            {
                var wander = mc as MapletActorWanderArea;

                //The area of this is going to be the entire maplet (so if we're in a submaplet, they'll wander in there - Awesome no ?)
                wander.WanderRect = new Rectangle(0, 0, generatedMap.GetLength(0), generatedMap.GetLength(1));

                //Pick the wander point to be the middle of the rectangle. If the point isn't valid we might have a problem
                wander.WanderPoint = new MapCoordinate(generatedMap.GetLength(0) / 2, generatedMap.GetLength(1) / 2, 0, MapType.LOCAL);

                MapletActorWanderArea clone = new MapletActorWanderArea();
                clone.WanderPoint = new MapCoordinate(wander.WanderPoint);
                clone.WanderRect = new Rectangle(wander.WanderRect.X, wander.WanderRect.Y, wander.WanderRect.Width, wander.WanderRect.Height);
                clone.Profession = wander.Profession;
                clone.OwnerFactions = wander.OwnerFactions;

                wanderAreas.Add(clone);
            }

            wAreas = wanderAreas.ToArray();

            #endregion

            #region Patrol Points & Paths

            foreach (var mc in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletPatrolPoint))))
            {
                var point = mc as MapletPatrolPoint;

                //The point is going to be in the middle of the entire maplet
                point.Point = new MapCoordinate(generatedMap.GetLength(0) / 2, generatedMap.GetLength(1) / 2, 0, MapType.LOCAL);

                MapletPatrolPoint clone = new MapletPatrolPoint();
                clone.Point = new MapCoordinate(point.Point);
                clone.OwnerFactions = point.OwnerFactions;
                clone.Profession = point.Profession;
                clone.PointRadius = point.PointRadius;

                patrolRouteList.Add(clone);
            }

            patrolRoutes = patrolRouteList.ToArray();

            foreach (var n in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletFootpathNode))))
            {
                var node = n as MapletFootpathNode;

                //Point is going to be in the middle of the entire maplet
                node.Point = new MapCoordinate(generatedMap.GetLength(0) / 2, generatedMap.GetLength(1) / 2, 0, MapType.LOCAL);

                //Better create a new one
                MapletFootpathNode clone = new MapletFootpathNode();
                clone.Point = new MapCoordinate(node.Point);
                clone.IsPrimary = node.IsPrimary;

                footpathNodeList.Add(clone);
            }

            footpathNodes = footpathNodeList.ToArray();

            #endregion

            #region Aniamls

            //Now lets create enemies :)
            foreach (var mc in maplet.MapletContents.Where(mc => mc.GetType().Equals(typeof(MapletHerd))).OrderByDescending(o => o.ProbabilityPercentage))
            {
                var herd = mc as MapletHerd;

                for (int i = 0; i < herd.MaxAmount; i++)
                {
                    //Check the random
                    if (random.Next(100) < herd.ProbabilityPercentage)
                    {
                        var herds = ActorGeneration.CreateAnimalHerds(herd.Biome, herd.Domesticated, herd.HerdTag, 1);

                        foreach (var animalHerd in herds)
                        {
                            foreach (var animal in animalHerd)
                            {
                                //Position them on the map
                                for (int attempt = 0; attempt < 150; attempt++)
                                {
                                    //Try 150 times
                                    int x = random.Next(maplet.SizeX);
                                    int y = random.Next(maplet.SizeY);

                                    if (generatedMap[x, y].MayContainItems)
                                    {
                                        //Put it there
                                        animal.MapCharacter.Coordinate = new MapCoordinate(x, y, 0, MapType.LOCAL);
                                        generatedMap[x, y].ForcePutItemOnBlock(animal.MapCharacter);
                                        actorList.Add(animal);

                                        //Wander around does he have?
                                        animal.MissionStack.Push(new WanderMission()
                                        {
                                            LoiterPercentage = 80,
                                            WanderPoint = new MapCoordinate(animal.MapCharacter.Coordinate),
                                            WanderRectangle = new Rectangle(0, 0, generatedMap.GetLength(0), generatedMap.GetLength(1))
                                        });

                                        break;
                                    }
                                }
                            }
                        }

                    }
                }
            }

            #endregion

            actors = actorList.ToArray();

            #region Ownership

            //Go through all map items - If they're not valid for this particular owner, make them inactive.
            foreach (var mapBlock in generatedMap)
            {
                foreach (var item in mapBlock.GetItems())
                {
                    if (!item.OwnedBy.HasFlag(owner))
                    {
                        item.IsActive = false;
                    }
                }
            }

            #endregion

            //we're done
            return generatedMap;
        }
        public override void Initialize()
        {
            base.Initialize();
            if (parameters.Length == 0)
            {
                TestFunctions.PrepareFileTestMap();
            }
            else if (parameters[0].ToString().Equals("Village"))
            {
                //TestFunctions.ParseXML();
                TestFunctions.GenerateSettlement();

                InventoryItemManager mgr = new InventoryItemManager();

                for (int i = 0; i < 500; i++)
                {
                    var block = GameState.LocalMap.GetBlockAtCoordinate(new MapCoordinate(GameState.Random.Next(GameState.LocalMap.localGameMap.GetLength(0)), GameState.Random.Next(GameState.LocalMap.localGameMap.GetLength(1)), 0, MapType.LOCAL));

                    if (block.MayContainItems)
                    {
                        var item = mgr.CreateItem(DatabaseHandling.GetItemIdFromTag(Archetype.INVENTORYITEMS, "loot")) as InventoryItem;
                        item.Coordinate = new MapCoordinate(block.Tile.Coordinate);
                        block.ForcePutItemOnBlock(item);
                    }
                }

                //Create the new character stuff
                MultiDecisionComponent mdc = new MultiDecisionComponent(PlayableWidth / 2 - 250, 150, CharacterCreation.GenerateCharacterCreation());
                mdc.Visible = true;

                interfaceComponents.Add(mdc);

                GameState.LocalMap.IsGlobalMap = false;

            }
            else if (parameters[0].ToString().Equals("Continue"))
            {
                GameState.LoadGame();
            }
            else if (parameters[0].ToString().Equals("WorldMap"))
            {
                //Load from the world map
                var worldMap = GameState.GlobalMap.globalGameMap;

                List<MapBlock> collapsedMap = new List<MapBlock>();

                foreach (var block in worldMap)
                {
                    collapsedMap.Add(block);
                }

                GameState.LocalMap = new LocalMap(GameState.GlobalMap.globalGameMap.GetLength(0), GameState.GlobalMap.globalGameMap.GetLength(1), 1, 0);

                //Go through each of them, add them to the local map
                GameState.LocalMap.AddToLocalMap(collapsedMap.ToArray());

                //Let's start the player off at the first capital
                var coordinate = GameState.GlobalMap.WorldSettlements.Where(w => w.IsCapital).Select(w => w.Coordinate).FirstOrDefault();

                //Create the player character. For now randomly. Later we'll start at a capital
                MapItem player = new MapItem();
                player.Coordinate = new MapCoordinate(coordinate);
                player.Description = "The player character";
                player.Graphic = SpriteManager.GetSprite(LocalSpriteName.PLAYERCHAR_MALE);
                player.InternalName = "Player Char";
                player.MayContainItems = false;
                player.Name = "Player";

                MapBlock playerBlock = GameState.LocalMap.GetBlockAtCoordinate(player.Coordinate);
                playerBlock.PutItemOnBlock(player);

                GameState.PlayerCharacter = new Actor();
                GameState.PlayerCharacter.MapCharacter = player;
                GameState.PlayerCharacter.IsPlayerCharacter = true;

                GameState.PlayerCharacter.Attributes = ActorGeneration.GenerateAttributes("human", DRObjects.ActorHandling.CharacterSheet.Enums.ActorProfession.WARRIOR, 10, GameState.PlayerCharacter);
                GameState.PlayerCharacter.Anatomy = ActorGeneration.GenerateAnatomy("human");

                GameState.PlayerCharacter.Attributes.Health = GameState.PlayerCharacter.Anatomy;

                GameState.PlayerCharacter.Inventory.EquippedItems = ActorGeneration.GenerateEquippedItems(250); //give him 250 worth of stuff

                foreach (var item in GameState.PlayerCharacter.Inventory.EquippedItems.Values)
                {
                    GameState.PlayerCharacter.Inventory.Inventory.Add(item.Category, item);
                }

                GameState.LocalMap.Actors.Add(GameState.PlayerCharacter);

                //What attributes do we want?
                MultiDecisionComponent mdc = new MultiDecisionComponent(PlayableWidth / 2 - 250, 150, CharacterCreation.GenerateCharacterCreation());
                mdc.Visible = true;

                interfaceComponents.Add(mdc);

                GameState.LocalMap.IsGlobalMap = true;

            }
            else if (parameters[0].ToString().Equals("Camp"))
            {

                TestFunctions.ParseXML();
            }
            else
            {
                TestFunctions.GenerateDungeon();

                //Give him random stats so he won't completly suck
                CharacterCreation.ProcessParameters(CharacterCreation.GenerateRandom());

                //Also give him a bow of some sort
                InventoryItemManager iim = new InventoryItemManager();

                InventoryItem item = iim.GetBestCanAfford("WEAPON", 500);

                GameState.PlayerCharacter.SpecialAttacks[0] = SpecialAttacksGenerator.GenerateSpecialAttack(1);
                GameState.PlayerCharacter.SpecialAttacks[1] = SpecialAttacksGenerator.GenerateSpecialAttack(2);
                GameState.PlayerCharacter.SpecialAttacks[2] = SpecialAttacksGenerator.GenerateSpecialAttack(3);

                GameState.PlayerCharacter.SpecialAttacks[1].TimeOutLeft = 5;

              //  GameState.PlayerCharacter.SpecialAttacks[3] = SpecialAttacksGenerator.GenerateSpecialAttack(4);
               // GameState.PlayerCharacter.SpecialAttacks[4] = SpecialAttacksGenerator.GenerateSpecialAttack(5);

                item.InInventory = true;

                //Give them a bunch of potions at random
                for (int i = 0; i < 5; i++ )
                {
                    var potionType = (PotionType[])Enum.GetValues(typeof(PotionType));
                    var potion = potionType.GetRandom();
                    var p = new Potion(potion);

                    p.InInventory = true;

                    GameState.PlayerCharacter.Inventory.Inventory.Add(p.Category, p);
                }

                GameState.PlayerCharacter.Inventory.Inventory.Add(item.Category, item);

            }

            //Add the health control
            HealthDisplayComponent hdc = new HealthDisplayComponent(50, 50, GameState.LocalMap.Actors.Where(a => a.IsPlayerCharacter).FirstOrDefault());
            hdc.Visible = false;
            interfaceComponents.Add(hdc);

            CharacterSheetComponent csc = new CharacterSheetComponent(50, 50, GameState.LocalMap.Actors.Where(a => a.IsPlayerCharacter).FirstOrDefault());
            csc.Visible = false;
            interfaceComponents.Add(csc);

            InventoryDisplayComponent ivt = new InventoryDisplayComponent(50, 50, GameState.LocalMap.Actors.Where(a => a.IsPlayerCharacter).FirstOrDefault());
            ivt.Visible = false;
            interfaceComponents.Add(ivt);

            TextLogComponent tlc = new TextLogComponent(10, GraphicsDevice.Viewport.Height - 50, GameState.NewLog);
            tlc.Visible = true;
            interfaceComponents.Add(tlc);

            log = tlc;

            AdventureDisplayComponent tdc = new AdventureDisplayComponent(GraphicsDevice.Viewport.Width / 2 - 100, 0);
            interfaceComponents.Add(tdc);

            var cemetry = SpriteManager.GetSprite(InterfaceSpriteName.DEAD);

            //Create the menu buttons
            menuButtons.Add(new AutoSizeGameButton("  Health  ", this.game.Content, InternalActionEnum.OPEN_HEALTH, new object[] { }, 50, GraphicsDevice.Viewport.Height - 35));
            menuButtons.Add(new AutoSizeGameButton(" Attributes ", this.game.Content, InternalActionEnum.OPEN_ATTRIBUTES, new object[] { }, 150, GraphicsDevice.Viewport.Height - 35));

            if (GameState.LocalMap.Location as Settlement != null)
            {
                menuButtons.Add(new AutoSizeGameButton(" Settlement ", this.game.Content, InternalActionEnum.TOGGLE_SETTLEMENT, new object[] { }, 270, GraphicsDevice.Viewport.Height - 35));
                LocationDetailsComponent ldc = new LocationDetailsComponent(GameState.LocalMap.Location as Settlement, PlayableWidth - 170, 0);
                ldc.Visible = true;
                interfaceComponents.Add(ldc);
            }

            menuButtons.Add(new AutoSizeGameButton(" Inventory ", this.game.Content, InternalActionEnum.OPEN_INVENTORY, new object[] { }, 350, GraphicsDevice.Viewport.Height - 35));

            //Invoke a size change
            Window_ClientSizeChanged(null, null);
        }