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()); }