1 /* 2 * Copyright (C) 2007-2011 Jordi Mas i Hernàndez <jmas@softcatala.org> 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public 15 * License along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 using System; 19 using System.Linq; 20 using System.Collections.Generic; 21 22 namespace gbrainy.Core.Main 23 { 24 // Manages a list of games to played within a session based on difficulty, game types and other parameters 25 public class GameSessionPlayList 26 { 27 IEnumerator <int> enumerator; 28 List <int> play_list; // Play list for the Selected difficulty, game types 29 GameDifficulty difficulty; 30 bool color_blind; 31 bool dirty; 32 GameSession.Types game_type; 33 GameManager manager; 34 GameSessionPlayList(GameManager manager)35 public GameSessionPlayList (GameManager manager) 36 { 37 this.manager = manager; 38 play_list = new List <int> (); 39 game_type = GameSession.Types.AllGames; 40 difficulty = GameDifficulty.Medium; 41 RandomOrder = true; 42 dirty = true; 43 } 44 45 public bool ColorBlind { 46 get { return color_blind;} 47 set { 48 if (color_blind == value) 49 return; 50 51 color_blind = value; 52 dirty = true; 53 } 54 } 55 56 public GameDifficulty Difficulty { 57 set { 58 if (difficulty == value) 59 return; 60 61 difficulty = value; 62 dirty = true; 63 } 64 get { return difficulty; } 65 } 66 67 public GameManager GameManager { 68 get { return manager;} 69 set { 70 if (manager == value) 71 return; 72 73 manager = value; 74 dirty = true; 75 } 76 } 77 78 public GameSession.Types GameType { 79 get {return game_type; } 80 set { 81 if (game_type == value) 82 return; 83 84 game_type = value; 85 dirty = true; 86 } 87 } 88 89 // Indicates if the PlayList for CustomGames is delivered in RandomOrder 90 public bool RandomOrder { get; set; } 91 92 // Establish the PlayList (the indices of the array to available games) 93 public int [] PlayList { 94 get { return play_list.ToArray ();} 95 set { 96 play_list = new List <int> (value); 97 dirty = false; 98 UpdateEnumerator (); 99 } 100 } 101 BuildListIfIsDirty()102 void BuildListIfIsDirty () 103 { 104 if (dirty == false) 105 return; 106 107 if ((game_type & GameSession.Types.Custom) != GameSession.Types.Custom) 108 BuildPlayList (manager.AvailableGames); 109 110 dirty = false; 111 } 112 113 // Taking a GameLocator list builds the play_list BuildPlayList(GameLocator [] all_games)114 void BuildPlayList (GameLocator [] all_games) 115 { 116 if ((game_type & GameSession.Types.Custom) == GameSession.Types.Custom) 117 throw new InvalidOperationException (); 118 119 ArrayListIndicesRandom indices = new ArrayListIndicesRandom (all_games.Length); 120 indices.Initialize (); 121 play_list.Clear (); 122 123 // Decide which game types are part of the list 124 bool logic, memory, calculation, verbal; 125 if ((game_type & GameSession.Types.AllGames) == GameSession.Types.AllGames) 126 { 127 logic = memory = calculation = verbal = true; 128 } 129 else 130 { 131 logic = (game_type & GameSession.Types.LogicPuzzles) == GameSession.Types.LogicPuzzles; 132 calculation = (game_type & GameSession.Types.Calculation) == GameSession.Types.Calculation; 133 memory = (game_type & GameSession.Types.Memory) == GameSession.Types.Memory; 134 verbal = (game_type & GameSession.Types.VerbalAnalogies) == GameSession.Types.VerbalAnalogies; 135 } 136 137 // Create item arrays for games types 138 List <int> logic_indices = new List <int> (); 139 List <int> calculation_indices = new List <int> (); 140 List <int> memory_indices = new List <int> (); 141 List <int> verbal_indices = new List <int> (); 142 143 if (logic) 144 logic_indices.AddRange (indices.Where (a => all_games[a].GameType == GameTypes.LogicPuzzle)); 145 146 if (memory) 147 memory_indices.AddRange (indices.Where (a => all_games[a].GameType == GameTypes.Memory)); 148 149 if (calculation) 150 calculation_indices.AddRange (indices.Where (a => all_games[a].GameType == GameTypes.Calculation)); 151 152 if (verbal) 153 verbal_indices.AddRange (indices.Where (a => all_games[a].GameType == GameTypes.VerbalAnalogy)); 154 155 CreateListWithDistributedGameTypes (logic_indices, calculation_indices, memory_indices, verbal_indices); 156 enumerator = play_list.GetEnumerator (); 157 } 158 CreateListWithDistributedGameTypes(List <int> logic_indices, List <int> calculation_indices, List <int> memory_indices, List <int> verbal_indices)159 void CreateListWithDistributedGameTypes (List <int> logic_indices, List <int> calculation_indices, List <int> memory_indices, 160 List <int> verbal_indices) 161 { 162 int total = logic_indices.Count + memory_indices.Count + calculation_indices.Count + verbal_indices.Count; 163 int pos_logic, pos_memory, pos_calculation, pos_verbal; 164 Random random = new Random (); 165 166 pos_logic = pos_memory = pos_calculation = pos_verbal = 0; 167 168 while (play_list.Count < total) 169 { 170 switch (random.Next (3)) { 171 case 0: 172 if (pos_calculation < calculation_indices.Count) play_list.Add (calculation_indices[pos_calculation++]); 173 if (pos_logic < logic_indices.Count) play_list.Add (logic_indices[pos_logic++]); 174 if (pos_memory < memory_indices.Count) play_list.Add (memory_indices[pos_memory++]); 175 if (pos_verbal < verbal_indices.Count) play_list.Add (verbal_indices[pos_verbal++]); 176 break; 177 case 1: 178 if (pos_memory < memory_indices.Count) play_list.Add (memory_indices[pos_memory++]); 179 if (pos_calculation < calculation_indices.Count) play_list.Add (calculation_indices[pos_calculation++]); 180 if (pos_verbal < verbal_indices.Count) play_list.Add (verbal_indices[pos_verbal++]); 181 if (pos_logic < logic_indices.Count) play_list.Add (logic_indices[pos_logic++]); 182 break; 183 case 2: 184 if (pos_calculation < calculation_indices.Count) play_list.Add (calculation_indices[pos_calculation++]); 185 if (pos_verbal < verbal_indices.Count) play_list.Add (verbal_indices[pos_verbal++]); 186 if (pos_memory < memory_indices.Count) play_list.Add (memory_indices[pos_memory++]); 187 if (pos_logic < logic_indices.Count) play_list.Add (logic_indices[pos_logic++]); 188 break; 189 } 190 } 191 } 192 UpdateEnumerator()193 void UpdateEnumerator () 194 { 195 if (RandomOrder == true) 196 { 197 ArrayListIndicesRandom random = new ArrayListIndicesRandom (play_list.Count); 198 random.RandomizeFromArray (play_list); 199 enumerator = random.GetEnumerator (); 200 } 201 else 202 enumerator = play_list.GetEnumerator (); 203 } 204 GetPuzzle()205 public Game GetPuzzle () 206 { 207 Game puzzle, first = null; 208 209 BuildListIfIsDirty (); 210 211 while (true) { 212 213 if (enumerator.MoveNext () == false) { // All the games have been played, restart again 214 enumerator = play_list.GetEnumerator (); 215 enumerator.MoveNext (); 216 } 217 218 puzzle = (Game) Activator.CreateInstance ((Type) manager.AvailableGames [enumerator.Current].TypeOf, true); 219 puzzle.Variant = manager.AvailableGames [enumerator.Current].Variant; 220 221 if (first != null && first.GetType () == puzzle.GetType ()) 222 break; 223 224 if (puzzle.IsPlayable == false) 225 continue; 226 227 if (ColorBlind == true && puzzle.UsesColors == true) 228 continue; 229 230 if (first == null) 231 first = puzzle; 232 233 if ((puzzle.Difficulty & difficulty) == difficulty) 234 break; 235 } 236 237 puzzle.CurrentDifficulty = Difficulty; 238 return puzzle; 239 } 240 } 241 } 242