From 31024f9fc5d3cdbb55d663d7290bc07bcf9b0f8e Mon Sep 17 00:00:00 2001 From: Anthony Leland Date: Fri, 30 Oct 2020 05:23:31 -0400 Subject: [PATCH] Decision Engine section --- README.md | 24 ++++++++++++++++++++++++ dataset/choice.csv | 6 ++++++ dataset/objects.csv | 20 -------------------- notebooks/motives.ipynb | 11 +++++++++-- source/Servo.MotiveEngine/Motives.cs | 4 ++-- source/Servo.sln | 16 +++++++++++++++- source/Servo/Program.cs | 12 ++++++++++++ source/Servo/Servo.csproj | 8 ++++++++ 8 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 dataset/choice.csv delete mode 100644 dataset/objects.csv create mode 100644 source/Servo/Program.cs create mode 100644 source/Servo/Servo.csproj diff --git a/README.md b/README.md index cc1bdc3..ddbdb8f 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,30 @@ Servo is a experimental re-implementation of SimAntics using ML.NET based on [Under the Hood of The Sims](https://users.cs.northwestern.edu/~forbus/c95-gd/lectures/The_Sims_Under_the_Hood_files/v3_document.htm). I have wanted to write my own version of SimAntics for a while but the process of rewriting the engine from scratch or even maintaining an existing re-implementation, such as FreeSO's, has proven to be tedious. Current machine learning technologies, such as ML.NET, can streamline the process. That being said, Servo is not intended to be used to rewrite The Sims itself. The models are intended for building new games based on it's design. +## Design + +### Motive Engine + +The Motive Engine is based on opposing weights. An object signals it's presence if the Sim's need is low. The need is the motive and that drives a Sims' decision. All games in the franchise are based on this dynamic at it's core. For example, if hunger is low then the fridge's presence is high and vice versa. A Sim's mood is the sum of the current state of their motives. They will only choose the fridge if it increases it's overall mood. The ML portion comes in deciding which has the priority. + +A Sim's motives decrease in increments and independently of each other during game play. They are randomized for this experiment. + +### Decision Engine + +The actual decision making is handled by ML.NET's recommendation algorithms based on Action, Need, and Threshold where Threshold is the "Rating", Need is the "User" and Action is the "Item". For example: + +| Action | Need | Threshold | +| ------------ | ------ | --------- | +| Refrigerator | Hunger | 30 | +| Refrigerator | Hunger | 28 | +| Refrigerator | Hunger | 24 | +| Refrigerator | Hunger | 21 | +| Refrigerator | Hunger | 20 | + +The decision engine keeps an eye on the motives and the queue. However, In Under the Hood of The Sims says that the final decision is based on whether the fridge increases the current mood as a whole, not the hunger motive. + +Current dataset design is NOT FINAL. + ## License I license the source code for this project under the GNU GPL v3, see [LICENSE](LICENSE), and data sets under the Open Database License, see [DATA-LICENSE](DATA-LICENSE). diff --git a/dataset/choice.csv b/dataset/choice.csv new file mode 100644 index 0000000..3d3d560 --- /dev/null +++ b/dataset/choice.csv @@ -0,0 +1,6 @@ +Action,Need,Threshold +Refrigerator,Hunger,30 +Refrigerator,Hunger,28 +Refrigerator,Hunger,24 +Refrigerator,Hunger,21 +Refrigerator,Hunger,20 \ No newline at end of file diff --git a/dataset/objects.csv b/dataset/objects.csv deleted file mode 100644 index 2cd0d09..0000000 --- a/dataset/objects.csv +++ /dev/null @@ -1,20 +0,0 @@ -Computer,Fun -Video Game,Fun -Phone,Social -Food Processor,Hunger -Coffeemaker,Hunger -Shower,Hygiene -Sim,Social -Dishwasher,Environment -Microwave,Hunger -TV,Fun -Computer,Social -Garbage Can,Environment -Trash Compactor,Environment -Stereo,Fun -Chair,Comfort -Bed,Comfort -Stool,Comfort -Toilet,Bladder -Toy,Fun -Plant,Environment \ No newline at end of file diff --git a/notebooks/motives.ipynb b/notebooks/motives.ipynb index 4be2bad..a26f337 100644 --- a/notebooks/motives.ipynb +++ b/notebooks/motives.ipynb @@ -29,8 +29,15 @@ "metadata": {}, "source": [ "const int NAX_MOOD = 600;\n", - "const int MAX_MOTIVE = 100;\n", - "\n", + "const int MAX_MOTIVE = 100;" + ], + "outputs": [] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "source": [ "static int MaxLimit(this int val, int max)\n", "{\n", " if (max < 0)\n", diff --git a/source/Servo.MotiveEngine/Motives.cs b/source/Servo.MotiveEngine/Motives.cs index 60efe7f..52da063 100644 --- a/source/Servo.MotiveEngine/Motives.cs +++ b/source/Servo.MotiveEngine/Motives.cs @@ -7,8 +7,8 @@ namespace Servo.MotiveEngine const int NAX_MOOD = 600; const int MAX_MOTIVE = 100; - public Motives(int hunger, int bladder, int fun, int energy, - int environment, int social) + public Motives(int hunger, int bladder, int fun, + int energy, int environment, int social) { Hunger = hunger; Bladder = bladder; diff --git a/source/Servo.sln b/source/Servo.sln index 0659d8e..0ea49f7 100644 --- a/source/Servo.sln +++ b/source/Servo.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30621.155 MinimumVisualStudioVersion = 15.0.26124.0 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Servo.MotiveEngine", "Servo.MotiveEngine\Servo.MotiveEngine.csproj", "{162D701B-5CBA-43A4-A763-F4906B287BE3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Servo.MotiveEngine", "Servo.MotiveEngine\Servo.MotiveEngine.csproj", "{162D701B-5CBA-43A4-A763-F4906B287BE3}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3B512BB9-9354-49A4-AE68-97531B21EBD5}" ProjectSection(SolutionItems) = preProject @@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\README.md = ..\README.md EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Servo", "Servo\Servo.csproj", "{6317836E-F520-4FEA-906E-2877CB5ED0AA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +35,18 @@ Global {162D701B-5CBA-43A4-A763-F4906B287BE3}.Release|x64.Build.0 = Release|Any CPU {162D701B-5CBA-43A4-A763-F4906B287BE3}.Release|x86.ActiveCfg = Release|Any CPU {162D701B-5CBA-43A4-A763-F4906B287BE3}.Release|x86.Build.0 = Release|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Debug|x64.ActiveCfg = Debug|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Debug|x64.Build.0 = Debug|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Debug|x86.ActiveCfg = Debug|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Debug|x86.Build.0 = Debug|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Release|Any CPU.Build.0 = Release|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Release|x64.ActiveCfg = Release|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Release|x64.Build.0 = Release|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Release|x86.ActiveCfg = Release|Any CPU + {6317836E-F520-4FEA-906E-2877CB5ED0AA}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/source/Servo/Program.cs b/source/Servo/Program.cs new file mode 100644 index 0000000..3c43258 --- /dev/null +++ b/source/Servo/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace Servo +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/source/Servo/Servo.csproj b/source/Servo/Servo.csproj new file mode 100644 index 0000000..c73e0d1 --- /dev/null +++ b/source/Servo/Servo.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.1 + + +