private bool TryMove(int newX, int newY, World world, bool teleport = false)
		{
			if (!world.ValidBlock(newX, newY))
				return false;

			Tuple<int, int> acres = world.ConvertToAcre(newX, newY);
			ExplorerConstants.Items.IDS newBlockItem = world.GetTopObject(newX, newY);
			ItemBlueprint newBlockInfo = ExplorerConstants.Items.AllBlueprints[newBlockItem];

			//First, go ahead and just get the item if we have autopickup turned on
			if (newBlockInfo.CanAutoPickup && GetOption(PlayerOptions.Autopickup) && !world.InLockedArea(LockID, acres.Item1, acres.Item2) &&
            newBlockInfo.StaminaRequired <= stamina && world.PickupObject(newX, newY))
			{
				GetItem(newBlockItem);
			}

			//If we still can't occupy the space, we need to stop
			if (!world.PlayerCanPass(newX, newY) && !(newBlockItem == ExplorerConstants.Items.IDS.Gate &&
				world.GetOwner(acres.Item1, acres.Item2) == playerID))
				return false;
			if (!teleport && stamina < newBlockInfo.StaminaRequired)
				return false;

			BlockX = newX;
			BlockY = newY;

			//Assume we moved one space
			if (!teleport)
			{
				stepsTaken++;
				EquippedSteps++;
				stamina -= newBlockInfo.StaminaRequired;
			}

			if(world.SetExplorer(playerID, acres.Item1, acres.Item2))
				score+=ExplorerConstants.Player.ExploreScore;

			return true;
		}
		//Perform the given actions in the given world. Returns all the errors that occurred
		public string PerformActions(List<ExplorerConstants.Player.Actions> actions, World world, World baseWorld, out int getChatCoins)
		{
			getChatCoins = 0;
			bool stopActions = false;
			bool strafing = false;
			int oblockX = BlockX;
			int oblockY = BlockY;
         int lookaheadX = BlockX;
         int lookaheadY = BlockY;
			Tuple<int, int> acre;
			List<string> errorMessages = new List<string>();
			int beforeFruit = ItemAmount(ExplorerConstants.Items.IDS.Fruit) + ItemAmount(ExplorerConstants.Items.IDS.SuperFruit);

         Action<ExplorerConstants.Items.IDS> EatFruit = x =>
         {
            if (CanEat)
            {
               if(x == ExplorerConstants.Items.IDS.Fruit)
               {
                  RestoreStamina(ExplorerConstants.Items.FruitStaminaRestore);
               }
               else if (x == ExplorerConstants.Items.IDS.SuperFruit)
               {
                  RestoreStamina(ExplorerConstants.Items.SuperFruitStaminaRestore);
               }
               else
               {
                  errorMessages.Add("-You can't eat that!");
                  return;
               }

               fullness += FruitFullnessIncrease;

               if(EquippedItem == x)
               {
                  UseEquippedItem();
               }
               else
               {
                  if(!RemoveItem(x, 1))
                     errorMessages.Add("-Internal error: tried to eat fruit that you didn't have!");
               }
            }
            else
            {
               errorMessages.Add("-You can't eat anymore; you're full!");
            }
         };

			//Force the removal of your token so it doesn't get in the way
			if(!InCave)
				world.ForceRemoval(ExplorerConstants.Map.Layers.PlayerLayer, BlockX, BlockY);

			foreach (ExplorerConstants.Player.Actions action in actions)
			{
				if (stopActions)
				{
					break;
				}

				int facingX = BlockX;
				int facingY = BlockY;
				int newX = BlockX;
				int newY = BlockY;

				switch (facingDirection)
				{
					case ExplorerConstants.Player.Directions.Right:
						facingX++;
						break;
					case ExplorerConstants.Player.Directions.Left:
						facingX--;
						break;
					case ExplorerConstants.Player.Directions.Down:
						facingY++;
						break;
					case ExplorerConstants.Player.Directions.Up:
						facingY--;
						break;
				}

				ExplorerConstants.Items.IDS facingItem = ExplorerConstants.Items.IDS.Empty;
				if(world.ValidBlock(facingX, facingY))
					facingItem = world.GetObject(facingX, facingY, ExplorerConstants.Map.Layers.ObjectLayer);

				ItemBlueprint facingInfo = ExplorerConstants.Items.AllBlueprints[facingItem];

				switch (action)
				{
					case ExplorerConstants.Player.Actions.Pickup:
						if (!world.ValidBlock(facingX, facingY))
						{
							errorMessages.Add("-You cannot pickup items here");
						}
						else if (stamina >= facingInfo.StaminaRequired)
						{
							acre = world.ConvertToAcre(facingX, facingY);
							if (facingInfo.OwnedItem && world.GetOwner(acre.Item1, acre.Item2) != playerID && !world.IsCave)
							{
								errorMessages.Add("-You cannot pick up items that aren't yours!");
							}
							else if (world.InLockedArea(LockID, acre.Item1, acre.Item2))
							{
								errorMessages.Add("-You cannot pick up items in a locked area!");
							}
							else if (world.PickupObject(facingX, facingY))
							{
                        if (ExplorerConstants.Items.PickupTransformations.ContainsKey(facingItem))
                           GetItem(ExplorerConstants.Items.PickupTransformations[facingItem]);
                        else
                           GetItem(facingItem);
                        
								stamina -= facingInfo.StaminaRequired;
                        if (facingItem == ExplorerConstants.Items.IDS.Statue)
                        {
                           score -= ExplorerConstants.Player.StatueScore;
                        }
                        else if (facingItem == ExplorerConstants.Items.IDS.AreaLocker && !world.IsCave)
                        {
                           world.SetLocked(acre.Item1, acre.Item2, false);
                           errorMessages.Add("-You've unlocked acre " + acre.Item1 + "-" + acre.Item2 + " plus the surrounding acres");
                        }
                        else if (facingItem == ExplorerConstants.Items.IDS.Flag)
                        {
                           score += ExplorerConstants.Player.FlagScore;
                        }

								if (facingItem == ExplorerConstants.Items.IDS.ChatCoins)
								{
                           //This is just a temporary solution!
                           List<ExplorerConstants.Items.IDS> possiblePickups = new List<ExplorerConstants.Items.IDS> {
                              ExplorerConstants.Items.IDS.Coal,
                              ExplorerConstants.Items.IDS.Dirt,
                              ExplorerConstants.Items.IDS.Fence,
                              ExplorerConstants.Items.IDS.Flower,
                              ExplorerConstants.Items.IDS.Fruit,
                              ExplorerConstants.Items.IDS.Grass,
                              ExplorerConstants.Items.IDS.Iron,
                              ExplorerConstants.Items.IDS.Planks,
                              ExplorerConstants.Items.IDS.Sand,
                              ExplorerConstants.Items.IDS.Sapling,
                              ExplorerConstants.Items.IDS.Seed,
                              ExplorerConstants.Items.IDS.Stone,
                              ExplorerConstants.Items.IDS.Torch,
                              ExplorerConstants.Items.IDS.Wood
                           };
                           possiblePickups.Shuffle();
									int coins = ExplorerConstants.Probability.ChatCoinGetLow + random.Next(ExplorerConstants.Probability.ChatCoinRange);
                           GetItem(possiblePickups[0], coins);
                           errorMessages.Add("-You picked up " + coins + " " + ExplorerConstants.Items.AllBlueprints[possiblePickups[0]].DisplayName + "s! Cool!");
                           //errorMessages.Add("-You picked up " + coins + " chat coins! Cool!");
									//getChatCoins += coins;
								}

								//You picked up the cave item! We need to "collapse" the cave.
								if (ExplorerConstants.Items.CaveLoot.Contains(facingItem) && world.IsCave)
								{
									errorMessages.Add("-Picking up the " + facingInfo.DisplayName + " caused you to teleport out of the cave!");
									LeaveCave(baseWorld);
									world = baseWorld;
									stopActions = true;
								}
							}
							else
							{
								errorMessages.Add("-There was no object to pick up");
							}
						}
						break;
					case ExplorerConstants.Player.Actions.LookUp:
						facingDirection = ExplorerConstants.Player.Directions.Up;
						break;
					case ExplorerConstants.Player.Actions.LookDown:
						facingDirection = ExplorerConstants.Player.Directions.Down;
						break;
					case ExplorerConstants.Player.Actions.LookLeft:
						facingDirection = ExplorerConstants.Player.Directions.Left;
						break;
					case ExplorerConstants.Player.Actions.LookRight:
						facingDirection = ExplorerConstants.Player.Directions.Right;
						break;
               case ExplorerConstants.Player.Actions.MoveDown:
                  if (!strafing)
                     facingDirection = ExplorerConstants.Player.Directions.Down;
                  newY++;
                  lookaheadY = newY + 1;
						TryMove(newX, newY, world);
						break;
					case ExplorerConstants.Player.Actions.MoveUp:
						if (!strafing)
							facingDirection = ExplorerConstants.Player.Directions.Up;
						newY--;
                  lookaheadY = newY - 1;
						TryMove(newX, newY, world);
						break;
					case ExplorerConstants.Player.Actions.MoveLeft:
						if (!strafing)
							facingDirection = ExplorerConstants.Player.Directions.Left;
						newX--;
                  lookaheadX = newX - 1;
						TryMove(newX, newY, world);
						break;
					case ExplorerConstants.Player.Actions.MoveRight:
						if (!strafing)
							facingDirection = ExplorerConstants.Player.Directions.Right;
						newX++;
                  lookaheadX = newX + 1;
						TryMove(newX, newY, world);
						break;
					case ExplorerConstants.Player.Actions.Strafe:
						strafing = !strafing;
						break;
					case ExplorerConstants.Player.Actions.UseEquippedItem:
						acre = world.ConvertToAcre(facingX, facingY);
						if(equipped == ExplorerConstants.Items.IDS.Fruit || equipped == ExplorerConstants.Items.IDS.SuperFruit)
						{
                     EatFruit(equipped);
						}
						else if (equipped == ExplorerConstants.Items.IDS.MagicStone)
						{
							IncreaseMaxStamina(ExplorerConstants.Items.MagicStoneStaminaIncrease);
							UseEquippedItem();
							errorMessages.Add("-You used a " + ExplorerConstants.Items.AllBlueprints[equipped].DisplayName + " and increased your max stamina!");
						}
						else if (world.CanPutObject(equipped, facingX, facingY))
						{
							string claimProblems = world.CanClaim(acre.Item1, acre.Item2, playerID);
							ExplorerConstants.Items.IDS actualObject = equipped;

							if (ExplorerConstants.Items.Transformations.ContainsKey(equipped))
								actualObject = ExplorerConstants.Items.Transformations[equipped];

							ItemBlueprint objectInfo = ExplorerConstants.Items.AllBlueprints[actualObject];

							if (objectInfo.RequiresOwnedAcre &&
								world.GetOwner(acre.Item1, acre.Item2) != playerID)
							{
								errorMessages.Add("-You can't place the equipped item (" + objectInfo.DisplayName + ") in an acre you don't own!");
							}
							else if (objectInfo.CannotOwn && (world.GetOwner(acre.Item1, acre.Item2) > 0 || world.IsSpawn(acre.Item1, acre.Item2)))
							{
								errorMessages.Add("-You can't place the equipped item (" + objectInfo.DisplayName + ") in an owned or spawning acre!");
							}
							else if (actualObject == ExplorerConstants.Items.IDS.Tower &&
								!string.IsNullOrWhiteSpace(claimProblems))
							{
								errorMessages.Add("-You can't claim this acre! " + claimProblems);
							}
							else if (actualObject == world.GetObject(facingX, facingY, objectInfo.Layer))
							{
								errorMessages.Add("-You can't place the equipped item (" + objectInfo.DisplayName + "); it's already there!");
							}
							else if (world.InLockedArea(LockID, acre.Item1, acre.Item2))
							{
								errorMessages.Add("-You can't place items in a locked area!");
							}
							else if (world.GetLocked(acre.Item1, acre.Item2) && actualObject == ExplorerConstants.Items.IDS.AreaLocker)
							{
								errorMessages.Add("-You can't lock this acre! It's already locked!");
							}
							else if (world.PutObject(actualObject, facingX, facingY))
							{
								if (actualObject == ExplorerConstants.Items.IDS.Tower)
								{
									score += ExplorerConstants.Player.TowerScore;
									errorMessages.Add("-You claimed acre " + acre.Item1 + "-" + acre.Item2 + "!");
									world.SetOwner(playerID, acre.Item1, acre.Item2);
								}
								else if (actualObject == ExplorerConstants.Items.IDS.AreaLocker)
								{
									world.SetLocked(acre.Item1, acre.Item2, true);
									errorMessages.Add("-You locked acre " + acre.Item1 + "-" + acre.Item2 + " and the surrounding acres");
								}
								else if (actualObject == ExplorerConstants.Items.IDS.Statue)
								{
									score += ExplorerConstants.Player.StatueScore;
								}
								UseEquippedItem();
							}
						}
						else
						{
							if (equipped == ExplorerConstants.Items.IDS.Empty)
								errorMessages.Add("-You don't have anything equipped");
							else
								errorMessages.Add("-You can't use the equipped item: " + ExplorerConstants.Items.AllBlueprints[equipped].DisplayName);
						}
							
						break;
				}

				if (stamina < MaxStamina / 2 && GetOption(PlayerOptions.AutoFruit))
				{
					if (ItemAmount(ExplorerConstants.Items.IDS.Fruit) > 0)
					{
                  EatFruit(ExplorerConstants.Items.IDS.Fruit);
//						if (!RemoveItem(ExplorerConstants.Items.IDS.Fruit, 1))
//							errorMessages.Add("-Fatal error: Inconsistent item counts. Please report this bug!");
//						else
//							RestoreStamina(ExplorerConstants.Items.FruitStaminaRestore);
					}
					else if (ItemAmount(ExplorerConstants.Items.IDS.SuperFruit) > 0)
					{
                  EatFruit(ExplorerConstants.Items.IDS.SuperFruit);
//						if (!RemoveItem(ExplorerConstants.Items.IDS.SuperFruit, 1))
//							errorMessages.Add("-Fatal error: Inconsistent item counts. Please report this bug!");
//						else
//							RestoreStamina(ExplorerConstants.Items.SuperFruitStaminaRestore);
					}
				}

            //Torch reuse
				if (EquippedSteps >= ExplorerConstants.Items.TorchSteps &&
					equipped == ExplorerConstants.Items.IDS.Torch)
				{
					UseEquippedItem();
				}

				if (equipped != ExplorerConstants.Items.IDS.Empty && inventory[equipped] == 0)
				{
					errorMessages.Add("-You ran out of your equipped item (" + ExplorerConstants.Items.AllBlueprints[equipped].DisplayName + ")");
					equipped = ExplorerConstants.Items.IDS.Empty;
				}

				if (stamina == 0)
				{
					errorMessages.Add("-You're out of stamina! Refill it with Fruit or rest for a bit.");
					break;
				}
			}

			if ((oblockX != BlockX || oblockY != BlockY) && !world.PlayerCanHalt(BlockX, BlockY))
			{
				errorMessages.Add("-You halted in a block which cannot be occupied, so you have been moved to a nearby location");
				Tuple<int, int> newLocation = world.FindCloseHaltable(BlockX, BlockY, lookaheadX, lookaheadY);

				if (!TryMove(newLocation.Item1, newLocation.Item2, world, true))
					errorMessages.Add("-Fatal error! You could not be moved from the previous bad location!");
			}
			else if (world.GetObject(BlockX, BlockY, ExplorerConstants.Items.AllBlueprints[ExplorerConstants.Items.IDS.CaveEntrance].Layer) == ExplorerConstants.Items.IDS.CaveEntrance)
			{
				//Oh crap, we landed on a cave entrance! Try to enter the cave.
				if (world.HasCave(BlockX, BlockY))
				{
					//Get rid of your dang player token
					//world.ForceRemoval(ExplorerConstants.Map.Layers.PlayerLayer, BlockX, BlockY);

					//Get the cave and stick you right in there
					World cave = world.GetCave(BlockX, BlockY);
					inCaveLocation = Tuple.Create(BlockX, BlockY);
					AdvanceWorldDepth(cave.SpawnAcreX, cave.SpawnAcreY);
					
					//Put a block over the cave so people can't get in
					world.ForcePut(ExplorerConstants.Items.IDS.BlockingBlock, inCaveLocation.Item1, inCaveLocation.Item2);

					errorMessages.Add("-You entered a cave! Equip a torch!");
				}
				else
				{
					errorMessages.Add("-You tried to enter the cave, but the cave collapsed!");
					world.ForceRemoval(ExplorerConstants.Items.AllBlueprints[ExplorerConstants.Items.IDS.CaveEntrance].Layer, BlockX, BlockY);
				}
			}
			else if (world.GetObject(BlockX, BlockY, ExplorerConstants.Items.AllBlueprints[ExplorerConstants.Items.IDS.CaveExit].Layer) == ExplorerConstants.Items.IDS.CaveExit)
			{
				errorMessages.Add("-As you leave the cave, the entrance collapses behind you");
				LeaveCave(baseWorld);
				world = baseWorld;
			}

			if (beforeFruit > 0 && (ItemAmount(ExplorerConstants.Items.IDS.Fruit) + ItemAmount(ExplorerConstants.Items.IDS.SuperFruit)) == 0)
				errorMessages.Add("-You've run out of fruit");

			//Now put your player token back
			if(!InCave)
				world.ForcePut(ExplorerConstants.Items.IDS.PlayerToken, BlockX, BlockY);

			return string.Join("\n", errorMessages.Distinct());
		}