Пример #1
0
        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);
                }
            }
        }
Пример #2
0
        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);
            }
        }