private ConsoleArea CreateMapArea(Map map)
		{
			var area = new ConsoleArea(60+10, 30+3);
			area.SetBorderStyle(ConsoleArea.BorderStyle.Double);
			area.SetBorderBackground(ConsoleColor.Black);
			area.SetBorderForeground(ConsoleColor.White);
			area.SetTitle(map.Name);

			FillArea(map, area, map.AllPositions);

			return area;
		}
		private Map GetOrAddMap(string mapName)
		{
			var map = GetMap(mapName);

			if (map == null)
			{
				map = new Map(mapName);
				_currentMaps.Add(mapName, map);
			}

			return map;
		}
		private bool PlayerCanWalkHere(Character player, Map map, Position pos)
		{
			var friends = GetFriends(player);
			var enemyCharacters = GetEnemyCharacters(player);
			var monsters = GetMonsters(player);
			var boulders = player.VisibleItems.Where(item => GetInfoFor(item.Id).SubType == "boulder");

			var blockingItems = friends.Concat(boulders);

			if (!PlayerHasPvPMode(player.Id))
			{
				blockingItems = blockingItems.Concat(enemyCharacters);
			}

			if (!PlayerHasAttackMode(player.Id))
			{
				blockingItems = blockingItems.Concat(monsters);
			}

			var blockedPositions = blockingItems.Select(item => item.Position);

			return !blockedPositions.Any(x => x.Equals(pos)) && (PlayerIsGaseous(player.Id) || map.IsWalkable(pos));
		}
		private string GetMapAreaTitle(Character player, Map map)
		{
			var activeTile = map.GetPositionValue(player.Position);
			var item = player.VisibleItems.FirstOrDefault(i => i.XPos == player.XPos && i.YPos == player.YPos);

			if (item != null)
			{
				return string.Format("{0}/{1} ({2},{3})", map.Name, item.Name, player.XPos, player.YPos);
			}

			var roomId = (activeTile & (uint) TileFlags.ROOM_ID);

			if (roomId > 0)
			{
				return string.Format("{0}/{1} ({2},{3})", map.Name, roomId, player.XPos, player.YPos);
			}

			return string.Format("{0} ({1},{2})", map.Name, player.XPos, player.YPos);
		}
		private string GetDebugInfo(Character player, Map map)
		{
			var positionValue = (TileFlags)map.GetPositionValue(player.Position);
			var debug = string.Format("Current: {0}", positionValue);

			var flags = Enum.GetValues(typeof (TileFlags))
			                .Cast<TileFlags>()
			                .Where(flag => flag != TileFlags.NOTHING)
			                .ToList();

			var exactMatches = flags.Where(flag => (positionValue & flag) == flag).ToList();

			foreach (var flag in flags)
			{
				var tileFlags = positionValue & flag;

				if (tileFlags > 0 && tileFlags != flag)
				{
					debug += string.Format(" | {0}:{1}", flag, tileFlags);
				}
			}

			debug += string.Format(" ({0})", string.Join("|", exactMatches));

			var label = (uint) (positionValue & TileFlags.LABEL);
			if (label > 0)
			{
				debug += string.Format(" LBL:'{0}'", Console2.Encoding.GetString(BitConverter.GetBytes(label)));
			}

			return debug;
		}
		private Position SelectPosition(Map map, Position start, string title)
		{
			var mapArea = CreateMapArea(map);
			var messageArea = CreateMessageArea();
			mapArea.SetTitle(title);
			messageArea.SetTitle(title);

			var position = start;

			while (true)
			{
				var previousPosition = position;

				mapArea.Write("S", start.X, start.Y, ConsoleColor.Blue, ConsoleColor.DarkBlue);
				mapArea.Write("X", position.X, position.Y, ConsoleColor.Red, ConsoleColor.DarkRed);
				mapArea.CenterOffset(position.X, position.Y);

				messageArea.Clear();
				messageArea.Write(string.Format("Select position and press [ENTER] ([Escape] to abort)"), 1, 1);
				messageArea.Write(string.Format("Current position: {0}, {1}", position.X, position.Y), 1, 2);

				_console2.DrawArea(mapArea, 0, 0);
				_console2.DrawArea(messageArea, 0, mapArea.Height);

				switch (Console.ReadKey(true).Key)
				{
					case ConsoleKey.UpArrow:
						position = new Position(position.X, position.Y - 1);
						break;
					case ConsoleKey.DownArrow:
						position = new Position(position.X, position.Y + 1);
						break;
					case ConsoleKey.LeftArrow:
						position = new Position(position.X - 1, position.Y);
						break;
					case ConsoleKey.RightArrow:
						position = new Position(position.X + 1, position.Y);
						break;
					case ConsoleKey.Enter:
						return position;
					case ConsoleKey.Escape:
						return null;
				}

				FillArea(map, mapArea, new[] { previousPosition });
			}
		}
		private ConsoleArea UpdateMapArea(Map map, Character player, IEnumerable<Position> otherPositionsToRedraw)
		{
			if (!_maps.ContainsKey(map.Name))
			{
				_maps[map.Name] = CreateMapArea(map);
			}
			else
			{
				FillArea(map, _maps[map.Name], player.VisibleArea.Concat(otherPositionsToRedraw));
			}

			var mapArea = _maps[map.Name];

			var goalForPlayer = _context.GetGoalForPlayer(player.Id);
			if (goalForPlayer != null)
			{
				var tile = GetTile(map.GetPositionValue(goalForPlayer));
				mapArea.Write(tile.Character, goalForPlayer.X, goalForPlayer.Y, ConsoleColor.Green, ConsoleColor.DarkGreen);
			}

			player.VisibleItems.ToList().ForEach(item => DrawItem(item, mapArea));
			player.VisibleEntities.ToList().ForEach(item => DrawEntity(item, mapArea));

			DrawPlayer(player.Id, player.XPos, player.YPos, mapArea);

			mapArea.SetTitle(GetMapAreaTitle(player, map));
			mapArea.CenterOffset(player.XPos, player.YPos);

			return mapArea;
		}
		private void UpdateDebugArea(ConsoleArea debugArea, Character player, Map map)
		{
			debugArea.Clear();
			debugArea.Write(GetDebugInfo(player, map), 0, 0);
		}
		private void FillArea(Map map, ConsoleArea area, IEnumerable<Position> positions)
		{
			foreach (var position in positions)
			{
				var tile = GetTile(map.GetPositionValue(position));
				area.Write(tile.Character, position.X, position.Y, tile.ForeColor, tile.BackColor);
			}
		}