private ConsoleArea CreatePlayerArea(Character player)
		{
			var area = new ConsoleArea(40+10, 30+3);
			area.SetBorderStyle(ConsoleArea.BorderStyle.Single);
			area.SetBorderBackground(ConsoleColor.DarkRed);
			area.SetBorderForeground(ConsoleColor.Red);
			area.SetDefaultBackground(ConsoleColor.Black);
			area.SetDefaultForeground(ConsoleColor.Green);
			area.SetTitle(player.Name);

			var row = 0;

			area.Write(string.Format("STR: {0}", player.Strength), 1, ++row);
			area.Write(string.Format("DEX: {0}", player.Dexterity), 1, ++row);
			area.Write(string.Format("CON: {0}", player.Constitution), 1, ++row);
			area.Write(string.Format("INT: {0}", player.Intelligence), 1, ++row);
			area.Write(string.Format("WIS: {0}", player.Wisdom), 1, ++row);

			row++;
			area.Write(string.Format("XP: {0}", player.Experience), 1, ++row);
			area.Write(string.Format("Lvl: {0}", player.Level), 1, ++row);


			var hpCol = ConsoleColor.Green;
			if (player.HitPoints < player.MaxHitPoints)
			{
				hpCol = player.HitPoints < player.MaxHitPoints / 2 ? ConsoleColor.Red : ConsoleColor.Yellow;
			}

			row++;
			area.Write(string.Format("HP: {0}/{1}", player.HitPoints, player.MaxHitPoints), 1, ++row, hpCol);
			area.Write(string.Format("AC: {0}", player.ArmorClass), 1, ++row);
			area.Write("Weapon: " + player.WieldedWeaponName, 1, ++row);
			area.Write("Armor: " + player.EquippedArmorName, 1, ++row);
			area.Write("Light: " + player.Light, 1, ++row);
			area.Write("Speed: " + player.Speed, 1, ++row);
			area.Write("Avail. pts: " + player.PointsToAllocate, 1, ++row);

			row++;
			area.Write("Inventory", 1, ++row);
			area.Write("=========", 1, ++row);

			for (int i = 0; i < player.Inventory.Length; i++)
			{
				area.Write(string.Format("{0}: {1}", i, _context.GetInfoFor(player.Inventory[i]).Name), 1, ++row);
			}

			area.SetOffset(0, 0);

			return area;
		}
		private void Update(Character uc)
		{
			ArmorClass = uc.ArmorClass;
			_hitPoints = uc._hitPoints;

			Strength = uc.Strength;
			Dexterity = uc.Dexterity;
			Constitution = uc.Constitution;
			Intelligence = uc.Intelligence;
			Wisdom = uc.Wisdom;

			Experience = uc.Experience;
			Level = uc.Level;

			Light = uc.Light;
			Speed = uc.Speed;

			EquippedArmorId = uc.EquippedArmorId;
			EquippedArmorName = uc.EquippedArmorName;
			WieldedWeaponId = uc.WieldedWeaponId;
			WieldedWeaponName = uc.WieldedWeaponName;

			PointsToAllocate = uc.PointsToAllocate;
		}
		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 IEnumerable<Item> GetMonsters(Character player)
		{
			return player.VisibleEntities.Where(x => x.Type == "monster");
		} 
		private IEnumerable<Item> GetFriends(Character player)
		{
			return player.VisibleEntities.Where(x => x.Type == "character" && IsFriendly(x.Id) && x.Id != player.Id);
		} 
		private IEnumerable<Item> GetEnemyCharacters(Character player)
		{
			return player.VisibleEntities.Where(x => x.Type == "character" && !IsFriendly(x.Id));
		}
		private bool GaseousPlayerCanWalkHere(Character player, Position pos)
		{
			var entities = player.VisibleEntities.Where(item => item.Id != player.Id);
			var boulders = player.VisibleItems.Where(item => GetInfoFor(item.Id).SubType == "boulder");
			var blocked = entities.Concat(boulders).Select(item => new Position(item.XPos, item.YPos));
			return !blocked.Any(x => x.Equals(pos));
		}
		private string SelectFromAttributes(Character player)
		{
			var attributes = new[]
			{
				new {Attribute = "STR", Value = player.Strength},
				new {Attribute = "DEX", Value = player.Dexterity},
				new {Attribute = "CON", Value = player.Constitution},
				new {Attribute = "INT", Value = player.Intelligence},
				new {Attribute = "WIS", Value = player.Wisdom}
			};

			var formattedList = attributes.Select((x, i) => string.Format("{0}: {1} ({2})", i, x.Attribute, x.Value));

			var selectedKey = CreateMessagePopup("Increase which attribute?", formattedList.ToArray());
			int choice;

			if (int.TryParse(selectedKey.KeyChar.ToString(), out choice))
			{
				if (choice >= 0 && choice < attributes.Count())
				{
					return attributes.ElementAt(choice).Attribute;
				}
			}

			return null;
		}
		private string SelectFromInventory(string action, Character player)
		{
			var inventory = player.Inventory.Select(x => _context.GetInfoFor(x)).ToList();

			if (!inventory.Any())
			{
				CreateMessagePopup("Sorry can't " + action, new[] { "You don't carry anything." });
				return null;
			}

			var formattedList = inventory.Select((x, i) => string.Format("{0}: {1}", i, x.Name));
			var selectedKey = CreateMessagePopup(action + " which item?", formattedList.ToArray());
			int choice;

			if (int.TryParse(selectedKey.KeyChar.ToString(), out choice))
			{
				if (choice >= 0 && choice < inventory.Count())
				{
					return inventory.ElementAt(choice).Id;
				}
			}

			return null;
		}
		private void IncreaseAttribute(Character player)
		{
			var attr = SelectFromAttributes(player);
			if (attr == null) return;
			_context.IncreaseAttribute(player.Id, (Attribute) Enum.Parse(typeof (Attribute), attr, true));
		}
		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 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 static IEnumerable<Position> GetAllVisibleItemPositions(Character player)
		{
			return player.VisibleItems.Concat(player.VisibleEntities)
			             .Select(x => new Position(x.XPos, x.YPos));
		}
		private void HandleKeyPress(ConsoleKeyInfo key, Character player)
		{
			switch (key.Key)
			{
				case ConsoleKey.Spacebar:
					break;
				case ConsoleKey.X:
					_context.Move(player.Id, _context.GetNextDirectionForPlayer(player.Id));
					break;
				case ConsoleKey.Y:
					_context.Scout(player.Id);
					break;
				case ConsoleKey.P:
					_context.PickUpItem(player.Id);
					break;
				case ConsoleKey.O:
					_context.DropItem(player.Id, SelectFromInventory("Drop", player));
					break;
				case ConsoleKey.V:
					_context.WieldWeapon(player.Id, SelectFromInventory("Wield", player));
					break;
				case ConsoleKey.R:
					_context.EquipArmor(player.Id, SelectFromInventory("Equip", player));
					break;
				case ConsoleKey.T:
					_context.UnequipArmor(player.Id, player.EquippedArmorId);
					break;
				case ConsoleKey.B:
					_context.UnwieldWeapon(player.Id, player.WieldedWeaponId);
					break;
				case ConsoleKey.F:
					_context.QuaffPotion(player.Id, SelectFromInventory("Quaff", player));
					break;
				case ConsoleKey.G:
					_context.QuickQuaff(player.Id, x => x.IsGaseousPotion);
					break;
				case ConsoleKey.H:
					_context.QuickQuaff(player.Id, x => x.IsHealingPotion);
					break;
				case ConsoleKey.OemPlus:
					IncreaseAttribute(player);
					break;
				case ConsoleKey.U:
					_context.MoveUp(player.Id);
					break;
				case ConsoleKey.N:
					_context.MoveDown(player.Id);
					break;
				case ConsoleKey.J:
					var plane = CreateTextInputPopup("Planeshift", "Shift to plane:");
					_context.Planeshift(player.Id, plane);
					break;
				case ConsoleKey.I:
					CreateMessagePopup("Visible Items",
					                   player.VisibleItems.Any()
						                   ? player.VisibleItems.Select(x => x.Name).ToArray()
						                   : new[] {"You can't see any items here..."});
					break;
				case ConsoleKey.K:
					CreateMessagePopup("Visible Entities",
					                   player.VisibleEntities.Any()
						                   ? player.VisibleEntities.Select(x => x.Name).ToArray()
						                   : new[] {"You can't see any entities here..."});
					break;
				case ConsoleKey.OemMinus:
					var command = CreateTextInputPopup("What would you like do do?", "Type command:");
					HandleCommand(command);
					break;
				case ConsoleKey.M:
					InitPlayers();
					break;
				default:
					var direction = GetPlayerDirection(key.Key);

					if (direction != Direction.None)
					{
						_context.Move(_currentPlayerId, direction);
					}
					else
					{
						switch (key.KeyChar)
						{
							case '1':
								_currentPlayerId = _player1Id;
								break;
							case '2':
								_currentPlayerId = _player2Id;
								break;
							case '3':
								_currentPlayerId = _player3Id;
								break;
							case '0':
								_context.ToggleAttackMode(_currentPlayerId);
								break;
							case '9':
								_context.TogglePvPMode(_currentPlayerId);
								break;
						}
					}
					break;
			}
		}