diff --git a/Assets/Driver.cs b/Assets/Driver.cs index 41f7ecc..76c3285 100644 --- a/Assets/Driver.cs +++ b/Assets/Driver.cs @@ -2,6 +2,7 @@ using Prolog; using UnityEngine; +// ReSharper disable once CheckNamespace public class Driver : MonoBehaviour { public GUIStyle CharacterNameStyle; @@ -30,41 +31,65 @@ public class Driver : MonoBehaviour private readonly object[] playerRelationships = new object[MaxPlayers]; private readonly bool[] playerRelationshipPin = new bool[MaxPlayers]; + int currentPlaysetNumber; + Playset currentPlayset; + + internal void Start() + { + SetPlayset(0); + } + + void SetPlayset(int playsetNumber) + { + currentPlaysetNumber = playsetNumber; + currentPlayset = Playset.Playsets[playsetNumber]; + Array.Clear(playerDetailPin, 0, playerDetailPin.Length); + Array.Clear(playerRelationshipPin, 0, playerRelationshipPin.Length); + } + internal void OnGUI() { var nameHeight = CharacterNameStyle.lineHeight; GUI.Label(new Rect(30, 30, 0, 0), "Fiascomatic", CharacterNameStyle); - GUI.Label(new Rect(30, 60, 100, 30), "Players:"); - countSelection = GUI.Toolbar(new Rect(80, 60, 100, 20), countSelection, playerCountStrings); + + GUI.Label(new Rect(30, 60, 100, 30), "Playset:"); + var playsetSelection = GUI.Toolbar(new Rect(0, 0, Screen.width, 20), currentPlaysetNumber, Playset.PlaysetNames); + if (playsetSelection != currentPlaysetNumber) + { + SetPlayset(playsetSelection); + } + + GUI.Label(new Rect(30, 90, 100, 30), "Players:"); + countSelection = GUI.Toolbar(new Rect(80, 90, 100, 20), countSelection, playerCountStrings); playerCount = countSelection + 3; - GUI.Label(new Rect(30, 175, 150, 300), "Click on a character name to edit it"); + GUI.Label(new Rect(30, 205, 150, 300), "Click on a character name to edit it"); - if (GUI.Button(new Rect(30, 100, 200, 60), "Let the suffering begin!")) + if (GUI.Button(new Rect(30, 130, 200, 60), "Let the suffering begin!")) { - this.Setup(); + Setup(); } for (int i = 0; i < playerCount; i++) { - var textposition = this.PlayerScreenPosition(i); + var textposition = PlayerScreenPosition(i); playerNames[i] = GUI.TextField( new Rect(textposition.x, textposition.y, 100, nameHeight), playerNames[i], - this.CharacterNameStyle); - var detailposition = this.DetailScreenPosition(i); + CharacterNameStyle); + var detailposition = DetailScreenPosition(i); GUI.Label( new Rect(detailposition.x, detailposition.y, 160, 300), playerDetailStrings[i], - this.DetailStyle); + DetailStyle); if (playerDetails[i] != null) playerDetailPin[i] = GUI.Toggle(new Rect(detailposition.x - 25, detailposition.y, 20, 20), playerDetailPin[i], ""); - var relationshipposition = this.RelationshipScreenPosition(i); + var relationshipposition = RelationshipScreenPosition(i); GUI.Label( new Rect(relationshipposition.x, relationshipposition.y, 160, 300), playerRelationshipStrings[i], - this.RelationshipStyle); + RelationshipStyle); if (playerRelationships[i] != null) playerRelationshipPin[i] = GUI.Toggle(new Rect(relationshipposition.x - 25, relationshipposition.y, 20, 20), playerRelationshipPin[i], ""); } @@ -73,43 +98,43 @@ internal void OnGUI() private void Setup() { PrologContext.DefaultStepLimit = 1000000; - switch (this.playerCount) + switch (playerCount) { case 3: - this.SolveSetup(new[] + SolveSetup(new[] { - this.RelationshipTuple(0, 1), this.RelationshipTuple(1, 2), this.RelationshipTuple(2, 0), - this.DetailTuple(0), this.DetailTuple(1), this.DetailTuple(2) + RelationshipTuple(0, 1), RelationshipTuple(1, 2), RelationshipTuple(2, 0), + DetailTuple(0), DetailTuple(1), DetailTuple(2) }); break; case 4: - this.SolveSetup(new[] + SolveSetup(new[] { - this.RelationshipTuple(0, 1), this.RelationshipTuple(1, 2), this.RelationshipTuple(2, 3), - this.RelationshipTuple(3, 0), - this.DetailTuple(0), this.DetailTuple(1), this.DetailTuple(2), - this.DetailTuple(3) + RelationshipTuple(0, 1), RelationshipTuple(1, 2), RelationshipTuple(2, 3), + RelationshipTuple(3, 0), + DetailTuple(0), DetailTuple(1), DetailTuple(2), + DetailTuple(3) }); break; case 5: - this.SolveSetup(new[] + SolveSetup(new[] { - this.RelationshipTuple(0, 1), this.RelationshipTuple(1, 2), this.RelationshipTuple(2, 3), - this.RelationshipTuple(3, 4), this.RelationshipTuple(4, 0), - this.DetailTuple(0), this.DetailTuple(1), this.DetailTuple(2), - this.DetailTuple(3), this.DetailTuple(4) + RelationshipTuple(0, 1), RelationshipTuple(1, 2), RelationshipTuple(2, 3), + RelationshipTuple(3, 4), RelationshipTuple(4, 0), + DetailTuple(0), DetailTuple(1), DetailTuple(2), + DetailTuple(3), DetailTuple(4) }); break; case 6: - this.SolveSetup(new[] + SolveSetup(new[] { - this.RelationshipTuple(0, 1), this.RelationshipTuple(1, 2), this.RelationshipTuple(2, 3), - this.RelationshipTuple(3, 4), this.RelationshipTuple(4, 5), this.RelationshipTuple(5, 0), - this.DetailTuple(0), this.DetailTuple(1), this.DetailTuple(2), - this.DetailTuple(3), this.DetailTuple(4), this.DetailTuple(5) + RelationshipTuple(0, 1), RelationshipTuple(1, 2), RelationshipTuple(2, 3), + RelationshipTuple(3, 4), RelationshipTuple(4, 5), RelationshipTuple(5, 0), + DetailTuple(0), DetailTuple(1), DetailTuple(2), + DetailTuple(3), DetailTuple(4), DetailTuple(5) }); break; } @@ -117,26 +142,26 @@ private void Setup() private void SolveSetup(object[] setup) { - using (var prologContext = PrologContext.Allocate(KnowledgeBase.Global, null)) + using (var prologContext = PrologContext.Allocate(currentPlayset.KnowledgeBase, null)) { if (!prologContext.IsTrue("make_setup", Prolog.Prolog.IListToPrologList(setup))) Debug.Log("Failed to make setup!"); else { - for (int i = 0; i < this.playerCount; i++) + for (int i = 0; i < playerCount; i++) { - this.playerRelationships[i] = Term.CopyInstantiation(setup[i]); - this.playerRelationshipStrings[i] = + playerRelationships[i] = Term.CopyInstantiation(setup[i]); + playerRelationshipStrings[i] = string.Format("{0}", ((Structure)(setup[i])).Argument(1).ToString().Replace("/", " / ")).Replace("_", " "); } - for (int i = 0; i < this.playerCount; i++) + for (int i = 0; i < playerCount; i++) { - this.playerDetails[i] = Term.CopyInstantiation(setup[this.playerCount + i]); - this.playerDetailStrings[i] = string.Format( + playerDetails[i] = Term.CopyInstantiation(setup[playerCount + i]); + playerDetailStrings[i] = string.Format( "{0}:\n{1}", - ((Structure)(setup[this.playerCount + i])).Argument(1), - ((Structure)(setup[this.playerCount + i])).Argument(2)).Replace("_", " "); + ((Structure)(setup[playerCount + i])).Argument(1), + ((Structure)(setup[playerCount + i])).Argument(2)).Replace("_", " "); } } } @@ -167,7 +192,7 @@ object DetailTuple(int player) private Vector2 PlayerScreenPosition(int i) { var center = new Vector2(Screen.width / 2f , Screen.height / 2f - 50); - var angle = i * Math.PI * 2 / this.playerCount; + var angle = i * Math.PI * 2 / playerCount; var radius = (Math.Min(Screen.width, Screen.height) * 0.5f) - 70; var textposition = center + radius * new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); return textposition; @@ -176,7 +201,7 @@ private Vector2 PlayerScreenPosition(int i) private Vector2 RelationshipScreenPosition(int i) { var center = new Vector2(Screen.width / 2f , Screen.height / 2f - 50); - var angle = (i+0.5f) * Math.PI * 2 / this.playerCount; + var angle = (i+0.5f) * Math.PI * 2 / playerCount; var radius = (Math.Min(Screen.width, Screen.height) * 0.5f) - 70; var textposition = center + radius * new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); return textposition; @@ -184,6 +209,6 @@ private Vector2 RelationshipScreenPosition(int i) private Vector2 DetailScreenPosition(int i) { - return this.PlayerScreenPosition(i) + new Vector2(0f, CharacterNameStyle.lineHeight); + return PlayerScreenPosition(i) + new Vector2(0f, CharacterNameStyle.lineHeight); } } diff --git a/Assets/MainScene.unity b/Assets/MainScene.unity index 4061d38..b873c27 100644 Binary files a/Assets/MainScene.unity and b/Assets/MainScene.unity differ diff --git a/Assets/Playset.cs b/Assets/Playset.cs new file mode 100644 index 0000000..cf3fa90 --- /dev/null +++ b/Assets/Playset.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; +using System.Collections.Generic; +using UnityEngine; +using Prolog; + +public class Playset +{ + const string PlaysetsDirectory = "Playsets"; + + public static readonly List Playsets = new List(); + public static readonly string[] PlaysetNames; + static Playset() + { + string playsetsPath = Path.Combine(Application.dataPath, PlaysetsDirectory); + string[] playsetsDirectory = Directory.GetFiles(playsetsPath); + var names = new List(); + foreach (var playset in playsetsDirectory) + { + if (Path.GetExtension(playset) == ".prolog") + { + var playsetName = Path.GetFileNameWithoutExtension(playset); + if (playsetName != null) + { + Playsets.Add(new Playset(playset)); + names.Add(playsetName); + } + } + } + PlaysetNames = names.ToArray(); + } + + + private Playset(string path) + { + KnowledgeBase = new KnowledgeBase(Path.GetFileNameWithoutExtension(path), null); + KnowledgeBase.Consult(Path.Combine(Application.dataPath, "Solver.prolog")); + KnowledgeBase.Consult(path); + } + + public readonly KnowledgeBase KnowledgeBase; +} + diff --git a/Assets/Playset.cs.meta b/Assets/Playset.cs.meta new file mode 100644 index 0000000..0aff48f --- /dev/null +++ b/Assets/Playset.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 907c06800e181d747b2ac004c7230679 +timeCreated: 1446932902 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Playsets/Ethan play set.prolog b/Assets/Playsets/Ethan play set.prolog new file mode 100644 index 0000000..0d0b528 --- /dev/null +++ b/Assets/Playsets/Ethan play set.prolog @@ -0,0 +1,316 @@ +% Ethan Robison +% Kevin Ye +% Daniel Thirman +% Alexander Martin + +% +% relationships +% + +roles_relation(father/son). + % son cannot be father of father +contradiction(relationship(X, father, Y), relationship(Y, father, X)). + +symmetric(brothers). +contradiction(relationship(X, brothers, Y), relationship(X, father, Y)). +contradiction(relationship(X, brothers, Y), relationship(X, cousins, Y)). + +symmetric(cousins). + % son cannot be cousin of father +contradiction(roles_relation(X, father ,Y), roles_relation(X, cousin, Y)). + +symmetric(family). +transitive(family). + +symmetric(friends). +symmetric(at_odds). +symmetric(old_schoolmates). +symmetric(old_school_enemies). +symmetric(amicable_neighbors). +symmetric(belligerent_neighbors). +symmetric(cohorts). + +generalizes(cousins, family). +generalizes(brothers, family). +generalizes(father, family). +generalizes(son, family). + + +generalizes(old_schoolmates, friends). +generalizes(amicable_neighbors, friends). +generalizes(old_school_enemies, at_odds). +generalizes(belligerent_neighbors, at_odds). + + % no need to make so many conflicting roles... +contradiction(relationship(X, friends, Y), relationship(X, at_odds, Y)). + + + +symmetric(sexual_partners). + % incest is out +contradiction(relationship(X, sexual_partners, Y), relationship(X, family, Y)). + + +roles_relation(pastor_of(X)/churchgoer_of(X)):- + religion(X). +implies(role(C, pastor_of(_)), has(C, dogearred_NIV)). +implies(role(C, pastor_of(_)), has(C, jesus_figurine)). + % one pastor_of(_) per town +contradiction(role(C, pastor_of(_)), role(D, pastor_of(_))) :- + C \= D. + +roles_relation(sheriff/criminal). +implies(role(C, sheriff), has(C, stetson_hat)). +implies(role(C, sheriff), has(C, handgun_45_caliber)). +% one sheriff per town +contradiction(role(C, sheriff), role(D, sheriff)):- + C \= D. + +roles_relation(drug_dealer/druggee). +implies(role(C, drug_dealer), role(C, criminal)). +implies(role(C, druggee), role(C, criminal)). +implies(relationship(X, drug_dealer, Y), relationship(X, cohorts, Y)). + +roles_relation(bartender/bar_patron). +roles_relation(gas_station_clerk/gas_station_patron). +roles_relation(car_salesman/dealership_patron). +roles_relation(mechanic/bodyshop_patron). + +roles_relation(scientist/subject). +implies(role(C, scientist), has(C, walkie_talkie)). +implies(role(C, scientist), has(C, secret_facility_id_card)). + +roles_relation(secret_agent/person_of_interest). +implies(role(C, secret_agent), has(C, handgun_45_caliber)). +implies(role(C, secret_agent), has(C, walkie_talkie)). +implies(role(C, secret_agent), has(C, secret_facility_id_card)). +implies(role(C, secret_agent), has(C, unmarked_sedan)). + + +conflicting_roles(scientist, secret_agent). +conflicting_roles(scientist, subject). +conflicting_roles(scientist, person_of_interest). +conflicting_roles(scientist, bartender). +conflicting_roles(scientist, car_salesman). +conflicting_roles(scientist, gas_station_clerk). +conflicting_roles(scientist, mechanic). +conflicting_roles(scientist, pastor_of(_)). +conflicting_roles(scientist, sheriff). +conflicting_roles(sheriff, criminal). +conflicting_roles(sheriff, bartender). +conflicting_roles(sheriff, car_salesman). +conflicting_roles(sheriff, gas_station_clerk). +conflicting_roles(sheriff, mechanic). +conflicting_roles(sheriff, pastor_of(_)). +conflicting_roles(pastor_of(_), churchgoer_of(_)). +conflicting_roles(pastor_of(_), bar_patron). +conflicting_roles(pastor_of(_), criminal). +conflicting_roles(pastor_of(_), bartender). +conflicting_roles(pastor_of(_), car_salesman). +conflicting_roles(pastor_of(_), gas_station_clerk). +conflicting_roles(pastor_of(_), mechanic). +conflicting_roles(bartender, bar_patron). +conflicting_roles(bartender, car_salesman). +conflicting_roles(bartender, gas_station_clerk). +conflicting_roles(bartender, mechanic). +conflicting_roles(gas_station_clerk, car_salesman). +conflicting_roles(gas_station_clerk, gas_station_patron). +conflicting_roles(gas_station_patron, mechanic). +conflicting_roles(car_salesman, dealership_patron). +conflicting_roles(car_salesman, mechanic). +conflicting_roles(mechanic, bodyshop_patron). + + +% +% locations +% + +location(gas_station). +location(brew_thru). +location(strip_club). +location(bar). +location(winn_dixie). +location(church). +location(school). +location(house). + + +location(inside_car(X)):- + car(X). + % anyone who starts out in the boat needs to be on the river +implies(at(X, inside_car(leaky_rowboat)), at(X, river)). + +location(car_dealership). + + +location(bog). +location(tree_grove). +location(farm). +location(country_road). +location(cemetary). +location(river). + + +location(inside_spaceship). +location(mysterious_facility). +location(inside_abondoned_facility). +location(inside_active_facility). + +implies(at(C, inside_active_facility), role(C, secret_agent)). +implies(at(C, inside_abondoned_facility), role(C, secret_agent)). + +% +% objects +% + +object(X) :- + car(X). +car(red_volvo). +car(stolen_hot_rod). +car(leaky_rowboat). % laughs, this was deliberate +car(old_pickup). +car(new_pickup). +car(unmarked_sedan). + + +object(metal_detector). +object(electric_generator). +object(barrel_of_motor_oil). +object(suitcase_of_gold_bullion). + + +object(dogearred_NIV). +object(jesus_figurine). + + +object(tattered_confederate_flag). +object(collectors_shotgun). + + +object(handgun_45_caliber). +object(stetson_hat). + + +object(alien_corpse). +object(human_corpse). +contradiction(has(C, alien_corpse), has(D, alien_corpse)) :- + C \= D. +contradiction(has(C, human_corpse), has(D, human_corpse)) :- + C \= D. + + +object(walkie_talkie). +object(secret_facility_id_card). +object(vial_of_experimental_phlebotinum). + + % these sorts of things are a bit shady... +object(backpack_full_of_dynamite). +object(bloody_revolver). +implies(has(C, backpack_full_of_dynamite, role(C, criminal))). +implies(has(C, bloody_revolver), role(C, criminal)). + + +object(tesla_coil). + % tesla coils are not a common possession... +implies(has(C, tesla_coil), role(C, scientist)). + +object(truth_serum). + % truth serum is for secret agents only +implies(has(C, truth_serum), role(C, secret_agent)). + + +% +% needs +% + +need(peer_approval). +need(make_parents_proud). +need(ten_grand_by_tomorrow). +need(get_out_of_this_town). + +need(find_a_job). + % why would such a person even need a job? +contradiction(needs(C, find_a_job), has(C, suitcase_of_gold_bullion)). + +need(satisfy_curiosity). +need(build_a_flying_machine). + +need(sexual_satisfaction). + % sexual_satisfaction means that one probably is not getting any +contradiction(needs(C, sexual_satisfaction), relationship(C, sexual_partners, _)). + +need(clean_up_this_town). +implies(needs(C, clean_up_this_town), role(C, sheriff)). + +need(confirm_research_hypothesis). + % have to have a hypothesis to confirm it +implies(needs(C, confirm_research_hypothesis), role(C, scientist)). + +need(hide_facility). +need(guard_facility_secret). + % have to know about the faacility to hide/guard it +implies(needs(C, hide_facility), access_to_secrets(C)). +implies(needs(C, guard_facility_secret), access_to_secrets(C)). + + +need(keep_parole). + % have to have committed a crime to have parole +implies(needs(C, keep_parole), role(C, criminal)). + +need(pay_bar_tab). + % have to have a tab to need to pay it +implies(needs(C, pay_bar_tab), role(C, bar_patron)). +need(drink_to_forget). + % bars are a good start... +implies(needs(C, drink_to_forget), role(C, bar_patron)). + + +religion(accepting_sort_of_christianity). +religion(bigoted_sort_of_christianity). +religion(eldritch). +religion(paganism). + +sacrificing_sort_of_religion(eldritch). +sacrificing_sort_of_religion(paganism). + +need(evangelize_religion(X)) :- + religion(X). +need(follow_religion(X)) :- + religion(X). + + % to evangelize a religion one must follow that religion +implies(needs(C, evangelize_religion(X)), follows_religion(C, X)). + +need(encounter_human_for_sacrificial_religion(X)) :- + sacrificing_sort_of_religion(X). + + % to need to find a human sacrifice, one must follow that sort of religion +implies(needs(C, encounter_human_for_sacrificial_religion(X)), follows_religion(C, X)). + + % sons follow their religions of their fathers +implies((relationship(X, son, Y), follows_religion(Y, R)), follows_religion(X, R)). + % people who are trying to sacrifice a person are, knowingly or unknowingly, cohorts +implies((needs(C, encounter_human_for_sacrificial_religion(R)), needs(D, encounter_human_for_sacrificial_religion(R))), relationship(C, cohorts, D)). + +contradiction(follows_religion(C, R1), follows_religion(C, R2)) :- + R1 \= R2. + +need(drug_addiction(X)) :- + drug(X). + +need(hide_drug_addiction_to(X)) :- + drug(X). + +implies(needs(C, hide_drug_addiction_to(X)), needs(C, drug_addiction(X))). +implies(needs(C, drug_addiction(_)), role(C, druggee)). + +drug(meth). +drug(crack). +drug(bath_salts). +drug(human_blood). +drug(phlebotinum). + +need(buy_new_tires_for_car(X)):- + car(X). + % have to have a car to need tires for it +implies(needs(C, buy_new_tires_for_car(X)), has(C, X)). diff --git a/Assets/Playsets/Ethan play set.prolog.meta b/Assets/Playsets/Ethan play set.prolog.meta new file mode 100644 index 0000000..fe232b8 --- /dev/null +++ b/Assets/Playsets/Ethan play set.prolog.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 731ba742d1af8be48b88c34f44ecb50e +timeCreated: 1446935109 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index c2c607a..22ea8ba 100644 Binary files a/ProjectSettings/ProjectSettings.asset and b/ProjectSettings/ProjectSettings.asset differ diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index e040c5c..b11ab9b 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 5.2.0f3 +m_EditorVersion: 5.2.2f1 m_StandardAssetsVersion: 0