public override string LandOn(ref Player player)
        {
            if (!_isPenalty) // Go to jail and get out of jail cards are set to not be penalties by default
            {
                // These name checks are enough to determine if the card drawn
                // is a go to jail or get out of jail card
                if (Name.ToLower().Contains("go to jail"))
                {
                    player.GoToJail();
                    return base.LandOn(ref player);
                }

                if (Name.ToLower().Contains("get out of jail free"))
                {
                    player.GetOutOfJailCardCount++;
                    return base.LandOn(ref player);
                }

                player.Receive(_penaltyOrBenefitAmount);
                return base.LandOn(ref player) + string.Format(" {0} has received {1}.", player.GetName(), _penaltyOrBenefitAmount);
            }
            else
            {
                player.Pay(_penaltyOrBenefitAmount);
                return base.LandOn(ref player) + string.Format(" {0} has paid {1}.", player.GetName(), _penaltyOrBenefitAmount);
            }
        }
 public void TradeProperty(ref TradeableProperty property, ref Player purchaser, decimal amount, decimal mortgageAmount)
 {
     // If the property isn't mortgaged the mortgage amount will just be 0
     purchaser.Pay(amount + mortgageAmount);
     Receive(amount);
     property.SetOwner(ref purchaser);
     Banker.Access().Receive(mortgageAmount);
 }
 public void Purchase(ref Player buyer)
 {
     if (AvailableForPurchase())
     {
         buyer.Pay(GetPrice());
         SetOwner(ref buyer);
     }
     else
     {
         throw new ApplicationException("This property is not available for purchase.");
     }
 }
 public override string LandOn(ref Player player)
 {
     if ((GetOwner() != Banker.Access()) && (GetOwner() != player))
     {
         PayRent(ref player);
         return string.Format("You rolled a total of {0}. So your rent is {0} x {1} = ${2}", player.GetLastMove(),
             _rentMultiplier, (player.GetLastMove()*_rentMultiplier));
     }
     else
     {
         return base.LandOn(ref player);
     }
 }
 public override string LandOn(ref Player player)
 {
     if((GetOwner() != Banker.Access()) && (GetOwner() != player))
     {
         //pay rent
         PayRent(ref player);
         return base.LandOn(ref player) +
                string.Format("\nRent has been paid for {0} of ${1} to {2}", GetName(), GetRent(), Owner.GetName());
     }
     else
     {
         return base.LandOn(ref player);
     }
 }
 public void PurchaseProperty(Player player, bool? testAnswer = null)
 {
     if (player.IsInJail)
     {
         Console.WriteLine("You are in Jail and can not purchase property.");
     }
     //if property available give option to purchase else so not available
     else if (Board.Access().GetProperty(player.GetLocation()).AvailableForPurchase())
     {
         TradeableProperty propertyLocatedOn = (TradeableProperty)Board.Access().GetProperty(player.GetLocation());
         bool? respYN = testAnswer ?? GetInputYn(player, string.Format("'{0}' is available to purchase for ${1}. Are you sure you want to purchase it?", propertyLocatedOn.GetName(), propertyLocatedOn.GetPrice()));
         if ((bool) respYN)
         {
             propertyLocatedOn.Purchase(ref player);//purchase property
             Console.WriteLine("{0}You have successfully purchased {1}.", PlayerPrompt(player), propertyLocatedOn.GetName());
         }
     }
     else
     {
         Console.WriteLine("{0}{1} is not available for purchase.", PlayerPrompt(player), Board.Access().GetProperty(player.GetLocation()).GetName());
     }
 }
        private void GetOutOfJail(Player player, bool mustSettle)
        {
            Console.WriteLine();
            Console.WriteLine("1. Pay $50 fine");
            Console.WriteLine("2. Use 'Get Out of Jail Free' card");
            if(!mustSettle) Console.WriteLine("3. Back to Main Menu");
            Console.Write(mustSettle ? "(1-2)>" : "(1-3)>");

            //read response
            var resp = InputInteger();

            //if response is invalid redisplay menu
            if (resp == 0)
                GetOutOfJail(player, mustSettle);

            if (mustSettle && resp != 1 && resp != 2)
            {
                Console.WriteLine("You must get out of Jail");
                GetOutOfJail(player, true);
            }

            switch (resp)
            {
                case 1:
                    Console.WriteLine(player.PayJailFee()
                        ? "You are now out of jail"
                        : "You have insufficient funds and are still in jail");
                    break;
                case 2:
                    if (player.GetOutOfJailCardCount > 0)
                    {
                        player.SetFreeFromJail();
                        player.GetOutOfJailCardCount--;
                        Console.WriteLine("You are now free from jail.");
                        break;
                    }
                    Console.WriteLine("You don't have any Get out of Jail free cards.");
                    if (mustSettle) GetOutOfJail(player, true);
                    break;
                case 3:
                    break;
                default:
                    Console.WriteLine("That option is not avaliable. Please try again.");
                    GetOutOfJail(player, mustSettle);
                    break;
            }
        }
        public void MortgageOptions(Player player)
        {
            Console.WriteLine();
            Console.WriteLine("1. Mortgage property");
            Console.WriteLine("2. Pay mortgage on property");
            Console.WriteLine("3. Back to Main Menu");
            Console.Write("(1-3)>");

            //read response
            var resp = InputInteger();

            Residential property;
            switch (resp)
            {
                case 1:
                    property =
                        (Residential)
                            DisplayPropertyChooser(player.GetPropertiesOwnedFromBoard(), "Property to mortgage: ", true);
                    if (property == null)
                    {
                        Console.WriteLine("You don't own any properties!");
                    }
                    else if (property.MortgageProperty())
                    {
                        Console.WriteLine("Property has been mortgaged for {0}", property.GetMortgageValue());
                    }
                    else // If it wasn't mortgaged it must be developed or already be mortgaged
                    {
                        Console.WriteLine(
                            "Property can't be mortgaged. Either it is already mortgaged or has been developed.");
                    }
                    break;
                case 2:
                    property =
                        (Residential)
                            DisplayPropertyChooser(player.GetPropertiesOwnedFromBoard(), "Property to unmortgage: ",
                                true);

                    if (property == null)
                    {
                        Console.WriteLine("You don't own any properties!");
                    }
                    else if (property.UnmortgageProperty())
                    {
                        Console.WriteLine("Mortgage has been paid for property {0}", property.GetName());
                    }
                    else // If it wasn't unmortgaged it's because it wasn't mortgaged in the first place
                    {
                        Console.WriteLine("Property must be mortgaged for you to pay the mortgage");
                    }
                    break;
                case 3:
                    break;
                default:
                    Console.WriteLine("That option is not avaliable. Please try again.");
                    MortgageOptions(player);
                    break;
            }
        }
        public Player DisplayPlayerChooser(ArrayList players, Player playerToExclude, String sPrompt)
        {
            //if no players return null
            if (players.Count == 0)
                return null;
            Console.WriteLine(sPrompt);
            //Create a new arraylist to display
            ArrayList displayList = new ArrayList(players);

            //remove the player to exlude
            displayList.Remove(playerToExclude);

            //go through and display each
            for (int i = 0; i < displayList.Count; i++)
            {
                Console.WriteLine("{0}. {1}", i + 1, displayList[i].ToString());
            }
            //display prompt
            Console.Write("({0}-{1})>", 1, displayList.Count);
            //get input
            int resp = this.InputInteger();

            //if outside of range
            if ((resp < 1) || (resp > displayList.Count))
            {
                Console.WriteLine("That option is not avaliable. Please try again.");
                this.DisplayPlayerChooser(players, playerToExclude, sPrompt);
                return null;
            }
            else
            {
                Player chosenPlayer = (Player) displayList[resp - 1];
                //find the player to return
                foreach (Player p in players)
                {
                    if(p.GetName() == chosenPlayer.GetName())
                        return p;
                }
                return null;
            }
        }
 public decimal GetRent(ref Player player)
 {
     return (_rentMultiplier*player.GetLastMove());
 }
 public virtual string LandOn(ref Player player)
 {
     return string.Format("{0} landed on {1}.", player.GetName(), GetName());
 }
 public virtual void PayRent(ref Player player)
 {
     player.Pay(Rent);
     GetOwner().Receive(Rent);
 }
        public void DisplayPlayerChoiceMenu(Player player)
        {
            int resp = 0;
            Console.WriteLine("\n{0}Please make a selection:\n", PlayerPrompt(player));
            Console.WriteLine("1. Finish turn");
            Console.WriteLine("2. View your details");
            Console.WriteLine("3. Purchase This Property");
            Console.WriteLine("4. Buy House for Property");
            Console.WriteLine("5. Sell house");
            Console.WriteLine("6. Trade Property with Player");
            Console.WriteLine("7. Mortgage Options");
            Console.WriteLine("8. Save Game");
            if (player.IsInJail) Console.WriteLine("9. Get Out of Jail");

            Console.Write(player.IsInJail ? "(1-9)>" : "(1-8)>");
            //read response
            resp = InputInteger();
            //if response is invalid redisplay menu
            if (resp == 0)
                this.DisplayPlayerChoiceMenu(player);

            //perform choice according to number input
                switch (resp)
                {
                    case 1:
                        break;
                    case 2:
                        Console.WriteLine("==================================");
                        Console.WriteLine(player.FullDetailToString());
                        Console.WriteLine("==================================");
                        DisplayPlayerChoiceMenu(player);
                        break;
                    case 3:
                        PurchaseProperty(player);
                        DisplayPlayerChoiceMenu(player);
                        break;
                    case 4:
                        BuyHouse(player);
                        DisplayPlayerChoiceMenu(player);
                        break;
                    case 5:
                        SellHouse(player);
                        DisplayPlayerChoiceMenu(player);
                        break;
                    case 6:
                        TradeProperty(player);
                        DisplayPlayerChoiceMenu(player);
                        break;
                    case 7:
                        MortgageOptions(player);
                        DisplayPlayerChoiceMenu(player);
                        break;
                    case 8:
                        SaveGame();
                        DisplayPlayerChoiceMenu(player);
                        break;
                    case 9:
                        GetOutOfJail(player, false);
                        DisplayPlayerChoiceMenu(player);
                        break;
                    default:
                        Console.WriteLine("That option is not avaliable. Please try again.");
                        DisplayPlayerChoiceMenu(player);
                        break;
                }
        }
        public bool GetInputYn(Player player, string sQuestion)
        {
            Console.WriteLine(PlayerPrompt(player) + sQuestion);
            Console.Write("y/n>");
            string resp = Console.ReadLine().ToUpper();

            switch (resp)
            {
                case "Y":
                    return true;
                case "N":
                    return false;
                default:
                    Console.WriteLine("That answer cannot be understood. Please answer 'y' or 'n'.");
                    this.GetInputYn(player, sQuestion);
                    return false;
            }
        }
 public string PlayerPrompt(Player player)
 {
     return string.Format("{0}:\t", player.GetName());
 }
        /// <summary>
        /// Sets up players for the new game of Monopoly
        /// </summary>
        /// <param name="testInput">Required so we can test this method without relying on console input, shouldn't be used outside of tests</param>
        /// <param name="testName">Required so we can test this method without relying on console input, shouldn't be used  outside of tests</param>
        public void SetUpPlayers(int? testInput = null, string testName = null)
        {
            //Add players to the board
            Console.WriteLine("How many players are playing?");
            Console.Write("(2-8)>");
            var playerCount = testInput ?? InputInteger();

            //if it is out of range then display msg and redo this method
            if ((playerCount < 2) || (playerCount > 8))
            {
                Console.WriteLine("That is an invalid amount. Please try again.");

                // Don't recall if it's a test
                if (testInput == null)
                {
                    SetUpPlayers();
                }
            }

            //Ask for players names
            for (int i = 0; i < playerCount; i++)
            {
                Console.WriteLine("Please enter the name for Player {0}:", i + 1);
                Console.Write(">");
                string sPlayerName = testName ?? Console.ReadLine();
                Player player = new Player(sPlayerName);
                //subscribe to events
                player.PlayerBankrupt += playerBankruptHandler;
                player.PlayerPassGo += playerPassGoHandler;
                //add player 
                Board.Access().AddPlayer(player);
                Console.WriteLine("{0} has been added to the game.", Board.Access().GetPlayer(i).GetName());
            }

            Console.WriteLine("Players have been setup");
        }
        private void HandleLanding(Property propertyLandedOn , Player player)
        {
            // If it's a residential property we need to parse it so we can get the colour and display it to the user
            // otherwise they won't be aware of colour the property is at any point.
            var propertyAsRes = propertyLandedOn.GetType() == typeof (Residential) ? (Residential) propertyLandedOn : null;
           
            // When landing on chance or community chest we need the behavour to be
            // slightly different, i.e. get a card and display what the card is
            if (propertyLandedOn.GetName().Contains("Chance") && (Board.Access().GetChanceCards().Count > 0))
            {
                Console.WriteLine(Board.Access().GetChanceCard().LandOn(ref player));
            }
            else if (propertyLandedOn.GetName().Contains("Community Chest") && (Board.Access().GetCommunityChestCards().Count > 0))
            {
                Console.WriteLine(Board.Access().GetCommunityChestCard().LandOn(ref player));
            }
            else
            {
                // Landon property and output to console
                // In the case that they've landed on a chance or community chest but there 
                // aren't any cards left we must make them aware of this.
                var isChance = propertyLandedOn.GetName().Contains("Chance");
                var isCommunityChest = propertyLandedOn.GetName().Contains("Community Chest");

                Console.WriteLine("{0}{1}{2}",
                    propertyLandedOn.LandOn(ref player),/*{0}*/
                    isChance ? " No more Chance cards." : isCommunityChest ? " No more Community Chest cards." : "",/*{1}*/
                    propertyAsRes != null ? " (Colour: " + propertyAsRes.GetHouseColour() + ")" : "");/*{2}*/
            }
        }
 public void SetOwner(ref Player newOwner)
 {
     Owner = newOwner;
 }
        public void BuyHouse(Player player, Property testProperty = null, bool? testAnswer = null)
        {
            if (Board.Access().Houses < 1)
            {
                Console.WriteLine("Sorry, the bank doesn't have any houses left.");
                return;
            }

            if (player.IsInJail)
            {
                Console.WriteLine("Sorry, you are in jail.");
                return;
            }

            //create prompt
            var sPrompt = String.Format("{0}Please select a property to buy a house for:", PlayerPrompt(player));

            //create variable for propertyToBuy
            Residential propertyToBuyFor = null;

            if (player.GetPropertiesOwnedFromBoard().Count == 0)
            {
                //write message
                Console.WriteLine("{0}You do not own any properties.", PlayerPrompt(player));
                //return from method
                return;
            }
            //get the property to buy house for
            var property = testProperty ?? DisplayPropertyChooser(player.GetPropertiesOwnedFromBoard(), sPrompt);
            //if dont own any properties
            
            //check that it is a residential
            if (property.GetType() == (new Residential().GetType()))
            {
                //cast to residential property
               propertyToBuyFor = (Residential) property;
            }
            else //else display msg 
            {
                Console.WriteLine("{0}A house can not be bought for {1} because it is not a Residential Property.", this.PlayerPrompt(player), property.GetName());
                return;
            }

            if (propertyToBuyFor.IsMortgaged)
            {
                Console.WriteLine("{0}A house can not be bought for {1} because it is currently mortgaged.", PlayerPrompt(player), property.GetName());
                return;
            }
            
            // Player must own all the propeties in the colour group
            if (!player.OwnsAllPropertiesOfColour(propertyToBuyFor.GetHouseColour()))
            {
                Console.WriteLine(
                    "You must own all the properties within this colour group ({0}) to buy houses for this property.",
                    propertyToBuyFor.GetHouseColour());
                return;
            }

            // We've checked if they own the properties of the colour, now
            // check if each property is equally developed
            if (!player.CanDevelopPropertyFurther(propertyToBuyFor))
            {
                Console.WriteLine("Each property in this colour group needs to have houses uniformly added");
            }
            else if (propertyToBuyFor.HasHotel)// If it has a hotel they can't add more houses.
            {
                Console.WriteLine("This property has a hotel and can not be developed further.");
            }
            else
            {
                // Can't buy a fifth house if there are not hotels left
                if (propertyToBuyFor.GetHouseCount() == 4 && Board.Access().Hotels < 1)
                {
                    Console.WriteLine("You can't buy another house as this would result in a hotel and there aren't any hotels left.");
                    return;
                }

                //confirm
                var doBuyHouse = testAnswer ?? GetInputYn(player, string.Format("You chose to buy a house for {0}. Are you sure you want to purchase a house for ${1}?", 
                                                                                propertyToBuyFor.GetName(), propertyToBuyFor.GetHouseCost()));

                //if confirmed
                if (doBuyHouse)
                {
                    //buy the house
                    propertyToBuyFor.AddHouse();
                    Console.WriteLine("{0}A new house for {1} has been bought successfully", PlayerPrompt(player),
                        propertyToBuyFor.GetName());
                }
            }
        }
        public void SellHouse(Player player, Property testProperty = null)
        {
            var playersProperties = player.GetPropertiesOwnedFromBoard();

            if (playersProperties.Count == 0)
            {
                Console.WriteLine("{0}You do not own any properties.", PlayerPrompt(player));
                return;
            }

            // Get properties that are residential and have at least one house to be sold
            var developedResidentials =
                playersProperties.ToArray()
                    .Where(x => x.GetType() == typeof (Residential))
                    .Cast<Residential>()
                    .Where(x => x.GetHouseCount() >= 1)
                    .ToArray();

            if (!developedResidentials.Any())
            {
                Console.WriteLine("You don't have any properties with houses to be sold!");
                return;
            }

            // Add the correct propeties to an arraylist, this is because
            // the property chooser takes an arraylist not an IEnumarable
            var propertiesToChooseFrom = new ArrayList();
            propertiesToChooseFrom.AddRange(developedResidentials);

            var playerPrompt = String.Format("{0}Please select a property to sell the house for:", PlayerPrompt(player));

            // Get the property to buy house for
            var property = testProperty ?? DisplayPropertyChooser(propertiesToChooseFrom, playerPrompt);

            var propertyToSellHouse = (Residential) property;

            propertyToSellHouse.SellHouse();
            Console.WriteLine("House sold for ${0}", propertyToSellHouse.GetHouseCost()/2);
        }
        public void TradeProperty(Player player)
        {
            //create prompt
            string sPropPrompt = String.Format("{0}Please select a property to trade:", this.PlayerPrompt(player));
            //create prompt
            string sPlayerPrompt = String.Format("{0}Please select a player to trade with:", this.PlayerPrompt(player));

            //get the property to trade
            TradeableProperty propertyToTrade = (TradeableProperty)this.DisplayPropertyChooser(player.GetPropertiesOwnedFromBoard(), sPropPrompt);

            //if dont own any properties
            if (propertyToTrade == null)
            {
                //write message
                Console.WriteLine("{0}You do not own any properties.", PlayerPrompt(player));
                //return from method
                return;
            }

            //get the player wishing to trade with
            Player playerToTradeWith = this.DisplayPlayerChooser(Board.Access().GetPlayers(), player, sPlayerPrompt);

            //get the amount wanted

            string inputAmtMsg = string.Format("{0}How much do you want for this property?", PlayerPrompt(player));

            decimal amountWanted = InputDecimal(inputAmtMsg);

            //confirm with playerToTradeWith
                //set console color
            ConsoleColor origColor = Console.ForegroundColor;
            int i = Board.Access().GetPlayers().IndexOf(playerToTradeWith);
            Console.ForegroundColor = this._colors[i];

            bool agreesToTrade;
            var mortgageInterest = Decimal.Zero;

            //get player response
            /*We need to do this to check and find if the property is mortgaged 
             and in the case that it is, notify the buyer that the price
             of the property includes the original owner's mortgage interest*/
            if (propertyToTrade.GetType() == typeof (Residential))
            {
                var residentialPropertyToTrade = (Residential) propertyToTrade;

                if (residentialPropertyToTrade.IsMortgaged)
                {
                    mortgageInterest = residentialPropertyToTrade.GetMortgageValue()*10/100;

                    agreesToTrade = GetInputYn(playerToTradeWith,
                        string.Format(
                            "{0} wants to trade '{1}' with you for ${2} (including seller's mortgage interest for this property). Do you agree to pay {2} for '{1}'",
                            player.GetName(),/*{0}*/
                            propertyToTrade.GetName(),/*{1}*/
                            amountWanted + mortgageInterest));/*{2}*/
                }
                else // If it's not mortgaged do the normal trading behaviour
                {
                    agreesToTrade = GetInputYn(playerToTradeWith,
                        string.Format("{0} wants to trade '{1}' with you for ${2}. Do you agree to pay {2} for '{1}'",
                            player.GetName(), propertyToTrade.GetName(), amountWanted));
                }
            }
            else 
            {
                agreesToTrade = GetInputYn(playerToTradeWith,
                    string.Format("{0} wants to trade '{1}' with you for ${2}. Do you agree to pay {2} for '{1}'",
                        player.GetName(), propertyToTrade.GetName(), amountWanted));
            }

            //resent console color
            Console.ForegroundColor = origColor;
            if (agreesToTrade)
            {
                Player playerFromBoard = Board.Access().GetPlayer(playerToTradeWith.GetName());
                //player trades property
                player.TradeProperty(ref propertyToTrade, ref playerFromBoard, amountWanted, mortgageInterest);
                Console.WriteLine("{0} has been traded successfully. {0} is now owned by {1}", propertyToTrade.GetName(), playerFromBoard.GetName());
            }
            else
            {
                //display rejection message
                Console.WriteLine("{0}{1} does not agree to trade {2} for ${3}", PlayerPrompt(player), playerToTradeWith.GetName(), propertyToTrade.GetName(), amountWanted);
            }     
        }
 public void AddPlayer(Player player)
 {
     Players.Add(player);
 }
 public override void PayRent(ref Player player)
 {
     player.Pay(GetRent(ref player));
     GetOwner().Receive(GetRent());
 }