private void CreateGearModel()
        {
            foreach (var grp in GearChoices.GroupBy(g => g.EquipSlotCategory))
            {
                // if gear is unique, equip it once only.
                grp.Where(e => e.IsUnique)
                .ForEach(
                    e =>
                    Model.AddConstraint(Expression.Sum(grp.Key.PossibleSlots.Select(s => gear[s, e])) <= 1,
                                        $"ensure gear uniqueness for {e}"));

                // SIMPLIFICATION: we ignore blocked slots
                foreach (var s in grp.Key.PossibleSlots)
                {
                    // choose at most one gear per slot
                    Model.AddConstraint(Expression.Sum(grp.Select(e => gear[s, e])) <= 1,
                                        $"choose at most one item for slot {s}");
                    foreach (var e in grp)
                    {
                        var gv = gear[s, e];
                        // ASSUMPTION: all gear choices have fixed parameters
                        e.AllParameters.Where(p => RelevantStats.Contains(p.BaseParam))
                        .ForEach(
                            p =>
                            AddExprToDict(StatExprs, p.BaseParam,
                                          p.Values.Sum(v => ((ParameterValueFixed)v).Amount) * gv));

                        // ASSUMPTION: all meldable items have at least one materia slot
                        // ASSUMPTION: customisable relics are unmeldable
                        if (e.FreeMateriaSlots > 0)
                        {
                            CreateMateriaModel(s, e);
                        }
                        else if (RelicCaps != null && RelicCaps.ContainsKey(e))
                        {
                            CreateRelicModel(s, e);
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        private void CreateGearModel()
        {
            foreach (var grp in GearChoices.GroupBy(g => g.EquipSlotCategory))
            {
                // if gear is unique, equip it once only.
                if (grp.Key.PossibleSlots.Count() > 1)
                {
                    grp.Where(e => e.IsUnique)
                    .ForEach(
                        e =>
                        Model.AddConstraint(Expression.Sum(grp.Key.PossibleSlots.Select(s => gear[s, e])) <= 1,
                                            $"ensure gear uniqueness for {e}"));
                }

                // SIMPLIFICATION: we ignore blocked slots
                foreach (var s in grp.Key.PossibleSlots)
                {
                    // choose at most one gear per slot
                    Model.AddConstraint(Expression.Sum(grp.Select(e => gear[s, e])) <= 1,
                                        $"choose at most one item for slot {s}");
                    foreach (var e in grp)
                    {
                        var gv = gear[s, e];

                        // ASSUMPTION: all gear choices have fixed parameters
                        var stats =
                            e.AllParameters.Where(p => RelevantStats.Contains(p.BaseParam))
                            .ToDictionary(p => p.BaseParam,
                                          p => p.Values.OfType <ParameterValueFixed>().Select(val => val.Amount).Sum());

                        if (SolverConfig.EquipmentOverrides?.ContainsKey(e) ?? false)
                        {
                            var statsOverride = SolverConfig.EquipmentOverrides[e];

                            if (statsOverride == null)
                            {
                                continue;
                            }

                            foreach (var kv in statsOverride)
                            {
                                stats[kv.Key] = kv.Value;
                            }
                        }

                        // sanity check stats
                        foreach (var kv in stats)
                        {
                            if (e.GetMaximumParamValue(kv.Key) < kv.Value)
                            {
                                Console.Error.WriteLine($"{kv.Key} => {kv.Value} for {e} is out of range");
                            }
                        }

                        stats.ForEach(p => StatExprs.AddExprToDict(p.Key, p.Value * gv));

                        // ASSUMPTION: all meldable items have at least one materia slot
                        // ASSUMPTION: customisable relics are unmeldable
                        if (e.FreeMateriaSlots > 0)
                        {
                            CreateMateriaModel(s, e);
                        }
                        else
                        {
                            CreateRelicModel(s, e);
                        }
                    }
                }
            }
        }