private void _BuildRounds(int numRounds, int numPlayer, int playersPerRound) { // What we want is that every player sung the same amount of songs // So we keep track how many songs each palyer sung List <int> numSung = new List <int>(numPlayer); for (int i = 0; i < numPlayer; i++) { numSung.Add(0); } List <CRound> combinations = new List <CRound>(); // Posibly add more rounds than requested if the song count per player is unequal for (int i = 0; i < numRounds * 10; i++) { if (combinations.Count == 0) { _AddCombinations(numPlayer, playersPerRound, combinations); } List <int> playersInRound = _GetPlayersForRound(numSung); CRound curRound = _GetMatchingCombination(playersInRound, numSung, combinations); foreach (int player in curRound.Players) { numSung[player]++; } _Rounds.Add(curRound); combinations.Remove(curRound); //Stop if we have enough rounds and all players sung the same amount of songs if (_Rounds.Count >= numRounds && numSung.All(ct => ct == numSung[0])) { break; } } }
private static CRound _GetMatchingCombination(List <int> playersInRound, List <int> numSung, List <CRound> combinations) { foreach (CRound round in combinations) { int matching = round.Players.Count(playersInRound.Contains); // A valid round contains only players from playersInRound or all players from playersInRound (and some others) if (matching == round.Players.Count || matching == playersInRound.Count) { return(round); } } // It may happen, that there are only players that already sung against each other. So create a 2nd best option with the most number of players that should sing in it int maxMatching = combinations.Max(c => c.Players.Count(playersInRound.Contains)); List <CRound> nextOptions = combinations.Where(c => c.Players.Count(playersInRound.Contains) == maxMatching).ToList(); // And select the combination that minimizes the sum of the number of songs sung (--> favor rounds with players that sung less than others) CRound result = null; int minSung = int.MaxValue; foreach (CRound round in nextOptions) { int curNumSung = round.Players.Sum(pl => numSung[pl]); if (curNumSung < minSung) { minSung = curNumSung; result = round; } } Debug.Assert(result != null); return(result); }
private void _SetNumJokers() { int[] jokers = new int[GameData.NumPlayerAtOnce]; if (GameData.RefillJokers) { for (int i = 0; i < jokers.Length; i++) { jokers[i] = GameData.NumJokers; } } else { if (GameData.Jokers == null) { GameData.Jokers = new int[GameData.NumPlayer]; for (int i = 0; i < GameData.ProfileIDs.Count; i++) { GameData.Jokers[i] = GameData.NumJokers; } } CRound round = GameData.Rounds[GameData.CurrentRoundNr - 1]; for (int i = 0; i < GameData.NumPlayerAtOnce; i++) { jokers[i] = GameData.Jokers[round.Players[i]]; } } _ScreenSongOptions.Selection.NumJokers = jokers; }
private void _SetTeamNames() { if (GameData.NumPlayerAtOnce < 1 || GameData.ProfileIDs.Count < GameData.NumPlayerAtOnce) { _ScreenSongOptions.Selection.TeamNames = new string[] { "foo", "bar" }; return; } _ScreenSongOptions.Selection.TeamNames = new string[GameData.NumPlayerAtOnce]; CRound c = GameData.Rounds[GameData.CurrentRoundNr - 1]; for (int i = 0; i < GameData.NumPlayerAtOnce; i++) { _ScreenSongOptions.Selection.TeamNames[i] = CBase.Profiles.GetPlayerName(GameData.ProfileIDs[c.Players[i]]); } }
/// <summary> /// Prepare next game and fill song queue based on configuration and given songs. /// </summary> /// <param name="songIDs">Array of SongIDs that are selected</param> /// <returns>false, if something can't setup correctly</returns> private bool _PrepareRound(int[] songIDs) { //Reset game CBase.Game.Reset(); CBase.Game.ClearSongs(); #region PlayerNames CBase.Game.SetNumPlayer(GameData.NumPlayerAtOnce); SPlayer[] players = CBase.Game.GetPlayers(); if (players == null || players.Length < GameData.NumPlayerAtOnce) { return(false); } //Get current round CRound c = GameData.Rounds[GameData.CurrentRoundNr - 1]; for (int i = 0; i < GameData.NumPlayerAtOnce; i++) { //try to fill with correct player data if (c != null) { players[i].ProfileID = GameData.ProfileIDs[c.Players[i]]; } else { players[i].ProfileID = Guid.Empty; } } #endregion PlayerNames #region SongQueue //Add all songs with configure game mode to song queue for (int i = 0; i < songIDs.Length; i++) { CBase.Game.AddSong(songIDs[i], GameData.GameMode); } #endregion SongQueue return(true); }
public override void JokerUsed(int teamNr) { if (_ScreenSongOptions.Selection.NumJokers == null) { return; } if (teamNr >= _ScreenSongOptions.Selection.NumJokers.Length) { return; } if (!GameData.RefillJokers) { CRound round = GameData.Rounds[GameData.CurrentRoundNr - 1]; GameData.Jokers[round.Players[teamNr]]--; } _ScreenSongOptions.Selection.NumJokers[teamNr]--; _ScreenSongOptions.Selection.RandomOnly = true; _ScreenSongOptions.Selection.CategoryChangeAllowed = false; }
public override void SongSelected(int songID) { const EGameMode gm = EGameMode.TR_GAMEMODE_NORMAL; CBase.Game.Reset(); CBase.Game.ClearSongs(); CBase.Game.AddSong(songID, gm); CBase.Game.SetNumPlayer(GameData.NumPlayerAtOnce); SPlayer[] players = CBase.Game.GetPlayers(); if (players == null) { return; } if (players.Length < GameData.NumPlayerAtOnce) { return; } CRound c = GameData.Rounds[GameData.CurrentRoundNr - 1]; for (int i = 0; i < GameData.NumPlayerAtOnce; i++) { //try to fill with the right data if (c != null) { players[i].ProfileID = GameData.ProfileIDs[c.Players[i]]; } else { players[i].ProfileID = -1; } } CBase.Graphics.FadeTo(EScreen.Sing); }