public static Instruction[,] GetRules(int ruleSeed) { var random = new MonoRandom(ruleSeed); var weights = new WeightMap <Instruction, string>(i => i.Key); var rules = new Instruction[NumStages, 4]; for (int i = 0; i < NumStages; ++i) { for (int j = 0; j < 4; ++j) { var digit = random.Next(1, 5); var stage = random.Next(1, i + 1); var instructions = new List <Instruction>() { Instruction.Position1, Instruction.Position2, Instruction.Position3, Instruction.Position4, Instruction.PressDigit(digit) }; if (i > 0) { var instruction = i % 2 == 0 ? Instruction.PressLabelFromStage(stage) : Instruction.PressPositionFromStage(stage); if (i > 2) { weights.SetWeight(instruction, 1); } instructions.Add(instruction); } var instruction2 = weights.Roll(instructions, random); rules[i, j] = instruction2; } } return(rules); }
void OnEnable() { weightMap = (WeightMap <T>)target; //Debug.Log(weightMap.WeightMap.Keys.Count + ", " + weightMap.WeightMap.Values.Count); setValues(); if (names == null) { names = weightMap.Map.Keys.Select(o => o.ToString()).ToArray(); } }
public static Rule[][] GetRules(int ruleSeed) { if (ruleSeed == 1) { return(new[] { // 3 wires new[] { new Rule(new[] { NoColourWire.GetCondition(Colour.Red) }, new Instruction(CutWire1)), new Rule(new[] { LastWireIsColour.GetCondition(Colour.White) }, new Instruction(CutWireLast)), new Rule(new[] { MoreThanOneColourWire.GetCondition(Colour.Blue) }, new Instruction(CutWireColourLast, Colour.Blue)), new Rule(new Instruction(CutWireLast)) }, // 4 wires new[] { new Rule(new[] { MoreThanOneColourWire.GetCondition(Colour.Red), Condition <Colour[]> .SerialNumberIsOdd() }, new Instruction(CutWireColourLast, Colour.Red)), new Rule(new[] { LastWireIsColour.GetCondition(Colour.Yellow), NoColourWire.GetCondition(Colour.Red) }, new Instruction(CutWire0)), new Rule(new[] { ExactlyOneColourWire.GetCondition(Colour.Blue) }, new Instruction(CutWire0)), new Rule(new[] { MoreThanOneColourWire.GetCondition(Colour.Yellow) }, new Instruction(CutWireLast)), new Rule(new Instruction(CutWire1)) }, // 5 wires new[] { new Rule(new[] { LastWireIsColour.GetCondition(Colour.Black), Condition <Colour[]> .SerialNumberIsOdd() }, new Instruction(CutWire3)), new Rule(new[] { ExactlyOneColourWire.GetCondition(Colour.Red), MoreThanOneColourWire.GetCondition(Colour.Yellow) }, new Instruction(CutWire0)), new Rule(new[] { NoColourWire.GetCondition(Colour.Black) }, new Instruction(CutWire1)), new Rule(new Instruction(CutWire0)) }, // 6 wires new[] { new Rule(new[] { NoColourWire.GetCondition(Colour.Yellow), Condition <Colour[]> .SerialNumberIsOdd() }, new Instruction(CutWire2)), new Rule(new[] { ExactlyOneColourWire.GetCondition(Colour.Yellow), MoreThanOneColourWire.GetCondition(Colour.White) }, new Instruction(CutWire3)), new Rule(new[] { NoColourWire.GetCondition(Colour.Red) }, new Instruction(CutWireLast)), new Rule(new Instruction(CutWire3)) } }); } var random = new MonoRandom(ruleSeed); var ruleSets = new Rule[4][]; for (int i = 3; i <= 6; ++i) { ConditionType[][] list; var conditionWeights = new WeightMap <ConditionType, string>(c => c.Key); var instructionWeights = new WeightMap <InstructionType, string>(s => s.Key); var list2 = new List <Rule>(); if (ruleSeed == 1) { list = new[] { new[] { new ConditionType(Condition <Colour[]> .SerialNumberStartsWithLetter()), new ConditionType(Condition <Colour[]> .SerialNumberIsOdd()) }, new[] { ExactlyOneColourWire, NoColourWire, LastWireIsColour, MoreThanOneColourWire } } } ; else { list = new[] { new[] { new ConditionType(Condition <Colour[]> .SerialNumberStartsWithLetter()), new ConditionType(Condition <Colour[]> .SerialNumberIsOdd()) }, new[] { ExactlyOneColourWire, NoColourWire, LastWireIsColour, MoreThanOneColourWire }, new[] { new ConditionType(Condition <Colour[]> .PortExactKey(PortType.DviD)), new ConditionType(Condition <Colour[]> .PortExactKey(PortType.PS2)), new ConditionType(Condition <Colour[]> .PortExactKey(PortType.RJ45)), new ConditionType(Condition <Colour[]> .PortExactKey(PortType.StereoRCA)), new ConditionType(Condition <Colour[]> .PortExactKey(PortType.Parallel)), new ConditionType(Condition <Colour[]> .PortExactKey(PortType.Serial)), new ConditionType(Condition <Colour[]> .EmptyPortPlate()) } } }; var rules = new Rule[random.NextDouble() < 0.6 ? 3 : 4]; ruleSets[i - 3] = rules; for (int j = 0; j < rules.Length; ++j) { var colours = new List <Colour>(WiresSolver.colours); var list3 = new List <Colour>(); var conditions = new Condition <Colour[]> [random.NextDouble() < 0.6 ? 1: 2]; var num = i - 1; for (int k = 0; k < conditions.Length; ++k) { var possibleQueryableProperties = GetPossibleConditions(list, num, k > 0); #if TRACE if (System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Trace.WriteLine("queryWeights:"); foreach (var entry in conditionWeights) { System.Diagnostics.Trace.WriteLine($" -- {entry.Key} = {entry.Value}"); } } #endif var conditionType = conditionWeights.Roll(possibleQueryableProperties, random, 0.1f); if (conditionType.UsesColour) { num -= conditionType.WiresInvolved; var i4 = random.Next(0, colours.Count); var colour = colours[i4]; colours.RemoveAt(i4); if (conditionType.ColourAvailableForSolution) { list3.Add(colour); } conditions[k] = conditionType.GetCondition(colour); } else { conditions[k] = conditionType.GetCondition(0); } } var instructions = GetPossibleInstructions(i, conditions); Instruction solution; var instructionType = instructionWeights.Roll(instructions, random); if (list3.Count > 0) { solution = new Instruction(instructionType, list3[random.Next(0, list3.Count)]); } else { solution = new Instruction(instructionType); } var rule = new Rule(conditions, solution); if (ruleSeed == 1 || rule.IsValid) { list2.Add(rule); } else { --j; } } Utils.StableSort(list2, r => - r.Queries.Length); var list4 = GetPossibleInstructions(i, null); if (ruleSeed != 1) { // Remove redundant rules. var forbiddenId = list2[list2.Count - 1].Solution.Type.Key; list4.RemoveAll(l => l.Key == forbiddenId); } list2.Add(new Rule(new Instruction(random.Pick(list4), null))); ruleSets[i - 3] = list2.ToArray(); } return(ruleSets); }
private static HeldRule CreateHeldRule(Colour?colour, WeightMap <HeldSolution, string> weights, Random random) { return(new HeldRule(colour, weights.Roll(GetHeldSolutions(), random))); }
private static InitialRule CreateInitialRule(List <Condition <ButtonData> > conditions, WeightMap <InitialSolution, InitialSolution> weights, Random random) { return(new InitialRule(conditions, weights.Roll(GetInitialSolutions(true), random))); }
public static RuleSet GetRules(int ruleSeed) { if (ruleSeed == 1) { return(new RuleSet( new[] { new InitialRule(new List <Condition <ButtonData> >() { ButtonColour(Colour.Blue), ButtonLabel(Label.Abort) }, InitialSolution.Hold), new InitialRule(new List <Condition <ButtonData> >() { Condition <ButtonData> .MoreThanNBatteries(1), ButtonLabel(Label.Detonate) }, InitialSolution.Tap), new InitialRule(new List <Condition <ButtonData> >() { ButtonColour(Colour.White), Condition <ButtonData> .IndicatorLit("CAR") }, InitialSolution.Hold), new InitialRule(new List <Condition <ButtonData> >() { Condition <ButtonData> .MoreThanNBatteries(2), Condition <ButtonData> .IndicatorLit("FRK") }, InitialSolution.Tap), new InitialRule(new List <Condition <ButtonData> >() { ButtonColour(Colour.Yellow) }, InitialSolution.Hold), new InitialRule(new List <Condition <ButtonData> >() { ButtonColour(Colour.Red), ButtonLabel(Label.Hold) }, InitialSolution.Tap), new InitialRule(InitialSolution.Hold) }, new[] { new HeldRule(Colour.Blue, new HeldSolution(HeldSolutionType.ReleaseOnTimerDigit, 4)), new HeldRule(Colour.White, new HeldSolution(HeldSolutionType.ReleaseOnTimerDigit, 1)), new HeldRule(Colour.Yellow, new HeldSolution(HeldSolutionType.ReleaseOnTimerDigit, 5)), new HeldRule(null, new HeldSolution(HeldSolutionType.ReleaseOnTimerDigit, 1)), } )); } var random = new MonoRandom(ruleSeed); var conditionWeights = new WeightMap <Condition <ButtonData>, string>(c => c.Key); var initialInstructionWeights = new WeightMap <InitialSolution, InitialSolution>(s => s); initialInstructionWeights.SetWeight(InitialSolution.Tap, 0.1f); initialInstructionWeights.SetWeight(InitialSolution.TapWhenSecondsMatch, 0.05f); var heldInstructionWeights = new WeightMap <HeldSolution, string>(s => s.Key); // Build condition lists. var PrimaryConditions = new List <Condition <ButtonData> >() { ButtonColour(Colour.Red), ButtonColour(Colour.Blue), ButtonColour(Colour.Yellow), ButtonColour(Colour.White), Condition <ButtonData> .MoreThanNBatteries(1), Condition <ButtonData> .MoreThanNBatteries(2) }; var IndicatorColorConditions = new List <Colour?>() { Colour.Red, Colour.Blue, Colour.Yellow, Colour.White }; var SecondaryConditions = new List <Condition <ButtonData> >() { ButtonLabel(Label.Press), ButtonLabel(Label.Hold), ButtonLabel(Label.Abort), ButtonLabel(Label.Detonate) }; for (int i = 0; i < 3; ++i) { SecondaryConditions.Add(Condition <ButtonData> .IndicatorLit(random.Pick(Utils.IndicatorLabels))); } var ports = new List <PortType>() { PortType.DviD, PortType.PS2, PortType.RJ45, PortType.StereoRCA, PortType.Parallel, PortType.Serial }; for (int i = 0; i < 3; ++i) { var port = Utils.RemoveRandom(ports, random); SecondaryConditions.Add(Condition <ButtonData> .Port(port)); } foreach (var port in ports) { PrimaryConditions.Add(Condition <ButtonData> .Port(port)); } PrimaryConditions.Add(Condition <ButtonData> .EmptyPortPlate()); SecondaryConditions.Add(Condition <ButtonData> .SerialNumberStartsWithLetter()); SecondaryConditions.Add(Condition <ButtonData> .SerialNumberIsOdd()); // Generate initial rules. var initialRules = new List <InitialRule>(); while (initialRules.Count < MaxInitialRules && PrimaryConditions.Count > 0) { var query = Utils.RemoveRandom(PrimaryConditions, random); if (random.Next(2) == 0) { initialRules.Add(CreateInitialRule(new List <Condition <ButtonData> >() { query }, initialInstructionWeights, random)); } else { initialRules.Add(CreateInitialRule(new List <Condition <ButtonData> >() { query, Utils.RemoveRandom(SecondaryConditions, random) }, initialInstructionWeights, random)); } } initialRules.Add(new InitialRule(InitialSolution.Hold)); // Generate held rules. var heldRules = new List <HeldRule>(); while (heldRules.Count < MaxHeldRules && IndicatorColorConditions.Count > 0) { var condition = Utils.RemoveRandom(IndicatorColorConditions, random); heldRules.Add(CreateHeldRule(condition, heldInstructionWeights, random)); } heldRules.Add(CreateHeldRule(null, heldInstructionWeights, random)); // Remove redundant rules. RemoveRedundantRules(initialRules, initialInstructionWeights, random, PrimaryConditions, SecondaryConditions); return(new RuleSet(initialRules.ToArray(), heldRules.ToArray())); }
private static void RemoveRedundantRules(List <InitialRule> rules, WeightMap <InitialSolution, InitialSolution> weights, Random random, List <Condition <ButtonData> > PrimaryQueryList, List <Condition <ButtonData> > SecondaryQueryList) { // Since the last rule always has the instruction 'hold the button', // force the second-last one to have a different instruction. if (rules[rules.Count - 2].Solution == InitialSolution.Hold) { rules[rules.Count - 2] = new InitialRule(rules[rules.Count - 2].Conditions, weights.Roll(GetInitialSolutions(false), random)); } var twobattery = -1; var onebattery = -1; InitialSolution?solution = null; var samesolution = true; for (var i = rules.Count - 1; i >= 0; i--) { var condition = rules[i].Conditions.FirstOrDefault(c => c.Key == nameof(Condition <ButtonData> .MoreThanNBatteries)); if (condition != null) { if (condition.Text.Contains("2")) { twobattery = i; if (onebattery > -1) { samesolution &= rules[i].Solution == solution; break; } solution = rules[i].Solution; } else if (condition.Text.Contains("1")) { onebattery = i; if (twobattery > -1) { samesolution &= rules[i].Solution == solution; break; } solution = rules[i].Solution; } } if (solution.HasValue) { samesolution &= rules[i].Solution == solution; } } if (onebattery == -1 || twobattery == -1) { return; } if (onebattery < twobattery && rules[onebattery].Conditions.Count == 1) { // We have a 'if there is more than 1 battery' rule above a 'if there are more than 2 batteries' rules. if (random.Next(2) == 0) { rules[onebattery].Conditions.Add(Utils.RemoveRandom(SecondaryQueryList, random)); } else { rules[onebattery].Conditions[0] = Utils.RemoveRandom(PrimaryQueryList, random); } } else if (rules[onebattery].Conditions.Count == 1 && rules[twobattery].Conditions.Count == 1 && samesolution) { // We have a 'if there is more than 1 battery' rule below a 'if there are more than 2 batteries' rules, // and every rule in between has the same instruction. switch (random.Next(7)) { //Add a secondary query to one or both of the battery rules case 0: rules[onebattery].Conditions.Add(Utils.RemoveRandom(SecondaryQueryList, random)); break; case 1: rules[twobattery].Conditions.Add(Utils.RemoveRandom(SecondaryQueryList, random)); break; case 2: rules[twobattery].Conditions.Add(Utils.RemoveRandom(SecondaryQueryList, random)); goto case 0; //Replace one or both of the battery rules with a new primary query case 3: rules[onebattery].Conditions[0] = Utils.RemoveRandom(PrimaryQueryList, random); break; case 4: rules[twobattery].Conditions[0] = Utils.RemoveRandom(PrimaryQueryList, random); break; case 5: rules[twobattery].Conditions[0] = Utils.RemoveRandom(PrimaryQueryList, random); goto case 3; //Replace one of the solutions in between the minimum and maximum battery. default: var replacementsolution = rules[onebattery].Solution == InitialSolution.Tap ? InitialSolution.Hold : InitialSolution.Tap; if (Math.Abs(onebattery - twobattery) == 1) { rules[Math.Min(onebattery, twobattery)].Solution = replacementsolution; } else { rules[random.Next(Math.Min(onebattery, twobattery), Math.Max(onebattery, twobattery))].Solution = replacementsolution; } break; } } }