private void CreateMateriaOrdering() { if (!MateriaChoices.Any()) { return; } // collect all equip slots and assign canonical order var equipSlots = GearChoices.SelectMany(e => e.EquipSlotCategory.PossibleSlots) .DistinctBy(s => s.Name) .OrderBy(s => s.Name) .ToList(); for (var i = 0; i < equipSlots.Count; i++) { var s = equipSlots[i]; var grp = GearChoices.Where(e => e.EquipSlotCategory.PossibleSlots.Contains(s)); foreach (var e in grp) { MateriaChoices.ForEach(m => materia[s, e, m.Key].BranchingPriority = i); } } }
private void CreateMateriaModel(EquipSlot s, Equipment e) { if (!MateriaChoices.Any()) { return; } var gv = gear[s, e]; //TODO: you can probably optimize tons here Model.AddConstraint( Expression.Sum(MateriaChoices.Select(m => materia[s, e, m.Key])) <= e.TotalMateriaSlots() * gv, $"restrict total materia amount to amount permitted for {e} in {s}"); if (e.IsAdvancedMeldingPermitted) { if (MateriaChoices.Any(m => MainStats.Contains(m.Key.BaseParam.Name))) { Model.AddConstraint( Expression.Sum( MateriaChoices.Where(m => MainStats.Contains(m.Key.BaseParam.Name)) .Select(m => materia[s, e, m.Key])) <= e.FreeMateriaSlots * gv, $"restrict advanced melding for mainstat materia to amount of slots in {e} in {s}"); } if (MateriaChoices.Any(m => !m.Value)) { Model.AddConstraint( Expression.Sum( MateriaChoices.Where(m => !m.Value).Select(m => materia[s, e, m.Key])) <= (e.FreeMateriaSlots + SolverConfig.OvermeldThreshold) * gv, $"restrict regular materia amount to amount permitted for {e} in {s}"); } } // SIMPLIFICATION: ignoring whether materia fits; doesn't matter anyway foreach (var matGrp in MateriaChoices.GroupBy(m => m.Key.BaseParam)) { var bp = matGrp.Key; var remCap = e.GetMateriaMeldCap(bp, true); if (remCap == 0) { continue; } // we need to constrain against min(remaining cap, melded materia) to account for stat caps var cv = cap[s, e, bp]; Model.AddConstraint(cv <= remCap * gv, $"cap stats using {e}'s meld cap for {bp} in slot {s}"); var maxRegularMat = matGrp.MaxBy(f => f.Key.Value).Key; var maxAdvancedMat = maxRegularMat; if (e.IsAdvancedMeldingPermitted) { maxAdvancedMat = matGrp.Where(m => m.Value).MaxBy(f => f.Key.Value).Key; } // need hash-set here for uniqueness Model.AddConstraint( cv <= Expression.Sum( new HashSet <MateriaItem> { maxRegularMat, maxAdvancedMat } .Select(m => m.Value * materia[s, e, m])), $"cap stats using used {bp} for {e} in slot {s}"); StatExprs.AddExprToDict(bp, cv); } }