public void CharacterGeneratorTest() { var prog = new Problem("Character generator"); var race = new FDVariable <string>("race", "human", "electroid", "insectoid"); var cclass = new FDVariable <string>("cclass", "fighter", "magic user", "cleric", "thief"); // Electroids are atheists prog.Inconsistent(race == "electroid", cclass == "cleric"); // Nationalities of humans var nationality = new FDVariable <string>("nationality", race == "human", "landia", "placeville", "cityburgh"); // Religions of clerics var religion = new FDVariable <string>("religion", cclass == "cleric", "monotheist", "pantheist", "lovecraftian", "dawkinsian"); // Lovecraftianism is outlawed in Landia prog.Inconsistent(nationality == "landia", religion == "lovecraftian"); // Insectoids believe in strict hierarchies prog.Inconsistent(race == "insectoid", religion == "pantheist"); // Lovecraftianism is the state religion of cityburgh prog.Inconsistent(nationality == "cityburgh", cclass == "cleric", Not(religion == "lovecraftian")); for (int i = 0; i < 100; i++) { var solution = prog.Solve(); var characterObject = new CharacterObject(); string Value(FDVariable <string> v) { return(solution.DefinesVariable(v) ? v.Value(solution) : null); } solution.Populate(characterObject); Assert.AreEqual(Value(race), characterObject.race); Assert.AreEqual(Value(cclass), characterObject.cclass); Assert.AreEqual(Value(nationality), characterObject.nationality); Assert.AreEqual(Value(religion), characterObject.religion); Console.WriteLine(solution.Model); } }
/// <summary> /// Add the information in the PCGToy file to the specified problem. /// </summary> /// <param name="path">File path</param> /// <param name="problem">Problem to add the contents to</param> /// <exception cref="FileFormatException">If the file is not a valid PCGToy file.</exception> public static void LoadFromFile(string path, Problem problem) { Dictionary <string, FDomain <object> > domains = new Dictionary <string, FDomain <object> >(); Dictionary <string, FDVariable <object> > variables = new Dictionary <string, FDVariable <object> >(); var f = System.IO.File.OpenText(path); while (f.Peek() >= 0) { var exp = SExpression.Read(f); if (!(exp is List <object> l) || l.Count == 0 || !(l[0] is string tag)) { throw new FileFormatException($"Unknown declaration {exp}"); } switch (tag) { case "domain": if (l.Count < 2 || !(l[1] is string domainName)) { throw new FileFormatException("Malformed domain declaration"); } if (l.Count < 3) { throw new FileFormatException($"Domain {domainName} has no elements"); } var elements = l.Skip(2).ToArray(); domains[domainName] = new FDomain <object>(domainName, elements); break; case "variable": if (l.Count < 3 || l.Count > 4 || !(l[1] is string varName) || !(l[2] is string domain)) { throw new FileFormatException("Malformed variable declaration"); } if (!domains.ContainsKey(domain)) { throw new FileFormatException( $"Unknown domain name: {domain} in declaration of variable {varName}"); } Literal c = null; if (l.Count == 4) { c = ConditionFromSExpression(l[3], variables); } var v = new FDVariable <object>(varName, domains[domain], c); variables[varName] = v; break; case "nogood": problem.Inconsistent(l.Skip(1).Select(sexp => ConditionFromSExpression(sexp, variables)).ToArray()); break; default: throw new FileFormatException($"Unknown declaraction {tag}"); } } }