/// <summary> /// Initializes a new instance of the <see cref="LlConsole.Game"/> class. /// </summary> /// <param name="configuration">XML configuration.</param> public Game(XmlDocument configuration) { if (configuration == null) { throw new ArgumentNullException( "configuration", "Cannot create new game with empty XML"); } XmlNodeList dice = configuration.GetElementsByTagName("Dice"); if (dice.Count > 0) { this.diceCount = XmlHelper.FromXmlIfExists<int>(dice[0], "Count", this.diceCount); this.diceSides = XmlHelper.FromXmlIfExists<int>(dice[0], "Sides", this.diceSides); } XmlNodeList props = configuration.GetElementsByTagName("Location"); foreach (XmlNode prop in props) { var l = new Location(prop); this.Add(l); } Location.SetBoard(this.Board); XmlNodeList peeps = configuration.GetElementsByTagName("Player"); foreach (XmlNode pers in peeps) { var p = new Player(pers); p.Where = this.Board[0]; this.Add(p); } XmlNodeList cards = configuration.GetElementsByTagName("FirstCard"); foreach (XmlNode card in cards) { var c = new Card(card); this.Add(c, false); } cards = configuration.GetElementsByTagName("SecondCard"); foreach (XmlNode card in cards) { var c = new Card(card); this.Add(c, true); } }
/// <summary> /// Update the current player to the next. /// </summary> /// <returns>The player.</returns> public Player NextPlayer() { int idx = (this.Players.IndexOf(this.currentPlayer) + 1) % this.Players.Count; this.currentPlayer = this.Players[idx]; if (this.currentPlayer.Balance <= 0 && this.Players.Count > 1) { this.currentPlayer = this.NextPlayer(); } return this.currentPlayer; }
/// <summary> /// Roll the dice, returning the value and a printable notice. /// </summary> /// <param name="p">The current player.</param> /// <returns>The rolled value.</returns> public string Roll(Player p) { int dice = 0; int i; string notices = string.Empty; for (i = 0; i < this.diceCount; i++) { dice += this.rand.Next(1, this.diceSides); } notices = "Rolls a " + dice.ToString() + "." + Environment.NewLine; if (p == null) { return notices; } for (i = 0; i < dice; i++) { notices += this.NextLocation(p, i != dice - 1); } return notices; }
/// <summary> /// Add the specified player. /// </summary> /// <param name="p">The new player.</param> public void Add(Player p) { this.Players.Add(p); if (this.currentPlayer == null) { this.currentPlayer = p; } }
/// <summary> /// Find the next location. /// </summary> /// <returns>The location.</returns> /// <param name="p">The moving player.</param> /// <param name="transit">If set to <c>true</c> transit.</param> public string NextLocation(Player p, bool transit) { string note = string.Empty; int idx; if (p == null) { return note; } idx = this.Board.IndexOf(p.Where) + 1; if (idx >= this.Board.Count) { idx = 0; } if (transit) { note = this.Board[idx].PassBy(this.currentPlayer); } p.Where = this.Board[idx]; return note; }
/// <summary> /// Handles the player's response of what to do when landing on another player's property. /// </summary> /// <returns>A message documenting what happened.</returns> /// <param name="p">The player.</param> /// <param name="answer">The player's answer.</param> private string RentLocation(Player p, string answer) { if (answer.ToLower(System.Globalization.CultureInfo.CurrentCulture).StartsWith("p", StringComparison.CurrentCulture)) { p.Withdraw(this.PriceRent); this.Owner.Deposit(this.PriceRent); return "Owned by " + this.Owner.Name + ", rent is $" + this.PriceRent.ToString(); } return string.Empty; }
/// <summary> /// Deals with the player's decision of whether to buy the location. /// </summary> /// <returns>A message documenting what happened.</returns> /// <param name="p">The player.</param> /// <param name="answer">The player's answer.</param> private string BuyLocation(Player p, string answer) { if (string.IsNullOrWhiteSpace(answer)) { return string.Empty; } if (answer.ToLower(System.Globalization.CultureInfo.CurrentCulture).StartsWith("y", StringComparison.CurrentCulture)) { p.Withdraw(this.PriceSale); this.Owner = p; return p.Name + " now owns " + this.Name + "."; } return string.Empty; }
/// <summary> /// Message to print when the player lands on the location. /// </summary> /// <returns>The on-landing message documenting what happened.</returns> /// <param name="p">The player.</param> /// <param name="answerer"> /// Routine that can handle the question's answer if the message is a question. /// </param> public string PrintOnLanding(Player p, ref Func<Player, string, string> answerer) { bool canBuy = this.CanBuy; bool ownable = this.Ownable; if (p == null) { return string.Empty; } switch (this.PropertyType) { case Zoning.Residential: case Zoning.Railroad: case Zoning.Franchise: if (canBuy && p.Balance > this.PriceSale) { answerer = this.BuyLocation; return "Want to buy " + this.Name + " for " + this.PriceSale.ToString() + "?"; } else if (canBuy) { return "Can't buy " + Name + ". Not enough money."; } else if (ownable && Owner != p) { int rent = PriceRent; if (this.PropertyType == Zoning.Franchise || this.PropertyType == Zoning.Railroad) { var rrs = board.Where(x => x.PropertyType == PropertyType && x.Owner == Owner); int nrrs = rrs.Count(); for (int i = 0; i < nrrs; i++) { rent *= Multiplier; } } answerer = RentLocation; return "Owned by " + Owner.Name + ", rent is $" + PriceRent.ToString() + ". [P]ay?"; } else if (ownable) { return p.Name + " already owns " + Name + "."; } break; case Zoning.Luxury: case Zoning.Necessity: p.Withdraw(this.PriceRent); return "Tax of $" + this.PriceRent.ToString() + " levied on " + p.Name + "."; case Zoning.Legacy: int due = this.PriceRent > p.Balance / 10 ? p.Balance / 10 : this.PriceRent; p.Withdraw(due); return "Tax of $" + due.ToString() + " levied on " + p.Name + "."; case Zoning.Trespassing: p.InJail = true; return p.Name + " was caught trespassing by Lord Blueblood and is sent to jail!"; case Zoning.MotherEarth: p.Deposit(this.Salary); return "Labor upon Mother Earth produces wages: $" + this.Salary.ToString() + "."; case Zoning.Park: return "Spending a day at the park."; } return string.Empty; }
/// <summary> /// Handle situations where a player passes a location but does not land there. /// </summary> /// <returns>A printable string documenting what happened.</returns> /// <param name="p">THe player.</param> public string PassBy(Player p) { string result = string.Empty; if (p == null) { return result; } if (this.PropertyType == Zoning.MotherEarth && this.SalaryOver > 0) { p.Deposit(this.SalaryOver); result = "Earned $" + this.SalaryOver.ToString() + " salary!" + Environment.NewLine; } return result; }
/// <summary> /// The entry point of the program, where the program control starts and ends. /// Initializes the game, preferably from an XML file, and goes into the main /// loop. /// </summary> /// <param name="args">The command-line arguments.</param> public static void Main(string[] args) { var gamecfg = new XmlDocument(); Game g; string playerName = string.Empty; foreach (string arg in args) { if (arg.ToLower(System.Globalization.CultureInfo.CurrentCulture).EndsWith(".xml", StringComparison.CurrentCulture)) { gamecfg.Load(arg); break; } } if (gamecfg != null) { g = new Game(gamecfg); } else { g = new Game(); for (int i = 0; i < 40; i++) { var l = new Location( Zoning.Residential, "Property " + (i + 1).ToString(), 0, 0, 0, 0, 100, 10); g.Add(l); } } if (g.PlayerCount < 2) { Console.WriteLine("Input player names, empty line when done:"); while (true) { playerName = Console.ReadLine(); if (string.IsNullOrWhiteSpace(playerName)) { break; } var p = new Player(playerName); p.Where = g.Board[0]; g.Add(p); } } Player player = g.Who(); while (g.Continue) { Func<Player, string, string> question = null; Location landing = g.Where(); string answer = string.Empty; Console.WriteLine("* " + player.ToString()); if (player.InJail) { Console.WriteLine(player.Name + " is in jail!"); } answer = g.Roll(); Console.Write(answer); landing = g.Where(); Console.WriteLine("Lands on " + landing.Name); Console.WriteLine(landing.PrintOnLanding(player, ref question)); answer = string.Empty; while (question != null && string.IsNullOrWhiteSpace(answer)) { answer = Console.ReadLine(); answer = question(player, answer); Console.WriteLine(answer); } if (player.Balance < 0) { Console.WriteLine(player.Name + " has gone bankrupt!"); } player = g.NextPlayer(); } Player winner = g.Who(); Console.WriteLine(winner.Name + " wins with $" + winner.Balance.ToString()); }