public void EnemyHealthPack3() { ConstraintThingySolver solver = new ConstraintThingySolver(); FiniteDomain <String> finiteDomain = new FiniteDomain <string>("enemy", "health-pack") { }; FiniteDomainVariable <String> roomType = solver.CreateFiniteDomainVariable(finiteDomain, "enemy", "health-pack"); RealVariable score = solver.CreateRealVariable(0, 5); // How this reads: // Enemies will always do 3 damage to the player // Health packs arbitarily restore between 3 and 4 health // Once solved, "roomType" will hold which kind of room was selected // and "score" will hold the strength of the item or enemy // in this case, only health packs can be assigned to the interval (0,5), so "score" will // contain the strength of the health pack, which is some arbitrary number between 3 and 5. new ScoreContraint <String>(score, roomType, new ScoreMapping <string>(finiteDomain, "enemy".PairedWith(new Interval(-3, -3)), "health-pack".PairedWith(new Interval(3, 100)))); foreach (var solution in solver.Solutions.FirstElements(10)) { AssertIntersect(new Interval(3, 5), score.UniqueValue); Assert.AreEqual("health-pack", roomType.UniqueValue); } }
public void CardinalityConstraint() { ConstraintThingySolver constraintThingySolver = new ConstraintThingySolver(); FiniteDomain <String> finiteDomain = new FiniteDomain <String>("hub", "forest", "swamp", "cave", "other") { }; FiniteDomainVariable <String> a = new FiniteDomainVariable <String>(constraintThingySolver, "a", finiteDomain, "hub"); FiniteDomainVariable <String> b = new FiniteDomainVariable <String>(constraintThingySolver, "b", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String> c = new FiniteDomainVariable <String>(constraintThingySolver, "c", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String> d = new FiniteDomainVariable <String>(constraintThingySolver, "d", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String> e = new FiniteDomainVariable <String>(constraintThingySolver, "e", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String> f = new FiniteDomainVariable <String>(constraintThingySolver, "f", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String>[] vars = new[] { a, b, c, d, e, f }; Constraint.RequireOccurences("hub", 1, vars); Constraint.RequireOccurences("forest", 1, vars); Constraint.RequireOccurences("swamp", 1, vars); Constraint.RequireOccurences("cave", 1, vars); Assert.AreEqual(60, constraintThingySolver.Solutions.Count()); }
public void EqualityAndInequalityInteraction() { var constraintSolver = new ConstraintThingySolver(); var finiteDomain = new FiniteDomain <String>("red", "green", "blue") { }; var x = new FiniteDomainVariable <String>(constraintSolver, "x", finiteDomain, "red", "green", "blue"); var y = new FiniteDomainVariable <String>(constraintSolver, "y", finiteDomain, "red", "green", "blue"); var z = new FiniteDomainVariable <String>(constraintSolver, "z", finiteDomain, "red", "green", "blue"); Constraint.Equal(x, y); Constraint.NotEqual(y, z); int solutions = 0; foreach (Solution solution in constraintSolver.Solutions) { solutions++; Assert.AreEqual(x.UniqueValue, y.UniqueValue); Assert.AreNotEqual(y.UniqueValue, z.UniqueValue); Assert.AreNotEqual(x.UniqueValue, z.UniqueValue); } Assert.AreEqual(6, solutions); }
public void EnemyHealthPack5() { const int numRooms = 3; ConstraintThingySolver solver = new ConstraintThingySolver(); FiniteDomain <String> finiteDomain = new FiniteDomain <string>("enemy", "health-pack"); FiniteDomainVariable <String>[] roomTypes = new FiniteDomainVariable <string> [numRooms]; for (int i = 0; i < numRooms; i++) { roomTypes[i] = solver.CreateFiniteDomainVariable(finiteDomain, "enemy", "health-pack"); } RealVariable[] roomScores = new RealVariable[numRooms]; var scoreMapping = new ScoreMapping <String>(finiteDomain, new Interval(-3, -3), new Interval(3, 3)); for (int i = 0; i < numRooms; i++) { roomScores[i] = Constraint.ScoreVariable(roomTypes[i], scoreMapping); } var sum = Constraint.Add(roomScores); Constraint.InRange(sum, 0, 4); foreach (var solution in solver.Solutions.FirstElements(1)) { AssertIntersect(new Interval(0, 4), sum.UniqueValue); } }
public void CorrectlyMapsBetweenValues3() { ConstraintThingySolver solver = new ConstraintThingySolver(); FiniteDomain <String> numbers = new FiniteDomain <string>("one", "two", "three"); FiniteDomain <String> colors = new FiniteDomain <string>("red", "green", "blue"); Mapping <String, String> mapping = new Mapping <string, string>(numbers, colors) { { "one", "red" }, { "one", "blue" }, { "two", "green" }, { "two", "blue" }, { "three", "blue" }, { "three", "red" } }; FiniteDomainVariable <String> numberVariable = solver.CreateFiniteDomainVariable(numbers, "one", "two", "three"); FiniteDomainVariable <String> colorVariable = solver.CreateFiniteDomainVariable(colors, "red", "green", "blue"); Constraint.Mapping(numberVariable, colorVariable, mapping); int solutions = 0; foreach (Solution solution in solver.Solutions) { solutions++; } Assert.AreEqual(6, solutions); }
public void PopulationWithOccurences() { const int numRooms = 5; ConstraintThingySolver solver = new ConstraintThingySolver(); // this the finite domain variables to be expanded first -- we test without this below solver.ExpansionOrder = ExpansionOrder.Deterministic; FiniteDomain <String> finiteDomain = new FiniteDomain <string>("enemy", "health-pack", "ammo", "boss", "puzzle"); FiniteDomainVariable <String>[] roomTypes = new FiniteDomainVariable <string> [numRooms]; for (int i = 0; i < numRooms; i++) { roomTypes[i] = solver.CreateFiniteDomainVariable(finiteDomain, "enemy", "health-pack", "ammo", "boss", "puzzle"); } // exactly 1 boss in the level Constraint.RequireOccurences("boss", 1, roomTypes); // at most 1 puzzle in the level Constraint.MaximumOccurences("puzzle", 1, roomTypes); RealVariable[] roomScores = new RealVariable[numRooms]; var scoreMapping = new ScoreMapping <String>(finiteDomain, "enemy".PairedWith(new Interval(-3, -3)), "health-pack".PairedWith(new Interval(2, 2)), "ammo".PairedWith(new Interval(2, 2)), "boss".PairedWith(new Interval(-6, -6)), "puzzle".PairedWith(new Interval(0, 0))); for (int i = 0; i < numRooms; i++) { roomScores[i] = Constraint.ScoreVariable(roomTypes[i], scoreMapping); } var sum = roomScores.Aggregate((a, b) => { var result = Constraint.Add(a, b); Constraint.GreaterThanOrEqual(result, 0); return(result); }); Constraint.InRange(sum, 0, 10); foreach (var solution in solver.Solutions.FirstElements(10)) { AssertIntersect(new Interval(0, 10), sum.UniqueValue); } }
protected override void InitializeConstraintSystem(ConstraintThingySolver solver) { FiniteDomainVariable <bool>[,] grid = new FiniteDomainVariable <bool> [8, 8]; FiniteDomain <bool> finiteDomain = new FiniteDomain <bool>(true, false); List <FiniteDomainVariable <bool> > allCells = new List <FiniteDomainVariable <bool> >(); for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { grid[i, j] = new FiniteDomainVariable <bool>(solver, String.Format("{0},{1}", i, j), finiteDomain, true, false); allCells.Add(grid[i, j]); } } Constraint.RequireOccurences(true, 8, allCells.ToArray()); // column / row constraints for (int i = 0; i < 8; i++) { List <FiniteDomainVariable <bool> > row = new List <FiniteDomainVariable <bool> >(); List <FiniteDomainVariable <bool> > col = new List <FiniteDomainVariable <bool> >(); for (int j = 0; j < 8; j++) { row.Add(grid[i, j]); col.Add(grid[j, i]); } Constraint.MaximumOccurences(true, 1, row.ToArray()); Constraint.MaximumOccurences(true, 1, col.ToArray()); } int n = 8; for (int slice = 0; slice < 2 * 8 - 1; ++slice) { List <FiniteDomainVariable <bool> > diagonal1 = new List <FiniteDomainVariable <bool> >(); List <FiniteDomainVariable <bool> > diagonal2 = new List <FiniteDomainVariable <bool> >(); int z = slice < n ? 0 : slice - n + 1; for (int j = z; j <= slice - z; ++j) { diagonal1.Add(grid[j, slice - j]); diagonal2.Add(grid[j, 7 - (slice - j)]); } Constraint.MaximumOccurences(true, 1, diagonal1.ToArray()); Constraint.MaximumOccurences(true, 1, diagonal2.ToArray()); } }
protected override void InitializeConstraintSystem(ConstraintThingySolver solver) { var letters = "abcde".ToCharArray(); FiniteDomain <char> finiteDomain = new FiniteDomain <char>(letters); var a = new FiniteDomainVariable <char>(solver, "a", finiteDomain, letters); var b = new FiniteDomainVariable <char>(solver, "b", finiteDomain, letters); var c = new FiniteDomainVariable <char>(solver, "c", finiteDomain, letters); var d = new FiniteDomainVariable <char>(solver, "d", finiteDomain, letters); var e = new FiniteDomainVariable <char>(solver, "e", finiteDomain, letters); Constraint.NotEqual(a, b, c, d, e); }
private static void PlayabilityExperiment(int numRooms, int randomSeed) { ConstraintThingySolver solver = new ConstraintThingySolver(randomSeed); FiniteDomain <String> finiteDomain = new FiniteDomain <string>("enemy", "health-pack", "ammo", "boss", "puzzle"); FiniteDomainVariable <String>[] roomTypes = new FiniteDomainVariable <string> [numRooms]; for (int i = 0; i < numRooms; i++) { roomTypes[i] = solver.CreateFiniteDomainVariable(finiteDomain, "enemy", "health-pack", "ammo", "boss", "puzzle"); } // exactly 1 boss in the level Constraint.RequireOccurences("boss", 1, roomTypes); // exactly 1 puzzle in the level Constraint.RequireOccurences("puzzle", 1, roomTypes); RealVariable[] roomScores = new RealVariable[numRooms]; var scoreMapping = new ScoreMapping <String>(finiteDomain, "enemy".PairedWith(new Interval(-3, -3)), "health-pack".PairedWith(new Interval(2, 2)), "ammo".PairedWith(new Interval(2, 2)), "boss".PairedWith(new Interval(-6, -6)), "puzzle".PairedWith(new Interval(0, 0))); for (int i = 0; i < numRooms; i++) { roomScores[i] = Constraint.ScoreVariable(roomTypes[i], scoreMapping); } var sum = roomScores.Aggregate((a, b) => { var result = Constraint.Add(a, b); Constraint.GreaterThanOrEqual(result, 0); return(result); }); Constraint.InRange(sum, 0, 10); foreach (var solution in solver.Solutions.FirstElements(10)) { AssertIntersect(new Interval(0, 10), sum.UniqueValue); Assert.AreEqual(1, roomTypes.Count(room => room.UniqueValue == "puzzle")); Assert.AreEqual(1, roomTypes.Count(room => room.UniqueValue == "boss")); } }
public void CorrectlyEnumeratesLotsOfPossibleValues() { ConstraintThingySolver constraintThingySolver = new ConstraintThingySolver(); FiniteDomain <int> finiteDomain = new FiniteDomain <int>(Enumerable.Range(0, 64)) { }; FiniteDomainVariable <int> x = new FiniteDomainVariable <int>(constraintThingySolver, "x", finiteDomain, Enumerable.Range(0, 64)); FiniteDomainVariable <int> y = new FiniteDomainVariable <int>(constraintThingySolver, "y", finiteDomain, Enumerable.Range(0, 64)); FiniteDomainVariable <int> z = new FiniteDomainVariable <int>(constraintThingySolver, "z", finiteDomain, Enumerable.Range(0, 64)); Assert.AreEqual(64 * 64 * 64, constraintThingySolver.Solutions.Count()); }
protected override void InitializeConstraintSystem(ConstraintThingySolver solver) { const int numRooms = 5; FiniteDomain <string> finiteDomain = new FiniteDomain <string>("enemy", "health-pack", "ammo", "boss", "puzzle"); FiniteDomainVariable <string>[] roomTypes = new FiniteDomainVariable <string> [numRooms]; for (int i = 0; i < numRooms; i++) { roomTypes[i] = solver.CreateFiniteDomainVariable(finiteDomain, "enemy", "health-pack", "ammo", "boss", "puzzle"); } // exactly 1 boss in the level Constraint.RequireOccurences("boss", 1, roomTypes); // exactly 1 puzzle in the level Constraint.RequireOccurences("puzzle", 1, roomTypes); RealVariable[] roomScores = new RealVariable[numRooms]; var scoreMapping = new ScoreMapping <string>(finiteDomain, "enemy".PairedWith(new Interval(-3, -3)), "health-pack".PairedWith(new Interval(2, 2)), "ammo".PairedWith(new Interval(2, 2)), "boss".PairedWith(new Interval(-6, -6)), "puzzle".PairedWith(new Interval(0, 0))); for (int i = 0; i < numRooms; i++) { roomScores[i] = Constraint.ScoreVariable(roomTypes[i], scoreMapping); } var sum = roomScores.Aggregate((a, b) => { var result = Constraint.Add((RealVariable)a, b); Constraint.GreaterThanOrEqual(result, 0); return(result); }); Constraint.InRange(sum, 0, 10); }
public void ImpossiblePlayability() { const int numRooms = 5; ConstraintThingySolver solver = new ConstraintThingySolver(); FiniteDomain <String> finiteDomain = new FiniteDomain <string>("enemy", "health-pack", "ammo", "boss", "puzzle"); FiniteDomainVariable <String>[] roomTypes = new FiniteDomainVariable <string> [numRooms]; for (int i = 0; i < numRooms; i++) { roomTypes[i] = solver.CreateFiniteDomainVariable(finiteDomain, "enemy", "health-pack", "ammo", "boss", "puzzle"); } // exactly 1 boss in the level Constraint.RequireOccurences("boss", 1, roomTypes); // at most 1 puzzle in the level Constraint.MaximumOccurences("puzzle", 1, roomTypes); RealVariable[] roomScores = new RealVariable[numRooms]; var scoreMapping = new ScoreMapping <String>(finiteDomain, "enemy".PairedWith(new Interval(-3, -3)), "health-pack".PairedWith(new Interval(2, 2)), "ammo".PairedWith(new Interval(2, 2)), // make placing a boss super expensive so there's no valid solution, yet still constrained to appear "boss".PairedWith(new Interval(-600, -600)), "puzzle".PairedWith(new Interval(0, 0))); for (int i = 0; i < numRooms; i++) { roomScores[i] = Constraint.ScoreVariable(roomTypes[i], scoreMapping); } var sum = Constraint.Add(roomScores); Constraint.InRange(sum, 0, 10); Assert.AreEqual(0, solver.Solutions.Count()); }
public void EnemyHealthPack1() { ConstraintThingySolver solver = new ConstraintThingySolver(); FiniteDomain <String> finiteDomain = new FiniteDomain <string>("enemy", "health-pack"); FiniteDomainVariable <String> variable = solver.CreateFiniteDomainVariable(finiteDomain, "enemy", "health-pack"); RealVariable score = solver.CreateRealVariable(0, 5); new ScoreContraint <String>(score, variable, new ScoreMapping <string>(finiteDomain, "enemy".PairedWith(new Interval(-3, -3)), "health-pack".PairedWith(new Interval(3, 3)))); int solutionCount = 0; foreach (var solution in solver.Solutions) { solutionCount++; Assert.AreEqual(new Interval(3, 3), score.UniqueValue); Assert.AreEqual("health-pack", variable.UniqueValue); } Assert.AreEqual(1, solutionCount); }
protected override void InitializeConstraintSystem(ConstraintThingySolver solver) { FiniteDomain <String> finiteDomain = new FiniteDomain <String>("hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String> a = new FiniteDomainVariable <String>(solver, "a", finiteDomain, "hub"); FiniteDomainVariable <String> b = new FiniteDomainVariable <String>(solver, "b", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String> c = new FiniteDomainVariable <String>(solver, "c", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String> d = new FiniteDomainVariable <String>(solver, "d", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String> e = new FiniteDomainVariable <String>(solver, "e", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String> f = new FiniteDomainVariable <String>(solver, "f", finiteDomain, "hub", "forest", "swamp", "cave", "other"); FiniteDomainVariable <String>[] vars = new[] { a, b, c, d, e, f }; Constraint.RequireOccurences("hub", 1, vars); Constraint.RequireOccurences("forest", 1, vars); Constraint.RequireOccurences("swamp", 1, vars); Constraint.RequireOccurences("cave", 1, vars); }
protected internal override void UpdateVariable(FiniteDomainVariable <T> variable, out bool success) { FiniteDomainVariable <T> otherVariable = (variable == Variables[0]) ? Variables[1] : Variables[0]; variable.NarrowTo(otherVariable.AllowableValues, out success); }
protected override void InitializeConstraintSystem(ConstraintThingySolver solver) { // topology: https://docs.google.com/a/u.northwestern.edu/drawings/d/1mpZ2gPq7D8mab7PI2PtV4bKYCrrtb7ZS3hg5gwgMa_E/ // // declare all of the room types FiniteDomain <String> roomType = new FiniteDomain <string>("start", "small-ammo", "big-ammo", "small-health-pack", "big-health-pack", "zombie", "two zombies", "dog", "trap", "boss", "end"); FiniteDomainVariable <String>[] roomTypes = new FiniteDomainVariable <string> [41]; roomTypes[0] = solver.CreateFiniteDomainVariable(roomType, "start"); for (int i = 1; i <= 13; i++) { roomTypes[i] = solver.CreateFiniteDomainVariable(roomType, "small-ammo", "big-ammo", "small-health-pack", "big-health-pack", "zombie", "two zombies", "dog", "trap", "boss"); } roomTypes[14] = solver.CreateFiniteDomainVariable(roomType, "end"); for (int i = 15; i <= 40; i++) { roomTypes[i] = solver.CreateFiniteDomainVariable(roomType, "small-ammo", "big-ammo", "small-health-pack", "big-health-pack", "zombie", "two zombies", "dog", "trap", "boss"); } // assert that adjacent rooms cannot have the same content Constraint.NotEqual(roomTypes[0], roomTypes[1]); Constraint.NotEqual(roomTypes[1], roomTypes[2]); Constraint.NotEqual(roomTypes[2], roomTypes[3]); Constraint.NotEqual(roomTypes[3], roomTypes[4]); Constraint.NotEqual(roomTypes[1], roomTypes[5]); Constraint.NotEqual(roomTypes[5], roomTypes[6]); Constraint.NotEqual(roomTypes[6], roomTypes[7]); Constraint.NotEqual(roomTypes[7], roomTypes[8]); Constraint.NotEqual(roomTypes[4], roomTypes[8]); Constraint.NotEqual(roomTypes[8], roomTypes[9]); Constraint.NotEqual(roomTypes[9], roomTypes[10]); Constraint.NotEqual(roomTypes[10], roomTypes[11]); Constraint.NotEqual(roomTypes[10], roomTypes[12]); Constraint.NotEqual(roomTypes[11], roomTypes[13]); Constraint.NotEqual(roomTypes[12], roomTypes[13]); Constraint.NotEqual(roomTypes[13], roomTypes[14]); Constraint.NotEqual(roomTypes[2], roomTypes[15]); Constraint.NotEqual(roomTypes[15], roomTypes[16]); Constraint.NotEqual(roomTypes[16], roomTypes[3]); Constraint.NotEqual(roomTypes[16], roomTypes[4]); Constraint.NotEqual(roomTypes[16], roomTypes[17]); Constraint.NotEqual(roomTypes[15], roomTypes[18]); Constraint.NotEqual(roomTypes[17], roomTypes[18]); Constraint.NotEqual(roomTypes[18], roomTypes[4]); Constraint.NotEqual(roomTypes[2], roomTypes[23]); Constraint.NotEqual(roomTypes[5], roomTypes[23]); Constraint.NotEqual(roomTypes[23], roomTypes[7]); Constraint.NotEqual(roomTypes[23], roomTypes[4]); Constraint.NotEqual(roomTypes[1], roomTypes[24]); Constraint.NotEqual(roomTypes[24], roomTypes[25]); Constraint.NotEqual(roomTypes[25], roomTypes[6]); Constraint.NotEqual(roomTypes[25], roomTypes[26]); Constraint.NotEqual(roomTypes[6], roomTypes[26]); Constraint.NotEqual(roomTypes[26], roomTypes[27]); Constraint.NotEqual(roomTypes[27], roomTypes[7]); Constraint.NotEqual(roomTypes[8], roomTypes[33]); Constraint.NotEqual(roomTypes[8], roomTypes[36]); Constraint.NotEqual(roomTypes[33], roomTypes[36]); Constraint.NotEqual(roomTypes[33], roomTypes[40]); Constraint.NotEqual(roomTypes[33], roomTypes[34]); Constraint.NotEqual(roomTypes[33], roomTypes[35]); Constraint.NotEqual(roomTypes[34], roomTypes[35]); Constraint.NotEqual(roomTypes[35], roomTypes[9]); Constraint.NotEqual(roomTypes[36], roomTypes[40]); Constraint.NotEqual(roomTypes[36], roomTypes[37]); Constraint.NotEqual(roomTypes[37], roomTypes[40]); Constraint.NotEqual(roomTypes[37], roomTypes[39]); Constraint.NotEqual(roomTypes[37], roomTypes[38]); Constraint.NotEqual(roomTypes[40], roomTypes[39]); Constraint.NotEqual(roomTypes[38], roomTypes[39]); Constraint.NotEqual(roomTypes[39], roomTypes[9]); Constraint.NotEqual(roomTypes[10], roomTypes[19]); Constraint.NotEqual(roomTypes[19], roomTypes[20]); Constraint.NotEqual(roomTypes[20], roomTypes[21]); Constraint.NotEqual(roomTypes[21], roomTypes[22]); Constraint.NotEqual(roomTypes[22], roomTypes[13]); Constraint.NotEqual(roomTypes[11], roomTypes[20]); Constraint.NotEqual(roomTypes[10], roomTypes[13]); Constraint.NotEqual(roomTypes[10], roomTypes[28]); Constraint.NotEqual(roomTypes[28], roomTypes[29]); Constraint.NotEqual(roomTypes[12], roomTypes[29]); Constraint.NotEqual(roomTypes[29], roomTypes[30]); Constraint.NotEqual(roomTypes[12], roomTypes[30]); Constraint.NotEqual(roomTypes[30], roomTypes[31]); Constraint.NotEqual(roomTypes[12], roomTypes[31]); Constraint.NotEqual(roomTypes[31], roomTypes[32]); Constraint.NotEqual(roomTypes[32], roomTypes[13]); ScoreMapping <String> damages = new ScoreMapping <String>(roomType, "small-health-pack".PairedWith(new Interval(35)), "big-health-pack".PairedWith(new Interval(70)), "small-ammo".PairedWith(new Interval(0)), "big-ammo".PairedWith(new Interval(0)), "start".PairedWith(new Interval(0)), "zombie".PairedWith(new Interval(-6)), "two zombies".PairedWith(new Interval(-15)), "dog".PairedWith(new Interval(-8)), "trap".PairedWith(new Interval(-5)), "boss".PairedWith(new Interval(-30)), "end".PairedWith(new Interval(0))); // create variables to contain how much damage is dealt in each room RealVariable[] roomDelta = new RealVariable[41]; roomDelta[0] = solver.CreateRealVariable(0); roomDelta[0].RequireUnique = false; for (int i = 1; i <= 13; i++) { roomDelta[i] = Constraint.ScoreVariable(roomTypes[i], damages); roomDelta[i].RequireUnique = false; } roomDelta[14] = solver.CreateRealVariable(0); roomDelta[14].RequireUnique = false; for (int i = 15; i <= 40; i++) { roomDelta[i] = Constraint.ScoreVariable(roomTypes[i], damages); roomDelta[i].RequireUnique = false; } // variables for how much health the player has in each room // under the assumptions of forward progress in the paper RealVariable[] playerHealth = new RealVariable[41]; // start at 100 playerHealth[0] = solver.CreateRealVariable(100); playerHealth[0].RequireUnique = false; // player must always have above 0 health for (int i = 1; i <= 40; i++) { playerHealth[i] = solver.CreateRealVariable(0, 10000); playerHealth[i].RequireUnique = false; } Constraint.Sum(playerHealth[1], roomDelta[1], playerHealth[0]); Constraint.Sum(playerHealth[2], roomDelta[2], playerHealth[1]); Constraint.Sum(playerHealth[3], roomDelta[3], Constraint.Minimize(playerHealth[2], playerHealth[16]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[4], roomDelta[4], Constraint.Minimize(playerHealth[3], playerHealth[23], playerHealth[16], playerHealth[18]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[5], roomDelta[5], playerHealth[1]); Constraint.Sum(playerHealth[6], roomDelta[6], Constraint.Minimize(playerHealth[5], playerHealth[25]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[7], roomDelta[7], Constraint.Minimize(playerHealth[6], playerHealth[27]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[8], roomDelta[8], Constraint.Minimize(playerHealth[4], playerHealth[7]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[9], roomDelta[9], Constraint.Minimize(playerHealth[8], playerHealth[35], playerHealth[39]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[10], roomDelta[10], playerHealth[9]); Constraint.Sum(playerHealth[11], roomDelta[11], playerHealth[10]); Constraint.Sum(playerHealth[12], roomDelta[12], playerHealth[10]); Constraint.Sum(playerHealth[13], roomDelta[13], Constraint.Minimize(playerHealth[11], playerHealth[12], playerHealth[10], playerHealth[22], playerHealth[32]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[14], roomDelta[14], playerHealth[13]); Constraint.Sum(playerHealth[15], roomDelta[15], playerHealth[2]); Constraint.Sum(playerHealth[16], roomDelta[16], playerHealth[15]); Constraint.Sum(playerHealth[17], roomDelta[17], playerHealth[16]); Constraint.Sum(playerHealth[18], roomDelta[18], Constraint.Minimize(playerHealth[15], playerHealth[17]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[19], roomDelta[19], playerHealth[10]); Constraint.Sum(playerHealth[20], roomDelta[20], Constraint.Minimize(playerHealth[19], playerHealth[11]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[21], roomDelta[21], playerHealth[11]); Constraint.Sum(playerHealth[22], roomDelta[22], playerHealth[21]); Constraint.Sum(playerHealth[23], roomDelta[23], Constraint.Minimize(playerHealth[2], playerHealth[5]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[24], roomDelta[24], playerHealth[1]); Constraint.Sum(playerHealth[25], roomDelta[25], playerHealth[24]); Constraint.Sum(playerHealth[26], roomDelta[26], Constraint.Minimize(playerHealth[25], playerHealth[6]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[27], roomDelta[27], playerHealth[26]); Constraint.Sum(playerHealth[28], roomDelta[28], playerHealth[10]); Constraint.Sum(playerHealth[29], roomDelta[29], Constraint.Minimize(playerHealth[28], playerHealth[12]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[30], roomDelta[30], Constraint.Minimize(playerHealth[29], playerHealth[12]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[31], roomDelta[31], Constraint.Minimize(playerHealth[30], playerHealth[12]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[32], roomDelta[32], playerHealth[31]); Constraint.Sum(playerHealth[33], roomDelta[33], playerHealth[8]); Constraint.Sum(playerHealth[34], roomDelta[34], playerHealth[33]); Constraint.Sum(playerHealth[35], roomDelta[35], Constraint.Minimize(playerHealth[33], playerHealth[34]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[36], roomDelta[36], Constraint.Minimize(playerHealth[8], playerHealth[33]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[37], roomDelta[37], playerHealth[36]); Constraint.Sum(playerHealth[38], roomDelta[38], playerHealth[37]); Constraint.Sum(playerHealth[39], roomDelta[39], Constraint.Minimize(playerHealth[40], playerHealth[37], playerHealth[38]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[40], roomDelta[40], Constraint.Minimize(playerHealth[33], playerHealth[36], playerHealth[37]).With(r => r.RequireUnique = false)); ScoreMapping <String> ammoChanges = new ScoreMapping <String>(roomType, "small-health-pack".PairedWith(new Interval(0)), "big-health-pack".PairedWith(new Interval(0)), "small-ammo".PairedWith(new Interval(6)), "big-ammo".PairedWith(new Interval(12)), "start".PairedWith(new Interval(0)), "zombie".PairedWith(new Interval(-1)), "two zombies".PairedWith(new Interval(-2)), "dog".PairedWith(new Interval(-2)), "trap".PairedWith(new Interval(0)), "boss".PairedWith(new Interval(-8)), "end".PairedWith(new Interval(0))); // create variables to contain how much damage is dealt in each room RealVariable[] ammoRoomDelta = new RealVariable[41]; ammoRoomDelta[0] = solver.CreateRealVariable(0); ammoRoomDelta[0].RequireUnique = false; for (int i = 1; i <= 13; i++) { ammoRoomDelta[i] = Constraint.ScoreVariable(roomTypes[i], ammoChanges); ammoRoomDelta[i].RequireUnique = false; } ammoRoomDelta[14] = solver.CreateRealVariable(0); ammoRoomDelta[14].RequireUnique = false; for (int i = 15; i <= 40; i++) { ammoRoomDelta[i] = Constraint.ScoreVariable(roomTypes[i], ammoChanges); ammoRoomDelta[i].RequireUnique = false; } // variables for how much health the player has in each room // under the assumptions of forward progress in the paper RealVariable[] playerAmmo = new RealVariable[41]; // start at 10 playerAmmo[0] = solver.CreateRealVariable(10); playerAmmo[0].RequireUnique = false; // player must always have above 0 ammo, but can be unlimited for (int i = 1; i <= 40; i++) { playerAmmo[i] = solver.CreateRealVariable(0, 500000); playerAmmo[i].RequireUnique = false; } Constraint.Sum(playerAmmo[1], ammoRoomDelta[1], playerAmmo[0]); Constraint.Sum(playerAmmo[2], ammoRoomDelta[2], playerAmmo[1]); Constraint.Sum(playerAmmo[3], ammoRoomDelta[3], Constraint.Minimize(playerAmmo[2], playerAmmo[16]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[4], ammoRoomDelta[4], Constraint.Minimize(playerAmmo[3], playerAmmo[23], playerAmmo[16], playerAmmo[18]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[5], ammoRoomDelta[5], playerAmmo[1]); Constraint.Sum(playerAmmo[6], ammoRoomDelta[6], Constraint.Minimize(playerAmmo[5], playerAmmo[25]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[7], ammoRoomDelta[7], Constraint.Minimize(playerAmmo[6], playerAmmo[27]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[8], ammoRoomDelta[8], Constraint.Minimize(playerAmmo[4], playerAmmo[7]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[9], ammoRoomDelta[9], Constraint.Minimize(playerAmmo[8], playerAmmo[35], playerAmmo[39]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[10], ammoRoomDelta[10], playerAmmo[9]); Constraint.Sum(playerAmmo[11], ammoRoomDelta[11], playerAmmo[10]); Constraint.Sum(playerAmmo[12], ammoRoomDelta[12], playerAmmo[10]); Constraint.Sum(playerAmmo[13], ammoRoomDelta[13], Constraint.Minimize(playerAmmo[11], playerAmmo[12], playerAmmo[10], playerAmmo[22], playerAmmo[32]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[14], ammoRoomDelta[14], playerAmmo[13]); Constraint.Sum(playerAmmo[15], ammoRoomDelta[15], playerAmmo[2]); Constraint.Sum(playerAmmo[16], ammoRoomDelta[16], playerAmmo[15]); Constraint.Sum(playerAmmo[17], ammoRoomDelta[17], playerAmmo[16]); Constraint.Sum(playerAmmo[18], ammoRoomDelta[18], Constraint.Minimize(playerAmmo[15], playerAmmo[17]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[19], ammoRoomDelta[19], playerAmmo[10]); Constraint.Sum(playerAmmo[20], ammoRoomDelta[20], Constraint.Minimize(playerAmmo[19], playerAmmo[11]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[21], ammoRoomDelta[21], playerAmmo[11]); Constraint.Sum(playerAmmo[22], ammoRoomDelta[22], playerAmmo[21]); Constraint.Sum(playerAmmo[23], ammoRoomDelta[23], Constraint.Minimize(playerAmmo[2], playerAmmo[5]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[24], ammoRoomDelta[24], playerAmmo[1]); Constraint.Sum(playerAmmo[25], ammoRoomDelta[25], playerAmmo[24]); Constraint.Sum(playerAmmo[26], ammoRoomDelta[26], Constraint.Minimize(playerAmmo[25], playerAmmo[6]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[27], ammoRoomDelta[27], playerAmmo[26]); Constraint.Sum(playerAmmo[28], ammoRoomDelta[28], playerAmmo[10]); Constraint.Sum(playerAmmo[29], ammoRoomDelta[29], Constraint.Minimize(playerAmmo[28], playerAmmo[12]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[30], ammoRoomDelta[30], Constraint.Minimize(playerAmmo[29], playerAmmo[12]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[31], ammoRoomDelta[31], Constraint.Minimize(playerAmmo[30], playerAmmo[12]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[32], ammoRoomDelta[32], playerAmmo[31]); Constraint.Sum(playerAmmo[33], ammoRoomDelta[33], playerAmmo[8]); Constraint.Sum(playerAmmo[34], ammoRoomDelta[34], playerAmmo[33]); Constraint.Sum(playerAmmo[35], ammoRoomDelta[35], Constraint.Minimize(playerAmmo[33], playerAmmo[34]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[36], ammoRoomDelta[36], Constraint.Minimize(playerAmmo[8], playerAmmo[33]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[37], ammoRoomDelta[37], playerAmmo[36]); Constraint.Sum(playerAmmo[38], ammoRoomDelta[38], playerAmmo[37]); Constraint.Sum(playerAmmo[39], ammoRoomDelta[39], Constraint.Minimize(playerAmmo[40], playerAmmo[37], playerAmmo[38]).With(r => r.RequireUnique = false)); Constraint.Sum(playerAmmo[40], ammoRoomDelta[40], Constraint.Minimize(playerAmmo[33], playerAmmo[36], playerAmmo[37]).With(r => r.RequireUnique = false)); Constraint.LimitOccurences("trap", 2, 4, roomTypes); Constraint.MaximumOccurences("small-health-pack", 5, roomTypes); Constraint.MaximumOccurences("big-health-pack", 5, roomTypes); Constraint.MaximumOccurences("small-ammo", 5, roomTypes); Constraint.MaximumOccurences("big-ammo", 5, roomTypes); Constraint.RequireOccurences("boss", 1, roomTypes); }
protected override void InitializeConstraintSystem(ConstraintThingySolver solver) { // topology: https://docs.google.com/a/u.northwestern.edu/drawings/d/1mpZ2gPq7D8mab7PI2PtV4bKYCrrtb7ZS3hg5gwgMa_E/ // // declare all of the room types FiniteDomain <String> roomType = new FiniteDomain <string>("key", "locked-door", "empty"); FiniteDomainVariable <String>[] roomTypes = new FiniteDomainVariable <string> [41]; for (int i = 0; i <= 40; i++) { roomTypes[i] = solver.CreateFiniteDomainVariable(roomType, "key", "locked-door", "empty"); } /* * for (int i = 0; i <= 40; i++) * { * if (i != 1 && i != 8 && i != 9 && i != 10 && i != 13) * { * Constraint.NotEqual(roomTypes[i], "key"); * * Constraint.NotEqual(roomTypes[i], "locked-door"); * } * }*/ ScoreMapping <String> keyLockScoring = new ScoreMapping <String>(roomType, "key".PairedWith(new Interval(1)), "locked-door".PairedWith(new Interval(-1)), "empty".PairedWith(new Interval(0))); // 3 things need to happen for a key and lock puzzle. // 1) player needs to first encounter the boss // 2) player needs to then encounter the locked door // 3) player needs to finally encounter the exit // we say a boss provides a value of +2 // we say the locked door provides a value of -1 // and we say that we need to have a value of +1 at the exit // with the restriction that we never dip negative along the path integral // so that placing a locked door before a guaranteed boss would be dissallowed // we use 'min' as our aggregation function RealVariable[] lockKeyDelta = new RealVariable[41]; for (int i = 0; i <= 40; i++) { lockKeyDelta[i] = Constraint.ScoreVariable(roomTypes[i], keyLockScoring); lockKeyDelta[i].RequireUnique = false; } RealVariable[] lockKeyRunningSum = new RealVariable[41]; // require the running sum to stay positive for (int i = 0; i <= 40; i++) { lockKeyRunningSum[i] = solver.CreateRealVariable(0, 100); lockKeyRunningSum[i].RequireUnique = false; } // start at 0. Constraint.Equal(lockKeyRunningSum[0], 0); // end at 0. Constraint.InRange(lockKeyRunningSum[14], 0, 0); Constraint.Sum(lockKeyRunningSum[1], lockKeyDelta[1], lockKeyRunningSum[0]); Constraint.Sum(lockKeyRunningSum[2], lockKeyDelta[2], lockKeyRunningSum[1]); Constraint.Equal(lockKeyRunningSum[2], lockKeyRunningSum[16]); Constraint.Sum(lockKeyRunningSum[3], lockKeyDelta[3], lockKeyRunningSum[2]); Constraint.Equal(lockKeyRunningSum[3], lockKeyRunningSum[23], lockKeyRunningSum[16], lockKeyRunningSum[18]); Constraint.Sum(lockKeyRunningSum[4], lockKeyDelta[4], lockKeyRunningSum[3]); Constraint.Sum(lockKeyRunningSum[5], lockKeyDelta[5], lockKeyRunningSum[1]); Constraint.Equal(lockKeyRunningSum[5], lockKeyRunningSum[25]); Constraint.Sum(lockKeyRunningSum[6], lockKeyDelta[6], lockKeyRunningSum[5]); Constraint.Equal(lockKeyRunningSum[6], lockKeyRunningSum[27]); Constraint.Sum(lockKeyRunningSum[7], lockKeyDelta[7], lockKeyRunningSum[6]); Constraint.Equal(lockKeyRunningSum[4], lockKeyRunningSum[7]); Constraint.Sum(lockKeyRunningSum[8], lockKeyDelta[8], lockKeyRunningSum[4]); Constraint.Equal(lockKeyRunningSum[8], lockKeyRunningSum[35], lockKeyRunningSum[39]); Constraint.Sum(lockKeyRunningSum[9], lockKeyDelta[9], lockKeyRunningSum[8]); Constraint.Sum(lockKeyRunningSum[10], lockKeyDelta[10], lockKeyRunningSum[9]); Constraint.Sum(lockKeyRunningSum[11], lockKeyDelta[11], lockKeyRunningSum[10]); Constraint.Sum(lockKeyRunningSum[12], lockKeyDelta[12], lockKeyRunningSum[10]); Constraint.Equal(lockKeyRunningSum[11], lockKeyRunningSum[12], lockKeyRunningSum[10], lockKeyRunningSum[22], lockKeyRunningSum[32]); Constraint.Sum(lockKeyRunningSum[13], lockKeyDelta[13], lockKeyRunningSum[11]); Constraint.Sum(lockKeyRunningSum[14], lockKeyDelta[14], lockKeyRunningSum[13]); Constraint.Sum(lockKeyRunningSum[15], lockKeyDelta[15], lockKeyRunningSum[2]); Constraint.Sum(lockKeyRunningSum[16], lockKeyDelta[16], lockKeyRunningSum[15]); Constraint.Sum(lockKeyRunningSum[17], lockKeyDelta[17], lockKeyRunningSum[16]); Constraint.Equal(lockKeyRunningSum[15], lockKeyRunningSum[17]); Constraint.Sum(lockKeyRunningSum[18], lockKeyDelta[18], lockKeyRunningSum[15]); Constraint.Sum(lockKeyRunningSum[19], lockKeyDelta[19], lockKeyRunningSum[10]); Constraint.Equal(lockKeyRunningSum[19], lockKeyRunningSum[11]); Constraint.Sum(lockKeyRunningSum[20], lockKeyDelta[20], lockKeyRunningSum[19]); Constraint.Sum(lockKeyRunningSum[21], lockKeyDelta[21], lockKeyRunningSum[11]); Constraint.Sum(lockKeyRunningSum[22], lockKeyDelta[22], lockKeyRunningSum[21]); Constraint.Equal(lockKeyRunningSum[2], lockKeyRunningSum[5]); Constraint.Sum(lockKeyRunningSum[23], lockKeyDelta[23], lockKeyRunningSum[2]); Constraint.Sum(lockKeyRunningSum[24], lockKeyDelta[24], lockKeyRunningSum[1]); Constraint.Sum(lockKeyRunningSum[25], lockKeyDelta[25], lockKeyRunningSum[24]); Constraint.Equal(lockKeyRunningSum[25], lockKeyRunningSum[6]); Constraint.Sum(lockKeyRunningSum[26], lockKeyDelta[26], lockKeyRunningSum[25]); Constraint.Sum(lockKeyRunningSum[27], lockKeyDelta[27], lockKeyRunningSum[26]); Constraint.Sum(lockKeyRunningSum[28], lockKeyDelta[28], lockKeyRunningSum[10]); Constraint.Equal(lockKeyRunningSum[28], lockKeyRunningSum[12]); Constraint.Sum(lockKeyRunningSum[29], lockKeyDelta[29], lockKeyRunningSum[28]); Constraint.Equal(lockKeyRunningSum[29], lockKeyRunningSum[12]); Constraint.Sum(lockKeyRunningSum[30], lockKeyDelta[30], lockKeyRunningSum[29]); Constraint.Equal(lockKeyRunningSum[30], lockKeyRunningSum[12]); Constraint.Sum(lockKeyRunningSum[31], lockKeyDelta[31], lockKeyRunningSum[30]); Constraint.Sum(lockKeyRunningSum[32], lockKeyDelta[32], lockKeyRunningSum[31]); Constraint.Sum(lockKeyRunningSum[33], lockKeyDelta[33], lockKeyRunningSum[8]); Constraint.Sum(lockKeyRunningSum[34], lockKeyDelta[34], lockKeyRunningSum[33]); Constraint.Equal(lockKeyRunningSum[33], lockKeyRunningSum[34]); Constraint.Sum(lockKeyRunningSum[35], lockKeyDelta[35], lockKeyRunningSum[33]); Constraint.Minimize(lockKeyRunningSum[8], lockKeyRunningSum[33]); Constraint.Sum(lockKeyRunningSum[36], lockKeyDelta[36], lockKeyRunningSum[8]); Constraint.Sum(lockKeyRunningSum[37], lockKeyDelta[37], lockKeyRunningSum[36]); Constraint.Sum(lockKeyRunningSum[38], lockKeyDelta[38], lockKeyRunningSum[37]); Constraint.Equal(lockKeyRunningSum[40], lockKeyRunningSum[37], lockKeyRunningSum[38]); Constraint.Sum(lockKeyRunningSum[39], lockKeyDelta[39], lockKeyRunningSum[40]); Constraint.Equal(lockKeyRunningSum[33], lockKeyRunningSum[36], lockKeyRunningSum[37]); Constraint.Sum(lockKeyRunningSum[40], lockKeyDelta[40], lockKeyRunningSum[33]); // Constraint.LimitOccurences("trap", 2, 4, roomTypes); // Constraint.MaximumOccurences("small-health-pack", 5, roomTypes); //Constraint.MaximumOccurences("big-health-pack", 6, roomTypes); // Constraint.RequireOccurences("boss", 1, roomTypes); //Constraint.MaximumOccurences("key", 5, roomTypes); //Constraint.MaximumOccurences("locked-door", 5, roomTypes); }
/// <summary> /// Creates a new equality constraint /// </summary> public EqualityConstraint(FiniteDomainVariable <T> x, FiniteDomainVariable <T> y) : base(new[] { x, y }) { }
protected override void InitializeConstraintSystem(ConstraintThingySolver solver) { // topology: https://docs.google.com/a/u.northwestern.edu/drawings/d/1mpZ2gPq7D8mab7PI2PtV4bKYCrrtb7ZS3hg5gwgMa_E/ // // declare all of the room types FiniteDomain <String> roomType = new FiniteDomain <string>("start", "empty", "small-health-pack", "big-health-pack", "zombie", "two zombies", "dog", "trap", "boss", "locked-door", "end"); FiniteDomainVariable <String>[] roomTypes = new FiniteDomainVariable <string> [15]; roomTypes[0] = solver.CreateFiniteDomainVariable(roomType, "start"); for (int i = 1; i <= 13; i++) { roomTypes[i] = solver.CreateFiniteDomainVariable(roomType, "empty", "small-health-pack", "big-health-pack", "zombie", "two zombies", "dog", "trap", "boss", "locked-door"); } roomTypes[14] = solver.CreateFiniteDomainVariable(roomType, "end"); // assert that adjacent rooms cannot have the same content Constraint.NotEqual(roomTypes[0], roomTypes[1]); Constraint.NotEqual(roomTypes[1], roomTypes[2]); Constraint.NotEqual(roomTypes[2], roomTypes[3]); Constraint.NotEqual(roomTypes[3], roomTypes[4]); Constraint.NotEqual(roomTypes[1], roomTypes[5]); Constraint.NotEqual(roomTypes[5], roomTypes[6]); Constraint.NotEqual(roomTypes[6], roomTypes[7]); Constraint.NotEqual(roomTypes[7], roomTypes[8]); Constraint.NotEqual(roomTypes[4], roomTypes[8]); Constraint.NotEqual(roomTypes[8], roomTypes[9]); Constraint.NotEqual(roomTypes[9], roomTypes[10]); Constraint.NotEqual(roomTypes[10], roomTypes[11]); Constraint.NotEqual(roomTypes[10], roomTypes[12]); Constraint.NotEqual(roomTypes[11], roomTypes[13]); Constraint.NotEqual(roomTypes[12], roomTypes[13]); Constraint.NotEqual(roomTypes[13], roomTypes[14]); ScoreMapping <String> damages = new ScoreMapping <String>(roomType, "small-health-pack".PairedWith(new Interval(10)), "big-health-pack".PairedWith(new Interval(20)), "start".PairedWith(new Interval(0)), "empty".PairedWith(new Interval(0)), "zombie".PairedWith(new Interval(-10)), "two zombies".PairedWith(new Interval(-25)), "dog".PairedWith(new Interval(-13)), "trap".PairedWith(new Interval(-10)), "boss".PairedWith(new Interval(-30)), "locked-door".PairedWith(new Interval(0)), "end".PairedWith(new Interval(0))); // create variables to contain how much damage is dealt in each room RealVariable[] roomDelta = new RealVariable[15]; roomDelta[0] = solver.CreateRealVariable(0); roomDelta[0].RequireUnique = false; for (int i = 1; i <= 13; i++) { roomDelta[i] = Constraint.ScoreVariable(roomTypes[i], damages); roomDelta[i].RequireUnique = false; } roomDelta[14] = solver.CreateRealVariable(0); roomDelta[14].RequireUnique = false; // variables for how much health the player has in each room // under the assumptions of forward progress in the paper RealVariable[] playerHealth = new RealVariable[15]; // start at 100 playerHealth[0] = solver.CreateRealVariable(100); playerHealth[0].RequireUnique = false; // player must stay between 0 and 100 health for (int i = 1; i <= 14; i++) { playerHealth[i] = solver.CreateRealVariable(10, 100); playerHealth[i].RequireUnique = false; } Constraint.Sum(playerHealth[1], roomDelta[1], playerHealth[0]); Constraint.Sum(playerHealth[2], roomDelta[2], playerHealth[1]); Constraint.Sum(playerHealth[3], roomDelta[3], playerHealth[2]); Constraint.Sum(playerHealth[4], roomDelta[4], playerHealth[3]); Constraint.Sum(playerHealth[5], roomDelta[5], playerHealth[1]); Constraint.Sum(playerHealth[6], roomDelta[6], playerHealth[5]); Constraint.Sum(playerHealth[7], roomDelta[7], playerHealth[6]); Constraint.Sum(playerHealth[8], roomDelta[8], Constraint.Minimize(playerHealth[4], playerHealth[7]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[9], roomDelta[9], playerHealth[8]); Constraint.Sum(playerHealth[10], roomDelta[10], playerHealth[9]); Constraint.Sum(playerHealth[11], roomDelta[11], playerHealth[10]); Constraint.Sum(playerHealth[12], roomDelta[12], playerHealth[10]); Constraint.Sum(playerHealth[13], roomDelta[13], Constraint.Minimize(playerHealth[11], playerHealth[12]).With(r => r.RequireUnique = false)); Constraint.Sum(playerHealth[14], roomDelta[14], playerHealth[13]); ScoreMapping <String> keyLockScoring = new ScoreMapping <String>(roomType, "small-health-pack".PairedWith(new Interval(0)), "big-health-pack".PairedWith(new Interval(0)), "start".PairedWith(new Interval(0)), "empty".PairedWith(new Interval(0)), "zombie".PairedWith(new Interval(0)), "two zombies".PairedWith(new Interval(0)), "dog".PairedWith(new Interval(0)), "trap".PairedWith(new Interval(0)), "boss".PairedWith(new Interval(2)), "locked-door".PairedWith(new Interval(-1)), "end".PairedWith(new Interval(0))); // 3 things need to happen for a key and lock puzzle. // 1) player needs to first encounter the boss // 2) player needs to then encounter the locked door // 3) player needs to finally encounter the exit // we say a boss provides a value of +2 // we say the locked door provides a value of -1 // and we say that we need to have a value of +1 at the exit // with the restriction that we never dip negative along the path integral // so that placing a locked door before a guaranteed boss would be dissallowed // we use 'min' as our aggregation function RealVariable[] lockKeyDelta = new RealVariable[15]; lockKeyDelta[0] = solver.CreateRealVariable(0); lockKeyDelta[0].RequireUnique = false; for (int i = 1; i <= 14; i++) { lockKeyDelta[i] = Constraint.ScoreVariable(roomTypes[i], keyLockScoring); lockKeyDelta[i].RequireUnique = true; lockKeyDelta[i].Precision = .2; lockKeyDelta[i].Priority = 2; } RealVariable[] lockKeyRunningSum = new RealVariable[15]; // start at 0 lockKeyRunningSum[0] = solver.CreateRealVariable(0); lockKeyRunningSum[0].RequireUnique = true; // require the running sum to stay positive for (int i = 1; i <= 14; i++) { lockKeyRunningSum[i] = solver.CreateRealVariable(0, 2.5); lockKeyRunningSum[i].RequireUnique = false; } // require that the sum at the end be basically equal to 1 Constraint.InRange(lockKeyRunningSum[14], .9, 1.1); Constraint.Sum(lockKeyRunningSum[1], lockKeyDelta[1], lockKeyRunningSum[0]); Constraint.Sum(lockKeyRunningSum[2], lockKeyDelta[2], lockKeyRunningSum[1]); Constraint.Sum(lockKeyRunningSum[3], lockKeyDelta[3], lockKeyRunningSum[2]); Constraint.Sum(lockKeyRunningSum[4], lockKeyDelta[4], lockKeyRunningSum[3]); Constraint.Sum(lockKeyRunningSum[5], lockKeyDelta[5], lockKeyRunningSum[1]); Constraint.Sum(lockKeyRunningSum[6], lockKeyDelta[6], lockKeyRunningSum[5]); Constraint.Sum(lockKeyRunningSum[7], lockKeyDelta[7], lockKeyRunningSum[6]); Constraint.Equal(lockKeyRunningSum[4], lockKeyRunningSum[7]); Constraint.Sum(lockKeyRunningSum[8], lockKeyDelta[8], lockKeyRunningSum[4]); Constraint.Sum(lockKeyRunningSum[9], lockKeyDelta[9], lockKeyRunningSum[8]); Constraint.Sum(lockKeyRunningSum[10], lockKeyDelta[10], lockKeyRunningSum[9]); Constraint.Sum(lockKeyRunningSum[11], lockKeyDelta[11], lockKeyRunningSum[10]); Constraint.Sum(lockKeyRunningSum[12], lockKeyDelta[12], lockKeyRunningSum[10]); Constraint.Equal(lockKeyRunningSum[11], lockKeyRunningSum[12]); Constraint.Sum(lockKeyRunningSum[13], lockKeyDelta[13], lockKeyRunningSum[11]); Constraint.Sum(lockKeyRunningSum[14], lockKeyDelta[14], lockKeyRunningSum[13]); Constraint.LimitOccurences("trap", 1, 2, roomTypes); Constraint.MaximumOccurences("small-health-pack", 1, roomTypes); Constraint.MaximumOccurences("big-health-pack", 1, roomTypes); Constraint.MaximumOccurences("empty", 2, roomTypes); Constraint.RequireOccurences("boss", 1, roomTypes); Constraint.RequireOccurences("locked-door", 1, roomTypes); }