private void GenerateMonsters() { Mouse.OverrideCursor = Cursors.Wait; int minTotalMonsterXP = 0; int maxTotalMonsterXP = 0; foreach (EncounterCharacterModel character in _encounterCharacters) { int baseThreshold = _statService.BaseXPThresholds[1]; if (_statService.BaseXPThresholds.ContainsKey(character.Level)) { baseThreshold = _statService.BaseXPThresholds[character.Level]; } if (_selectedDifficultyOption.Key == EncounterChallenge.Easy) { maxTotalMonsterXP += (2 * baseThreshold); } else if (_selectedDifficultyOption.Key == EncounterChallenge.Medium) { minTotalMonsterXP += (2 * baseThreshold); maxTotalMonsterXP += (3 * baseThreshold); } else if (_selectedDifficultyOption.Key == EncounterChallenge.Hard) { minTotalMonsterXP += (3 * baseThreshold); maxTotalMonsterXP += (4 * baseThreshold); } else if (_selectedDifficultyOption.Key == EncounterChallenge.Deadly) { minTotalMonsterXP += (4 * baseThreshold); maxTotalMonsterXP += (5 * baseThreshold); } else if (_selectedDifficultyOption.Key == EncounterChallenge.TPK) { minTotalMonsterXP += (5 * baseThreshold); maxTotalMonsterXP += (20 * baseThreshold); } } int attempts = 0; List <EncounterMonsterModel> monsters = new List <EncounterMonsterModel>(); while (attempts++ < 50) { int totalMonsterXP = 0; int totalMonsters = 0; int adjustedTotalMonsterXP = 0; string selectedEnvironment = _selectedEnvironmentOption.Key != null?_selectedEnvironmentOption.Key.ToLower() : null; foreach (MonsterModel monsterModel in _compendium.Monsters.OrderBy(x => Guid.NewGuid())) { if (selectedEnvironment == null || (monsterModel.Environment != null && monsterModel.Environment.ToLower().Contains(selectedEnvironment))) { int maxMonsterXP = Math.Min(maxTotalMonsterXP / _minMonsters, maxTotalMonsterXP - adjustedTotalMonsterXP); if (maxMonsterXP < 25 || totalMonsters >= _maxMonsters || adjustedTotalMonsterXP > minTotalMonsterXP) { break; } int monsterXP = _statService.GetMonsterXP(monsterModel); if (monsterXP > 0 && monsterXP <= maxMonsterXP) { EncounterMonsterModel encounterMonsterModel = new EncounterMonsterModel(); encounterMonsterModel.MonsterModel = monsterModel; int maxQuantity = 0; int potentialAdjust = (int)(_statService.GetXPMultiplier(totalMonsters + 1) * (float)(totalMonsterXP + monsterXP)); while (potentialAdjust < maxTotalMonsterXP) { potentialAdjust = (int)(_statService.GetXPMultiplier(totalMonsters + ++maxQuantity + 1) * (float)(totalMonsterXP + (monsterXP * (maxQuantity + 1)))); } maxQuantity = Math.Min(maxQuantity, _maxMonsters - monsters.Count); if (maxQuantity > 0) { encounterMonsterModel.Quantity = new Random((int)DateTime.Now.Ticks).Next(1, maxQuantity); monsters.Add(encounterMonsterModel); totalMonsters += encounterMonsterModel.Quantity; totalMonsterXP += (monsterXP * encounterMonsterModel.Quantity); adjustedTotalMonsterXP = (int)(_statService.GetXPMultiplier(totalMonsters) * (float)totalMonsterXP); } } } } if (_statService.EstimateEncounterChallenge(_encounterCharacters, monsters) == _selectedDifficultyOption.Key) { break; } else { monsters.Clear(); } } Mouse.OverrideCursor = null; if (monsters.Count > 0) { _monsters.Clear(); foreach (EncounterMonsterModel encounterMonster in monsters.OrderBy(x => x.Name)) { _monsters.Add(new EncounterMonsterViewModel(encounterMonster)); } } else { _dialogService.ShowConfirmationDialog("Encounter Creation Failed", "Unable to generate an encounter using the selected criteria.", "OK", null, null); } }