public void TestAcceptTradeCounterOffer() { var manager = DoInitialPlacementsAndRoll(false); var activePlayer = manager.ActivePlayer; var player1 = manager.Players.FirstOrDefault(p => p.Id == PLAYER_1); Assert.IsNotNull(player1); // Active player offer trade of 1 ore and 2 wheat for 3 wood and 4 sheep. activePlayer.RemoveAllResources(); player1.RemoveAllResources(); var toOtherPlayer = new ResourceCollection(ore: 1, wheat: 2); var toActivePlayer = new ResourceCollection(wood: 3, sheep: 4); var toActivePlayerCounter = new ResourceCollection(brick: 5, sheep: 1); var originalOffer = new TradeOffer(activePlayer.Id, toOtherPlayer, toActivePlayer); var counterOffer = new TradeOffer(player1.Id, toActivePlayerCounter, toOtherPlayer); activePlayer.AddResources(toOtherPlayer); player1.AddResources(toActivePlayerCounter); manager.PlayerOfferTrade(activePlayer.Id, originalOffer); Assert.AreEqual(PlayerTurnState.RequestingPlayerTrade, manager.PlayerTurnState, "Player should be in the 'RequestingTrade' state."); // Player 1 can't afford it and will send a counter-offer. var r = manager.AcceptTradeFromActivePlayer(player1.Id); Assert.IsTrue(r.Failed, "Player 1 can't afford the current trade."); r = manager.SendCounterTradeOffer(player1.Id, counterOffer); Assert.IsTrue(r.Succeeded, "The counter offer send action should work."); r = manager.PlayerAcceptCounterTradeOffer(activePlayer.Id, player1.Id); Assert.IsTrue(r.Succeeded, "The counter offer should be accepted."); Assert.IsTrue(activePlayer.ResourceCards.Equals(toActivePlayerCounter), "Active player did not get his resources from the trade."); Assert.IsTrue(player1.ResourceCards.Equals(toOtherPlayer), "Player 1 did not get his resources from the trade."); Assert.AreEqual(PlayerTurnState.TakeAction, manager.PlayerTurnState, "The trade is complete. Player should be in the 'TakeAction' state."); }
/// <summary> /// Sends a counter trade offer to the active player. This can only be called by a non-active player. /// </summary> public ActionResult SendCounterTradeOffer(int playerId, TradeOffer counterOffer) { var validation = ValidatePlayerAction(PlayerTurnState.RequestingPlayerTrade); if (validation.Failed) return validation; var pr = GetPlayerFromId(playerId); if (pr.Failed) return pr; if (counterOffer == null || !counterOffer.IsValid) { return ActionResult.CreateFailed("Invalid trade offer."); } counterOffer.CreatorPlayerId = playerId; // Set the playedId manually just in case. _tradeHelper.SendCounterOffer(counterOffer); return ActionResult.CreateSuccess(); }
/// <summary> /// Trade with the bank or harbor. A 4:1 trade with the bank is always available. /// A 3:1 or 2:1 trade can be done depending on the player's harbors. /// Can only be called by the active player. /// </summary> public ActionResult PlayerTradeWithBank(int playerId, TradeOffer tradeOffer) { var validation = ValidatePlayerAction(PlayerTurnState.TakeAction, playerId); if (validation.Failed) return validation; var pr = GetPlayerFromId(playerId); if (pr.Failed) return pr; var player = pr.Data; var ports = _gameBoard.GetPortsForPlayer(playerId); return player.DoTradeWithBank(tradeOffer, ports); }
/// <summary> /// Offer a player-to-player trade with anyone. This can be immediately accepted or /// players can send counter-offers. Can only be called by the active player. /// </summary> public ActionResult PlayerOfferTrade(int playerId, TradeOffer tradeOffer) { var validation = ValidatePlayerAction(PlayerTurnState.TakeAction, playerId); if (validation.Failed) return validation; if (tradeOffer == null || !tradeOffer.IsValid) { return ActionResult.CreateFailed("Invalid trade offer."); } if (!ActivePlayer.HasAtLeast(tradeOffer.ToGive)) { return ActionResult.CreateFailed("Cannot afford to create this trade offer."); } _tradeHelper.ClearAllOffers(); tradeOffer.CreatorPlayerId = playerId; // Set the playerId manually just in case. _tradeHelper.ActivePlayerTradeOffer = tradeOffer; _playerTurnState = PlayerTurnState.RequestingPlayerTrade; return ActionResult.CreateSuccess(); }
/// <summary> /// Does a resource exchange with the bank. /// </summary> public ActionResult DoTradeWithBank(TradeOffer offer, IList<Port> portsAvailable) { if (!offer.IsValidBankOffer) return ActionResult.CreateFailed("Invalid trade. One or more resources are empty."); var toReceive = offer.ToReceive.GetLargestStack(); var toGive = offer.ToGive.GetLargestStack(); if (toGive.Type == toReceive.Type) return ActionResult.CreateFailed("Invalid trade. Both resource types are identical."); bool threeToOnePort = portsAvailable.Any(p => p.Resource == toGive.Type); bool twoToOnePort = portsAvailable.Any(p => p.Resource == ResourceTypes.None); bool doTrade = false; doTrade = ((toReceive.Count*4) == toGive.Count) || (threeToOnePort && ((toReceive.Count*3) == toGive.Count)) || (twoToOnePort && ((toReceive.Count*2) == toGive.Count)); if (!doTrade) return ActionResult.CreateFailed("Invalid trade. Resource counts are invalid."); this.RemoveResources(offer.ToGive); this.AddResources(offer.ToReceive); return ActionResult.CreateSuccess(); }
/// <summary> /// Returns true if this player can afford to do the specified trade offered by a different player. /// </summary> public bool CanAffordTradeOffer(TradeOffer otherPlayerOffer) { return HasAtLeast(otherPlayerOffer.ToReceive); }
/// <summary> /// Accepts a trade offer from another player and does the resouces exchange. /// </summary> public ActionResult AcceptTradeOffer(Player otherPlayer, TradeOffer offer) { if (!CanAffordTradeOffer(offer)) { return ActionResult.CreateFailed("Accepting player cannot afford the trade."); } if (!otherPlayer.HasAtLeast(offer.ToGive)) { return ActionResult.CreateFailed("Offering player cannot afford the trade."); } this.RemoveResources(offer.ToReceive); otherPlayer.RemoveResources(offer.ToGive); this.AddResources(offer.ToGive); otherPlayer.AddResources(offer.ToReceive); return ActionResult.CreateSuccess(); }
/// <summary> /// Send a counter-offer to the active player. /// </summary> public void SendCounterOffer(TradeOffer counterOffer) { int playerId = counterOffer.CreatorPlayerId; CancelCounterOffer(playerId); CounterOffers.Add(counterOffer); }
public void TestTradeWithBank() { var manager = DoInitialPlacementsAndRoll(false); var player = manager.ActivePlayer; // Trade 4 ore for 1 brick. var toGive = new ResourceCollection(ore: 4); var toGet = new ResourceCollection(brick: 1); player.RemoveAllResources(); player.AddResources(toGive); Assert.IsTrue(player.ResourceCards.IsSingleResourceType && player.ResourceCards.Equals(toGive)); var offer = new TradeOffer(player.Id, toGive, toGet); var tradeResult = manager.PlayerTradeWithBank(player.Id, offer); Assert.IsTrue(tradeResult.Succeeded, "The bank trade should succeed."); Assert.IsTrue(player.ResourceCards.IsSingleResourceType && player.ResourceCards.Equals(toGet)); Assert.AreEqual(PlayerTurnState.TakeAction, manager.PlayerTurnState, "Player should be in the 'TakeAction' state."); // Trade 8 wheat for 2 wood. toGive = new ResourceCollection(wheat: 8); toGet = new ResourceCollection(wood: 2); player.RemoveAllResources(); player.AddResources(toGive); Assert.IsTrue(player.ResourceCards.IsSingleResourceType && player.ResourceCards.Equals(toGive)); offer = new TradeOffer(player.Id, toGive, toGet); tradeResult = manager.PlayerTradeWithBank(player.Id, offer); Assert.IsTrue(tradeResult.Succeeded, "The bank trade should succeed."); Assert.IsTrue(player.ResourceCards.IsSingleResourceType && player.ResourceCards.Equals(toGet)); Assert.AreEqual(PlayerTurnState.TakeAction, manager.PlayerTurnState, "Player should be in the 'TakeAction' state."); // Trade 2 wheat for 2 wood. Should fail. toGive = new ResourceCollection(wheat: 2); toGet = new ResourceCollection(wood: 2); player.RemoveAllResources(); player.AddResources(toGive); Assert.IsTrue(player.ResourceCards.IsSingleResourceType && player.ResourceCards.Equals(toGive)); offer = new TradeOffer(player.Id, toGive, toGet); tradeResult = manager.PlayerTradeWithBank(player.Id, offer); Assert.IsTrue(tradeResult.Failed, "The bank trade should fail."); Assert.IsTrue(player.ResourceCards.IsSingleResourceType && player.ResourceCards.Equals(toGive)); Assert.AreEqual(PlayerTurnState.TakeAction, manager.PlayerTurnState, "Player should be in the 'TakeAction' state."); }