void RebuildActionItems()
        {
            ActionScroll.Children.Clear();
            List <RoundAction> actions = HumanPlayer.PossibleActions();
            ActionItemControl  c;

            // If the player has hit the top 50, provide the "Retire" option
            if (HumanPlayer.BestRank <= 50)
            {
                c = new ActionItemControl();
                c.BindAction(RetireAction);
                c.ActionClicked += ActionClicked;
                ActionScroll.Children.Add(c);
            }

            foreach (RoundAction action in actions)
            {
                c = new ActionItemControl();
                c.BindAction(action);
                c.ActionClicked += ActionClicked;
                ActionScroll.Children.Add(c);
            }

            // Add a special action at the end of the list to end the quarter and advance the game.
            c = new ActionItemControl();
            EndRoundAction.CostString = GameFormat.FormatTime(HumanPlayer.ThisRound.TimeRemaining);
            c.BindAction(EndRoundAction);
            c.ActionClicked += ActionClicked;
            ActionScroll.Children.Add(c);
        }
 public static string DefaultRiskString(GamePlayer Player, GameAction Action)
 {
     if (Action.RiskPercent == 0)
     {
         return(null);
     }
     return(GameFormat.FormatPercent(Action.RiskPercent));
 }
        void RebuildStatus()
        {
            // Top status area
            LabelName.Content           = HumanPlayer.Name;
            LabelPlayerPosition.Content = $"(#{HumanPlayer.Values.Rank})"; // Todo: compute
            LabelAge.Content            = string.Format("Age: {0}", (int)Math.Floor(HumanPlayer.Age));
            LabelTime.Content           = string.Format("Q{0} {1}", GameEngine.Quarter, GameEngine.CurrentYear);
            LabelMoney.Content          = GameFormat.FormatMoney(HumanPlayer.ThisRound.Money);
            double moneyPercent = 0;

            if (HumanPlayer.Values.Money != 0)
            {
                moneyPercent = (double)HumanPlayer.ThisRound.Money / HumanPlayer.Values.Money - 1;
            }
            LabelMoneyChange.Content    = string.Format("({0})", GameFormat.FormatPercent(moneyPercent));
            LabelMoneyChange.Foreground = moneyPercent < 0 ? Brushes.DarkRed : Brushes.DarkGreen;

            LabelFans.Content = GameFormat.FormatFans(HumanPlayer.ThisRound.FanCount);
            double fanPercent = 0;

            if (HumanPlayer.Values.FanCount != 0)
            {
                fanPercent = (double)HumanPlayer.ThisRound.FanCount / HumanPlayer.Values.FanCount - 1;
            }
            LabelFansChange.Content    = string.Format("({0})", GameFormat.FormatPercent(fanPercent));
            LabelFansChange.Foreground = fanPercent < 0 ? Brushes.DarkRed : Brushes.DarkGreen;

            // Side panel status
            LabelTimeRemaining.Content = string.Format("Time Remaining ({0})", GameFormat.FormatTime(HumanPlayer.ThisRound.TimeRemaining));
            double TimeRemainingPercent = HumanPlayer.ThisRound.TimeRemaining / 90.0;

            BarTimeRemaining.SetPercent(TimeRemainingPercent, TimeRemainingPercent, false);

            double sentimentPercent = HumanPlayer.AffinityAsPercent(HumanPlayer.ThisRound.PublicSentiment);

            LabelPublicSentiment.Content = string.Format("Public Sentiment ({0})", GameFormat.FormatPercent(sentimentPercent));
            BarPublicSentiment.SetPercent(sentimentPercent, sentimentPercent, true);

            double affinityProfessional = HumanPlayer.AffinityAsPercent(HumanPlayer.ThisRound.AffinityProfessional);

            LabelProfessionalAffinity.Content = string.Format("Professional Affinity ({0})", GameFormat.FormatPercent(affinityProfessional));
            BarProfessionalAffinity.SetPercent(affinityProfessional, affinityProfessional, false);

            double affinityMedia = HumanPlayer.AffinityAsPercent(HumanPlayer.ThisRound.AffinityMedia);

            LabelMediaAffinity.Content = string.Format("Media Affinity ({0})", GameFormat.FormatPercent(affinityMedia));
            BarMediaAffinity.SetPercent(affinityMedia, affinityMedia, false);

            double affinitySocial = HumanPlayer.AffinityAsPercent(HumanPlayer.ThisRound.AffinitySocial);

            LabelSocialAffinity.Content = string.Format("Social Affinity ({0})", GameFormat.FormatPercent(affinitySocial));
            BarSocialAffinity.SetPercent(affinitySocial, affinitySocial, false);

            double affinityCriminal = HumanPlayer.AffinityAsPercent(HumanPlayer.ThisRound.AffinityCriminal);

            LabelCriminalAffinity.Content = string.Format("Criminal Affinity ({0})", GameFormat.FormatPercent(affinityCriminal));
            BarCriminalAffinity.SetPercent(affinityCriminal, affinityCriminal, false);
        }
        // Crminal handling
        public void ApplyFine(long fineAmount, string fineReason)
        {
            string outcome = string.Format("You were fined {0}", GameFormat.FormatMoney(fineAmount));

            ThisRound.Money -= fineAmount;

            FineCount++;
            FineTotal += fineAmount;

            SetResult("Failed: " + outcome, false);
            QueueNews(fineReason, outcome, true, MediaEventType.Criminal);
        }
        public static string DefaultCostString(GamePlayer Player, GameAction Action)
        {
            List <string> stringParts = new List <string>();

            if (Action.MoneyCost > 0)
            {
                stringParts.Add(GameFormat.FormatMoney(Action.MoneyCost));
            }
            if (Action.TimeCost != 0)
            {
                stringParts.Add(GameFormat.FormatTime(Action.TimeCost) + (Action.NumQuarters > 1 ? $" for {Action.NumQuarters} Quarters" : ""));
            }
            if (stringParts.Count == 0)
            {
                return(null);
            }
            return(string.Join(", ", stringParts));
        }
        internal void BindPlayer(GamePlayer gamePlayer)
        {
            Player = gamePlayer;

            LabelName.Content = Player.Name;
            LabelRank.Content = Player.Values.Rank;
            int dRank = Player.Values.Rank - Player.LastRound.Rank;

            if (dRank == 0)
            {
                LabelArrow.Content    = "="; // circle in webdings
                LabelArrow.Foreground = Brushes.DarkGoldenrod;
            }
            else if (dRank < 0)
            {
                LabelArrow.Content    = "5"; // Up arrow
                LabelArrow.Foreground = Brushes.DarkGreen;
            }
            else
            {
                LabelArrow.Content    = "6"; // Down arrow
                LabelArrow.Foreground = Brushes.DarkRed;
            }

            string description = "Age: " + (int)Math.Floor(Player.Age);

            if (Player.Dead)
            {
                description = $"Deceased";
            }

            LabelDescription.Content = description;

            LabelFans.Content  = GameFormat.FormatFans(Player.Values.FanCount);
            LabelMoney.Content = GameFormat.FormatMoney(Player.Values.Money);
        }
        internal void BindPlayer(GamePlayer p)
        {
            StackDetails.Children.Clear();
            if (p.Dead)
            {
                LabelHeading.Content = "You Died";
                StackDetails.Children.Add(new Label()
                {
                    Content = p.DeadHowDied
                });
                StackDetails.Children.Add(new Label()
                {
                    Content = p.DeadContext
                });
                if (p.Retired)
                {
                    StackDetails.Children.Add(new Label()
                    {
                        Content = "(It's a shame, as they were just about to retire.)"
                    });
                }
            }
            else if (p.Retired)
            {
                LabelHeading.Content = "Game Over";
                string location = "from the industry";
                if (p.InJail)
                {
                    location = "in a jail cell";
                }
                StackDetails.Children.Add(new Label()
                {
                    Content = $"{p.Name} Retired {location} at the age of {Math.Floor(p.Age)}"
                });
            }

            StackDetails.Children.Add(new Label()
            {
                Content = $"Final Money: {GameFormat.FormatMoney(p.Values.Money)}"
            });
            StackDetails.Children.Add(new Label()
            {
                Content = $"Final Fans: {GameFormat.FormatFans(p.Values.FanCount)}"
            });
            StackDetails.Children.Add(new Label()
            {
                Content = $"Final Rank: #{p.Values.Rank}"
            });
            double workPercent = 0;

            if (p.TotalDays > 0)
            {
                workPercent = (double)p.WorkedDays / p.TotalDays;
            }
            StackDetails.Children.Add(new Label()
            {
                Content = $"Productivity: Worked {p.WorkedDays} / {p.TotalDays} days ({workPercent*100:n2}%)"
            });

            if (p.FineCount > 0)
            {
                string s = p.FineCount == 1 ? "" : "s";
                StackDetails.Children.Add(new Label()
                {
                    Content = $"Fined {p.FineCount} time{s} for a total of {GameFormat.FormatMoney(p.FineTotal)}"
                });
            }

            if (p.JailCount > 0)
            {
                string s  = p.JailCount == 1 ? "" : "s";
                string s2 = p.JailQuarters == 1 ? "" : "s";
                StackDetails.Children.Add(new Label()
                {
                    Content = $"Jailed {p.JailCount} time{s} for a total of {p.JailQuarters} Quarter{s2}"
                });
            }
        }
        public List <RoundAction> PossibleActions()
        {
            List <RoundAction> actions = new List <RoundAction>();

            if (Dead)
            {
                return(actions);
            }

            // Add cancel actions for any partial projects. Number these options as -1, -2, -3... for tracking.
            int index = 1;

            foreach (PartialProject p in PartialProjects)
            {
                if (p.JailTime)
                {
                    string     action_s     = p.QuartersRemaining == 1 ? "" : "s";
                    GameAction cancelAction = new GameAction()
                    {
                        Title        = $"In Jail",
                        Description  = $"You're stuck here for another {p.QuartersRemaining} Quarter{action_s}",
                        CostString   = (Player, Action) => null,
                        CommitAction = (Player, Action, Media) => { }
                    };
                    actions.Add(new RoundAction(this, cancelAction, -index));
                    return(actions); // There can be no other actions in jail.
                }
                else
                {
                    string action_s  = p.QuartersRemaining == 1 ? "" : "s";
                    string remaining = $"{p.QuartersRemaining} Quarter{action_s} remaining. ";
                    if (p.QuartersRemaining == 1)
                    {
                        remaining = "Completes this quarter. ";
                    }
                    GameAction cancelAction = new GameAction()
                    {
                        Title         = $"Cancel '{p.Project.Title}'",
                        Description   = remaining + "Recover your time but lose all investment.",
                        TimeCost      = -p.Project.TimeCost,
                        CancelTaskFor = p,
                        CostString    = (Player, Action) => null,
                        BenefitString = (Player, Action) => $"Recover {GameFormat.FormatTime(p.Project.TimeCost)}",
                        CommitAction  = (Player, Action, Media) =>
                        {
                            GameAction.DeductCost(Player, Action, Media); // Adds back the time because of TimeCost field manipulation above
                                                                          // Also remove this project from the partial project list
                            Player.PartialProjects.Remove(Action.CancelTaskFor);
                        }
                    };
                    actions.Add(new RoundAction(this, cancelAction, -index));
                }
                index++;
            }

            for (int i = 0; i < EngineData.Actions.Length; i++)
            {
                GameAction a = EngineData.Actions[i];
                if (a.CanUseAction(this, a, null))
                {
                    actions.Add(new RoundAction(this, a, i));
                }
            }
            return(actions);
        }
 public override string ToString()
 {
     return($"GamePlayer('{Name}',{Math.Floor(Age)}/{Math.Floor(LifeExpectancy)}, #{Values.Rank}, {GameFormat.FormatMoney(Values.Money)}, {GameFormat.FormatFans(Values.FanCount)}");
 }