static bool Prefix(BombGenerator __instance, BombFace selectedFace, BombComponent bombComponentPrefab, GeneratorSetting settings) { var bomb = __instance.GetValue <Bomb>("bomb"); var type = bombComponentPrefab.ComponentType; // Let the timer component spawn normally and record the bomb's information. if (type == ComponentTypeEnum.Timer) { allBombInfo.Add(bomb, new BombInfo(settings, selectedFace, __instance.GetValue <Random>("rand"))); void logCallback(string condition, string _, LogType __) { if (!condition.StartsWith("[BombGenerator] Bomb component list: ")) { return; } // Replace the Random object with a fake one, so that we can make the consistent RNG calls later. __instance.SetValue("rand", new FakeRandom()); Application.logMessageReceived -= logCallback; } Application.logMessageReceived += logCallback; return(true); } // If we don't have information about a bomb, just let it go through. if (!allBombInfo.TryGetValue(bomb, out BombInfo bombInfo)) { return(true); } // Once we're ready to instantiate the components, this allows us to call the original method again. if (bombInfo.EnableOriginal) { return(true); } // If the generator is trying to fill the bomb with empty components, clear the valid faces to skip over it. if (type == ComponentTypeEnum.Empty) { __instance.GetValue <List <BombFace> >("validBombFaces").Clear(); return(false); } // Start loading any fake modules. if (bombComponentPrefab.GetComponent <FakeModule>() != null) { __instance.StartCoroutine(LoadModule(bombComponentPrefab, bombInfo)); } else { bombInfo.Components.Add(bombComponentPrefab); } return(false); }
public void GeneratorThrowsExceptionWhenMapIsTooSmallForAllBombs(int bombsAmount, int width, int height) { BombGenerator bombGenerator = new BombGenerator(); Map map = GenerateEmptyMap(width, height, bombsAmount); Exception ex = Assert.Throws <Exception>(() => bombGenerator.GenerateBombs(map)); Assert.NotNull(ex); }
public void GeneratorGeneratesExaclyAsManyBombsAsRequested(int bombsAmount, int width, int height) { BombGenerator bombGenerator = new BombGenerator(); Map map = GenerateEmptyMap(width, height, bombsAmount); Map generatedMap = bombGenerator.GenerateBombs(map); Assert.Equal(bombsAmount, HowManyBombsDoesMapHave(generatedMap)); }
public void GeneratorDoesNotGenerateBombsWhichAreSurroundedByOtherBombs() { int bombsAmount = 8, width = 3, height = 3; BombGenerator bombGenerator = new BombGenerator(); Map map = GenerateEmptyMap(width, height, bombsAmount); for (int i = 0; i < 2; i++) { Map generatedMap = bombGenerator.GenerateBombs(map); Assert.False(IsAnyBombSurroundedByOtherBombs(generatedMap)); } }
private MineField(int zoneSize, int numberOfBombs) { if (numberOfBombs <= 0) { throw new NoBombException(); } if (numberOfBombs >= zoneSize * zoneSize) { throw new TooManyBombsException(); } BombCount = numberOfBombs; ZoneSize = zoneSize; _cells = new ICell[zoneSize, zoneSize]; GenerateGameCells(); PutBombs(); ScanNumberOfBombsAroundEmptyCells(); void GenerateGameCells() { for (var row = 0; row < zoneSize; row++) { for (var column = 0; column < zoneSize; column++) { _cells[row, column] = new UndiscoveredCell(row, column); } } } void PutBombs() { var generator = new BombGenerator(numberOfBombs); do { _cells.OfType <UndiscoveredCell>() .Where(a => !a.HasBomb) .ForEach(a => a.HasBomb = generator.Put()); } while (generator.BombNumber > 0); } void ScanNumberOfBombsAroundEmptyCells() { _cells.OfType <UndiscoveredCell>() .Where(a => a.HasBomb) .SelectMany(CellsAround) .ForEach(u => ((UndiscoveredCell)u).NumberOfBombsAround++); } }
public bool NewBomb(int modules) { if (BombInProgress) { return(false); } else { CurrentBomb = BombGenerator.Generate(modules); Debug.LogFormat("[Game] Starting new bomb with {0} modules...", modules); BombInProgress = true; return(true); } }
static bool Prefix(BombGenerator __instance, BombFace selectedFace, BombComponent bombComponentPrefab, GeneratorSetting settings) { var bomb = __instance.GetValue <Bomb>("bomb"); var type = bombComponentPrefab.ComponentType; // Let the timer component spawn normally and record the bomb's information. if (type == ComponentTypeEnum.Timer) { allBombInfo.Add(bomb, new BombInfo(settings, selectedFace, __instance.GetValue <Random>("rand"))); return(true); } // If we don't have information about a bomb, just let it go through. if (!allBombInfo.TryGetValue(bomb, out BombInfo bombInfo)) { return(true); } // Once we're ready to instantiate the components, this allows us to call the original method again. if (bombInfo.EnableOriginal) { return(true); } // If the generator is trying to fill the bomb with empty components, clear the valid faces to skip over it. if (type == ComponentTypeEnum.Empty) { __instance.GetValue <List <BombFace> >("validBombFaces").Clear(); return(false); } // Start loading any fake modules. if (bombComponentPrefab.GetComponent <FakeModule>() != null) { __instance.StartCoroutine(LoadModule(bombComponentPrefab, bombInfo)); } else { bombInfo.Components.Add(bombComponentPrefab); } return(false); }
void Start() { if (instance == null) { instance = this; } else if (instance != this) { Destroy(gameObject); } restartPoint = new Vector3(0f, -1.688f, 0f); bombGenerator = GameObject.Find("Generator").GetComponent <BombGenerator> (); scoreText = GameObject.Find("Score Text"); scoreText.SetActive(false); finalScore = GameObject.Find("Final Score"); finalScore.SetActive(false); gameOver = false; gamesPlayed = PlayerPrefs.GetInt("GamesPlayed"); totalScore = PlayerPrefs.GetInt("TotalScore"); bestScore = PlayerPrefs.GetInt("BestScore"); CheckUnlockedCharacters(); }
static void HandleCaseGeneration() { Tweaks.FixRNGSeed(); BombGenerator bombGenerator = Object.FindObjectOfType <BombGenerator>(); if (bombGenerator.BombPrefabOverride == null) // No point in doing anything if they aren't even going to use the ObjectPool. { ObjectPool prefabPool = bombGenerator.BombPrefabPool; // Generate a case parent if (CaseParent != null) { Object.Destroy(CaseParent); } // We have to parent the case to a GameObject that isn't active so it doesn't appear in the scene but itself is still active. CaseParent = new GameObject(); CaseParent.SetActive(false); // Override any KMGameCommands foreach (KMGameCommands gameCommands in Object.FindObjectsOfType <KMGameCommands>()) { var previousDelegate = gameCommands.OnCreateBomb; gameCommands.OnCreateBomb = (string missionId, KMGeneratorSetting generatorSettings, GameObject spawnTarget, string seed) => { HandleGeneratorSetting(ModMission.CreateGeneratorSettingsFromMod(generatorSettings), prefabPool); return(previousDelegate(missionId, generatorSettings, spawnTarget, seed)); }; } // This must happen regardless of even BetterCasePicker is enabled so that the game can't try to spawn the fake case. prefabPool.Objects = prefabPool.Objects.Where(gameobject => gameobject.name != "TweaksCaseGenerator").ToList(); if (!Tweaks.settings.BetterCasePicker && !Tweaks.CaseGeneratorSettingCache) { return; } // Try to figure out what mission we are going into Mission mission = null; if (!string.IsNullOrEmpty(GameplayState.MissionToLoad)) { if (GameplayState.MissionToLoad.Equals(FreeplayMissionGenerator.FREEPLAY_MISSION_ID)) { mission = FreeplayMissionGenerator.Generate(GameplayState.FreeplaySettings); } else if (GameplayState.MissionToLoad.Equals(ModMission.CUSTOM_MISSION_ID)) { mission = GameplayState.CustomMission; } else { mission = MissionManager.Instance.GetMission(GameplayState.MissionToLoad); } } if (mission == null) { Debug.LogError("[BetterCasePicker] Unable to find the current mission"); return; } HandleGeneratorSetting(mission.GeneratorSetting, prefabPool); } }
public static void HandleCaseGeneration() { // The game sets the seed to 33 for some reason, so we have to set the seed so it doesn't pick the same values every time. Random.InitState((int)System.DateTime.Now.Ticks); BombGenerator bombGenerator = Object.FindObjectOfType <BombGenerator>(); if (bombGenerator.BombPrefabOverride == null) // No point in doing anything if they aren't even going to use the ObjectPool. { ObjectPool prefabPool = bombGenerator.BombPrefabPool; // This must happen regardless of even BetterCasePicker is enabled so that the game can't try to spawn the fake case. prefabPool.Objects = prefabPool.Objects.Where(gameobject => gameobject.name != "TweaksCaseGenerator").ToList(); if (!Tweaks.settings.BetterCasePicker && !Tweaks.CaseGeneratorSettingCache) { return; } // Try to figure out what mission we are going into Mission mission = null; if (!string.IsNullOrEmpty(GameplayState.MissionToLoad)) { if (GameplayState.MissionToLoad.Equals(FreeplayMissionGenerator.FREEPLAY_MISSION_ID)) { mission = FreeplayMissionGenerator.Generate(GameplayState.FreeplaySettings); } else if (GameplayState.MissionToLoad.Equals(ModMission.CUSTOM_MISSION_ID)) { mission = GameplayState.CustomMission; } else { mission = MissionManager.Instance.GetMission(GameplayState.MissionToLoad); } } if (mission == null) { Debug.LogError("[BetterCasePicker] Unable to find the current mission"); return; } bool frontFaceOnly = mission.GeneratorSetting.FrontFaceOnly; int componentCount = mission.GeneratorSetting.ComponentPools.Where(pool => pool.ModTypes == null || pool.ModTypes.Count == 0 || !(pool.ModTypes.Contains("Factory Mode") || pool.ModTypes[0].StartsWith("Multiple Bombs"))).Sum(pool => pool.Count) + 1; Dictionary <GameObject, int> bombcases = prefabPool.Objects .Where(gameobject => gameobject.GetComponent <KMBomb>() != null) .ToDictionary(gameobject => gameobject, gameobject => { if (!frontFaceOnly) { return(gameobject.GetComponent <KMBomb>().Faces.Select(face => face.Anchors.Count).Sum()); } else { return(gameobject.GetComponent <KMBomb>().Faces[0].Anchors.Count); } }); bombcases.Add(prefabPool.Default, !frontFaceOnly ? 12 : 6); // Generate a case using Case Generator if (Tweaks.CaseGeneratorSettingCache) { List <Vector2> caseSizes = new List <Vector2>(); for (int x = 1; x <= componentCount; x++) { for (int y = 1; y <= componentCount; y++) { if (x >= y) { caseSizes.Add(new Vector2(x, y)); } } } var caseSize = caseSizes .Where(size => size.y / size.x >= 0.5f && size.x * size.y * (frontFaceOnly ? 1 : 2) >= componentCount) .OrderBy(size => System.Math.Abs(size.x * size.y * (frontFaceOnly ? 1 : 2) - componentCount)) .ThenByDescending(size => size.y / size.x) .FirstOrDefault(); if (caseSize != default(Vector2)) { if (CaseParent != null) { Object.Destroy(CaseParent); } // We have to parent the case to a GameObject that isn't active so it doesn't appear in the scene but itself is still active. CaseParent = new GameObject(); CaseParent.SetActive(false); var caseGameObject = BombCaseGenerator.GenerateCase(caseSize); caseGameObject.transform.parent = CaseParent.transform; bombcases.Add(caseGameObject, (int)(caseSize.x * caseSize.y * (frontFaceOnly ? 1 : 2))); } } if (bombcases.Count == 0) { Debug.LogError("[BetterCasePicker] Unable to find any bomb cases to use"); return; } var validBombCases = bombcases.Where(pair => pair.Value >= componentCount); var minBombCases = !validBombCases.Any() ? bombcases.Where(pair => pair.Value == bombcases.Max(pair2 => pair2.Value)) : validBombCases.Where(pair => pair.Value == validBombCases.Min(pair2 => pair2.Value)); prefabPool.Objects = minBombCases.Select(x => x.Key).ToList(); } }
void Start() { GetComponent <KMGameInfo>().OnStateChange += delegate(KMGameInfo.State state) { if (state == KMGameInfo.State.Gameplay) { BombGenerator bombGenerator = FindObjectOfType <BombGenerator>(); if (bombGenerator.BombPrefabOverride == null) // No point in doing anything if they aren't even going to use the ObjectPool. { GameplayState gameplayState = SceneManager.Instance.GameplayState; Mission mission = null; if (!string.IsNullOrEmpty(GameplayState.MissionToLoad)) { if (GameplayState.MissionToLoad.Equals(FreeplayMissionGenerator.FREEPLAY_MISSION_ID)) { mission = FreeplayMissionGenerator.Generate(GameplayState.FreeplaySettings); } else if (GameplayState.MissionToLoad.Equals(ModMission.CUSTOM_MISSION_ID)) { mission = GameplayState.CustomMission; } else { mission = MissionManager.Instance.GetMission(GameplayState.MissionToLoad); } } if (mission == null) { LogError("Unable to find mission."); return; } bool frontFaceOnly = mission.GeneratorSetting.FrontFaceOnly; int componentCount = mission.GeneratorSetting.ComponentPools.Where(pool => pool.ModTypes == null || !(pool.ModTypes.Contains("Factory Mode") || pool.ModTypes.Contains("Multiple Bombs"))).Sum(pool => pool.Count) + 1; ObjectPool prefabPool = bombGenerator.BombPrefabPool; Dictionary <GameObject, int> bombcases = prefabPool.Objects .Where(gameobject => gameobject.GetComponent <KMBomb>() != null) .ToDictionary(gameobject => gameobject, gameobject => { if (!frontFaceOnly) { return(gameobject.GetComponent <KMBomb>().Faces.Select(face => face.Anchors.Count).Sum()); } else { return(gameobject.GetComponent <KMBomb>().Faces[0].Anchors.Count); } }); bombcases.Add(prefabPool.Default, !frontFaceOnly ? 12 : 6); if (bombcases.Count == 0) { LogError("Unable to find any bomb cases to use."); return; } var validBombCases = bombcases.Where(pair => pair.Value >= componentCount); var minBombCases = validBombCases.Count() == 0 ? bombcases.Where(pair => pair.Value == bombcases.Max(pair2 => pair2.Value)) : validBombCases.Where(pair => pair.Value == validBombCases.Min(pair2 => pair2.Value)); prefabPool.Objects = minBombCases.Select(x => x.Key).ToList(); } } }; }
// attach bomb generator, call from bomb generator. public void setBombGenerator(BombGenerator bg) { this.bg = bg; }