// District movement private void InitMoveToNextDistrict() { CurElectionDistrictIndex++; // Clear graph and highlight from last district if (CurrentDistrictResult != null) { CurrentDistrictResult.District.Region.SetAnimatedHighlight(false); } Game.UI.Parliament.CurrentElectionGraph.ClearGraph(); Game.UI.Parliament.ModifierSliderContainer.ClearContainer(); if (CurElectionDistrictIndex < DistrictOrder.Count) { // Update current result CurrentDistrictResult = DistrictOrder[CurElectionDistrictIndex].GetLatestElectionResult(); CurrentDistrictResult.District.Region.SetAnimatedHighlight(true); TempSeats[CurrentDistrictResult.Winner] += CurrentDistrictResult.Seats; // Prepare graph for next district if (CurrentDistrictResult.District.ElectionResults.Count > 1) { Game.UI.Parliament.CurrentElectionMarginText.gameObject.SetActive(true); Game.UI.Parliament.LastElectionWinnerKnob.gameObject.SetActive(true); float margin = CurrentDistrictResult.District.GetLatestElectionResult(offset: 1).GetMargin(Game.LocalPlayerParty); Game.UI.Parliament.CurrentElectionMarginText.text = (margin > 0 ? "+" : "") + margin.ToString("0.0") + " %"; Game.UI.Parliament.LastElectionWinnerKnob.color = CurrentDistrictResult.Winner.Color; } else { Game.UI.Parliament.CurrentElectionMarginText.gameObject.SetActive(false); Game.UI.Parliament.LastElectionWinnerKnob.gameObject.SetActive(false); } List <GraphDataPoint> dataPoints = new List <GraphDataPoint>(); foreach (KeyValuePair <Party, float> kvp in CurrentDistrictResult.VoteShare) { dataPoints.Add(new GraphDataPoint(kvp.Key.Acronym, kvp.Value, kvp.Key.Color)); } int yMax = (((int)CurrentDistrictResult.VoteShare.Values.Max(x => x)) / 9 + 1) * 10; // Update current election graph Game.UI.Parliament.CurrentElectionContainer.SetActive(true); Game.UI.Parliament.CurrentElectionTitle.text = CurrentDistrictResult.District.Name; Game.UI.Parliament.CurrentElectionSeatsText.text = CurrentDistrictResult.Seats.ToString(); Game.UI.Parliament.CurrentElectionSeatsIcon.gameObject.SetActive(true); Game.UI.Parliament.CurrentElectionGraph.InitAnimatedBarGraph(dataPoints, yMax, 10, 0.1f, Color.white, Color.grey, Game.UI.Font, GraphAnimationTime, startAnimation: false); Game.CameraHandler.MoveToFocusDistricts(new List <District>() { CurrentDistrictResult.District }, DistrictPanTime, OnCameraMoveToNextDistrictDone); State = AnimationState.MoveToNextDistrict; } else { State = AnimationState.InitEndAnimation; } }
private void DisplayGraph(bool fullRefesh = true) { DistrictElectionResult result = ElectionResults[CurrentIndex]; YearText.text = result.Year.ToString(); if (result != null) { List <GraphDataPoint> dataPoints = new List <GraphDataPoint>(); foreach (KeyValuePair <Party, float> kvp in result.VoteShare) { List <Sprite> modifierIcons = new List <Sprite>(); List <string> iconTooltipTitles = new List <string>(); List <string> iconTooltipTexts = new List <string>(); foreach (Modifier m in result.Modifiers.Where(x => x.Party == kvp.Key)) { modifierIcons.Add(IconManager.Singleton.GetModifierIcon(m.Type)); iconTooltipTitles.Add(m.Type.ToString()); iconTooltipTexts.Add(m.Description + "\n\nSource: " + m.Source); } string label = GlobalSettings.DebugMode ? kvp.Key.Acronym + " / " + result.PartyPoints[kvp.Key] : kvp.Key.Acronym; // Show party points when in debug mode dataPoints.Add(new GraphDataPoint(label, kvp.Value, kvp.Key.Color, modifierIcons, iconTooltipTitles, iconTooltipTexts)); } int yMax = (((int)result.VoteShare.Values.Max(x => x)) / 9 + 1) * 10; if (fullRefesh) { ElectionGraph.InitAnimatedBarGraph(dataPoints, yMax, 10, 0.1f, Color.white, Color.grey, PrefabManager.Singleton.GraphFont, 0.25f, startAnimation: true); } else { ElectionGraph.UpdateAnimatedBarGraph(dataPoints, yMax, 0.25f); } } }
/// <summary> /// This is a client-side function, a seed ensures that the outcome is the same for all clients. /// Concludes the preparation phase when all players are ready and handles everything that happens: /// - AI actions /// - Locking player actions /// - Election result /// - Updating party values (seats, total seats, etc.) /// - Handling district effects /// - Starting next election cycle /// </summary> /// <param name="seed">Seed is used to synchronize in multiplayer</param> public void ConcludePreparationPhase(int seed) { UnityEngine.Random.InitState(seed); // Change state if (State != GameState.PreparationPhase) { return; } State = GameState.Election; // AI policies foreach (Party p in Parties.Where(p => !p.IsHuman)) { p.AI.DistributePolicyPoints(); } // Lock policies foreach (Party party in Parties) { foreach (Policy policy in party.Policies) { policy.LockValue(); } } // Reset seats foreach (Party p in Parties) { p.Seats = 0; } // Create and apply election result List <DistrictElectionResult> districtResults = new List <DistrictElectionResult>(); foreach (District district in VisibleDistricts.Values) { DistrictElectionResult districtResult = district.RunElection(Parties); districtResults.Add(districtResult); } GeneralElectionResult electionResult = new GeneralElectionResult(ElectionCycle, Year, districtResults); electionResult.Apply(this); // District effects foreach (District d in VisibleDistricts.Values) { d.OnElectionEnd(); } // Handle next election start StartNextElectionCycle(); ElectionAnimationHandler.StartAnimation(electionResult); }
/// <summary> /// This function calculates the election results of an election between the given parties. /// A specified amount of single voters will vote, whereas their vote will be decided by weighted random based on party points. /// Each party has x base points. On top of that points are added for policies that match the district traits, modifiers and mentality. /// There will always be a single winner party. /// This function only returns a result, but does not yet add it to the district/game. To add it call AddElectionResult(). /// </summary> public DistrictElectionResult RunElection(List <Party> parties) { // Get party popularities Dictionary <Party, float> voterShares = new Dictionary <Party, float>(); Dictionary <Party, int> partyPoints = new Dictionary <Party, int>(); Dictionary <Party, int> partyVotes = new Dictionary <Party, int>(); foreach (Party p in parties) { partyPoints.Add(p, GetPartyPopularity(p)); partyVotes.Add(p, 0); } // Add modifiers to result List <Modifier> electionModifiers = new List <Modifier>(); // Copy is created so that the modifiers in the election result don't get changed later foreach (Modifier m in Modifiers) { electionModifiers.Add(m); } // Exclude parties with exclusion modifiers foreach (Modifier m in Modifiers.Where(x => x.Type == ModifierType.Exclusion)) { partyPoints[m.Party] = 0; } // Cast "calculation" votes for (int i = 0; i < Voters; i++) { Party votedParty = GetSingleVoterResult(partyPoints); partyVotes[votedParty]++; } foreach (Party p in parties) { //Debug.Log(p.Name + " got " + partyVotes[p] + " votes."); voterShares.Add(p, 100f * partyVotes[p] / Voters); } // Guarantee that there is only one winner List <Party> winnerParties = voterShares.Where(x => x.Value == voterShares.Values.Max(v => v)).Select(x => x.Key).ToList(); if (winnerParties.Count > 1) { Party singleWinnerParty = winnerParties[Random.Range(0, winnerParties.Count)]; voterShares[singleWinnerParty] += 0.1f; } Party winner = voterShares.First(x => x.Value == voterShares.Max(y => y.Value)).Key; // Calculate number of "game" votes based on voter turnout foreach (Party p in parties) { partyVotes[p] = (int)((Population * VoterTurnout) * voterShares[p] / 100f); } // Create result DistrictElectionResult result = new DistrictElectionResult ( Game.ElectionCycle, Game.Year, Seats, this, partyPoints, partyVotes, voterShares, winner, electionModifiers ); return(result); }