public static bool TryQueryStructure( Structure term, PrologContext context, out ELNode foundNode, out ELNodeEnumerator enumerator) { // // Dispatch based on the functor and arity. // // Handle root queries, i.e. /Key if (term.IsFunctor(Symbol.Slash, 1)) return TryRootQuery(term, context, out foundNode, out enumerator); if (!IsELTerm(term)) throw new Exception("Malformed EL query: " + ISOPrologWriter.WriteToString(term)); if (term.IsFunctor(SBindNodeOperator, 2)) { var variableToBind = term.Argument(1) as LogicVariable; if (variableToBind == null) throw new ArgumentException("RHS of >> must be an uninstantiated variable: "+ ISOPrologWriter.WriteToString(term.Argument(1))); foundNode = null; return TryNodeBindingQuery(out enumerator, term.Argument(0), variableToBind, context); } return TryChildQuery( out foundNode, out enumerator, term.Argument(0), term.Argument(1), term.Functor == Symbol.Colon, context); }
private void UpdateLocomotion() { UpdateLocomotionBidsAndPath(); if (CurrentlyDockedWith != null && !CurrentlyDockedWith.DockingTiles().Contains(transform.position)) { // We were docked with an object, but are not anymore. perceptionRoot.DeleteKey(SDockedWith); CurrentlyDockedWith = null; } if (currentPath != null) { // Update the steering if (currentPath.UpdateSteering(steering) || (Vector2.Distance(transform.position, currentDestination.transform.position) < 0.75 && currentDestination.IsCharacter())) { // Finished the path CurrentlyDockedWith = CurrentDestination; ELNode.Store(perceptionRoot / SDockedWith % CurrentlyDockedWith); ELNode.Store(lastDestination % CurrentDestination); currentPath = null; currentDestination = null; (motorRoot / SWalkingTo).DeleteSelf(); Face(CurrentlyDockedWith); steering.Stop(); QueueEvent("arrived_at", CurrentlyDockedWith); } } }
public static bool TryChildQuery( out ELNode foundNode, out ELNodeEnumerator enumerator, object parentExpression, object keyExpression, bool isExclusive, PrologContext context) { // Decode the parent expression ELNode parentNode; ELNodeEnumerator parentEnumerator; if (!TryQuery(parentExpression, context, out parentNode, out parentEnumerator)) { // Parent failed, so we fail enumerator = null; foundNode = null; return false; } // // Decode the key argument // var key = keyExpression; var v = key as LogicVariable; return isExclusive?TryExclusiveQuery(out foundNode, out enumerator, parentNode, parentEnumerator, key, v) : TryNonExclusiveQuery(out foundNode, out enumerator, parentNode, key, v, parentEnumerator); }
void UpdateLocomotionBidsAndPath() { //foreach (var pair in bidTotals) // bidTotals[pair.Key] = 0; bidTotals.Clear(); elRoot.WalkTree(SConcerns, this.updateConcernBids); GameObject winner = null; float winningBid = 0; foreach (var pair in bidTotals) { if (pair.Value > winningBid) { winningBid = pair.Value; winner = pair.Key; } } if (winner != null) { // Replan if destination has changed or if destination has moved away from current path. var newDestination = (winner != CurrentDestination && winner != CurrentlyDockedWith); if (newDestination || (currentDestination != null && currentPath != null && !CurrentDestination.DockingTiles().Contains(currentPath.FinalTile))) { if (newDestination) { ELNode.Store(eventHistory / new Structure("goto", winner)); // Log change for debugging purposes. } this.CurrentDestination = winner; this.currentPath = planner.Plan(gameObject.TilePosition(), this.CurrentDestination.DockingTiles()); } } }
void UpdateConcernBids(ELNode concern) { // Make sure this isn't the EL root (it's not an actual concern node). if (concern.Key != null) { ELNode bids; if (concern.TryLookup(SLocationBids, out bids)) { // Add its bids in foreach (var bid in bids.Children) { var destination = bid.Key as GameObject; if (destination == null) { throw new Exception("Location bid is not a GameObject: " + bid.Key); } var bidValue = Convert.ToSingle(bid.ExclusiveKeyValue <object>()); if (bidTotals.ContainsKey(destination)) { bidTotals[destination] += bidValue; } else { bidTotals[destination] = bidValue; } } } } }
public static bool TryQuery(object term, PrologContext context, out ELNode foundNode, out ELNodeEnumerator enumerator) { // Dereference any top-level variables. var t = Term.Deref(term); // Dereference indexicals var i = t as Indexical; if (i != null) t = i.GetValue(context); // A game object means the gameobject's EL KB. var g = t as GameObject; if (g != null) t = g.KnowledgeBase().ELRoot; // If it's already an ELNode, use that. var n = t as ELNode; if (n != null) { foundNode = n; enumerator = null; return true; } // Otherwise, it's an expression, so evaluate it. var s = t as Structure; if (s != null) return TryQueryStructure(s, context, out foundNode, out enumerator); var v = t as LogicVariable; if (v != null && !v.IsBound) throw new Exception("EL query root is an unbound variable: " + v); throw new Exception("Malformed EL query: " + ISOPrologWriter.WriteToString(term)); }
/// <summary> /// Call into Prolog to respond to EVENTDESCRIPTION /// </summary> /// <param name="eventDescription">Term representing the event</param> private void NotifyEvent(object eventDescription) { ELNode.Store(eventHistory / Term.CopyInstantiation(eventDescription)); if (!this.IsTrue(new Structure(SNotifyEvent, eventDescription))) { Debug.LogError("notify_event/1 failed: " + ISOPrologWriter.WriteToString(eventDescription)); } }
/// <summary> /// Thrown when attempting to write a non-exclusive value to an exclusive value or vice-versa. /// </summary> public ELNodeExclusionException(string message, ELNode node, object key) : base(string.Format("{0}: {1}{2}{3}", message, node, node.IsExclusive?ELProlog.ExclusiveOperator:ELProlog.NonExclusiveOperator, ISOPrologWriter.WriteToString(key))) { }
private void SetSpeechTimeout(string speech) { currentlySpeaking = true; ELNode.Store(motorRoot / SIAmSpeaking); clearSpeechTime = Time.time + Math.Max( SpeechDelayMinimum, Math.Min(SpeechDelayMaximum, speech.Length * SpeechDelaySecondsPerChar)); }
internal void Start() { lastPlayerActivity = KnowledgeBase.Global.ELRoot.StoreNonExclusive(Symbol.Intern("last_player_activity")); lastPlayerActivity.StoreExclusive(-1, true); elRoot = this.KnowledgeBase().ELRoot; haloElNode = elRoot / Symbol.Intern("halo"); mouseSelectionELNode = elRoot / Symbol.Intern("perception") / Symbol.Intern("mouse_selection"); talkingToElNode = elRoot / Symbol.Intern("social_state") / Symbol.Intern("talking_to"); MouseSelection = null; }
#pragma warning restore 649 #endregion internal void Start() { this.lastPlayerActivity = KnowledgeBase.Global.ELRoot.StoreNonExclusive(Symbol.Intern("last_player_activity")); this.lastPlayerActivity.StoreExclusive(-1, true); var theCamera = Camera.main; var bottomOfUI = Math.Min(InputRect.yMin, Math.Min(CommentaryRect.yMin, ResponseRect.yMin)); var r = theCamera.pixelRect; r.height -= bottomOfUI + 50; theCamera.pixelRect = r; FindObjectOfType <TileMap>().UpdateCamera(theCamera); Tile.UpdateTileSize(theCamera); }
public KnowledgeBase(string kbName, GameObject gameObject, KnowledgeBase parent, params KnowledgeBase[] otherImports) { if (kbName == null) throw new ArgumentNullException("kbName"); Name = kbName; this.Parent = parent; this.GameObject = gameObject; this.ELRoot = new ELNode(null, Symbol.Intern("root")); //if (parent == null) throw new ArgumentNullException("parent"); if (otherImports == null) throw new ArgumentNullException("otherImports"); foreach (var import in otherImports) if (import == null) throw new ArgumentNullException("otherImports"); if (parent != null) imports.Add(parent); imports.AddRange(otherImports); }
private void UpdateLocations() { // TODO: FIX THIS SO THAT DESTROYED OBJECTS GET THEIR ENTRIES GC'ed. foreach (var p in Registry <PhysicalObject>()) { var o = p.gameObject; var n = locationRoot.ChildWithKey(o); // Don't do anything if /perception/location/O:Location:override in database, // which would mean the character is brainwashed about O's position. if (n == null || n.Children.Count == 0 || !n.Children[0].ContainsKey(brainwashedSymbol)) { if (!p.Exists) { // Dead; remove it. locationRoot.DeleteKey(o); } // Determine if it's inside something else if (p.Container == null) { // It's not inside another object, so find what room it's in. if (n == null || !n.ExclusiveKeyValue <GameObject>().GetComponent <Room>().Contains(o)) { var r = TileMap.TheTileMap.TileRoom(o); var location = r != null?(r.gameObject):null; if (location == null && p is Door) { location = ((Door)p).ForceRoom; } ELNode.Store(locationRoot / o % location); if (o == gameObject) { myCurrentRoom = r; } } } else { if (!p.IsHidden) { ELNode.Store((locationRoot / o % p.Container)); } } } } }
private void UpdateStatusTextBids(ELNode concern) { var textRoot = concern.ChildWithKey(SStatusText); if (textRoot != null && textRoot.Children.Count > 0) { var text = textRoot.Children[0]; if (text.Children.Count > 0) { var bid = Convert.ToSingle(text.Children[0].Key); if (bid > maxStatusBid) { maxStatusBid = bid; maxBidStatus = text.Key.ToString(); } } } }
private void UpdateLocations() { foreach (var p in Registry <PhysicalObject>()) { var o = p.gameObject; var n = this.locationRoot.ChildWithKey(o); // Don't do anything if /perception/location/O:Location:override in database, // which would mean the character is brainwashed about O's position. if (n == null || n.Children.Count == 0 || !n.Children[0].ContainsKey(this.brainwashedSymbol)) { // Determine if it's inside something if (p.Container == null) { // It's not inside another object, so find what room it's in. if (n == null || !n.ExclusiveKeyValue <GameObject>().GetComponent <Room>().Contains(o)) { foreach (var r in Registry <Room>()) { if (r.Contains(o)) { ELNode.Store(this.locationRoot / o % (r.gameObject)); if (o == this.gameObject) { this.myCurrentRoom = r; } } } } } else { if (!p.IsHidden) { ELNode.Store((this.locationRoot / o % p.Container)); } } } } }
internal void Start() { updateConcernBids = this.UpdateConcernBids; elRoot = this.KnowledgeBase().ELRoot; this.perceptionRoot = elRoot / Symbol.Intern("perception"); this.locationRoot = perceptionRoot / Symbol.Intern("location"); this.conversationalSpace = perceptionRoot / Symbol.Intern("conversational_space"); this.socialSpace = perceptionRoot / Symbol.Intern("social_space"); this.motorRoot = elRoot / Symbol.Intern("motor_state"); this.physiologicalStates = elRoot / Symbol.Intern("physiological_states"); this.eventHistory = elRoot / Symbol.Intern("event_history"); this.lastDestination = elRoot / Symbol.Intern("last_destination"); ELNode.Store(lastDestination % null); // Need a placeholder last destination so that /last_destination/X doesn't fail. if (!KB.Global.IsTrue("register_character", gameObject)) { throw new Exception("Can't register character " + name); } if (greyOutTexture == null) { greyOutTexture = new Texture2D(1, 1); greyOutTexture.SetPixel(0, 0, new Color(0, 0, 0, 128)); } }
private static bool TryRootQuery(Structure term, PrologContext context, out ELNode foundNode, out ELNodeEnumerator enumerator) { // Expression is /Key. var arg0 = term.Argument(0); // This is a "/constant" expression, i.e. a top-level lookup. if (arg0 is LogicVariable) { throw new NotImplementedException("Lookups of the form /Variable are not supported."); } enumerator = null; return context.KnowledgeBase.ELRoot.TryLookup(arg0, out foundNode); }
public void SetKB(KnowledgeBase kb) { root = kb.ELRoot; displayChildren.Add(root); }
private static bool TryNonExclusiveQueryEnumeratedParent( out ELNode foundNode, out ELNodeEnumerator enumerator, object key, LogicVariable v, ELNodeEnumerator parentEnumerator) { // Enumerated parent path // NonUniqueParent/Something foundNode = null; if (v == null) { // NonUniqueParent/Key // Enumerate parent, then do deterministic lookup for child. enumerator = new ELNodeEnumeratorFixedChildFromParentEnumerator(parentEnumerator, key); return true; } if (parentEnumerator.BindsVar(v)) { // We're doing a search for a variable that's aready bound. enumerator = new ELNodeEnumeratorPreboundVariable(parentEnumerator, v, false); return true; } // NonUniqueParent/Variable // Enumerate both parent and child. enumerator = new ELNodeEnumeratorLogicVariableFromParentEnumerator(parentEnumerator, v); return true; }
private static bool TryNonExclusiveQuery(out ELNode foundNode, out ELNodeEnumerator enumerator, ELNode parentNode, object key, LogicVariable v, ELNodeEnumerator parentEnumerator) { if (parentNode != null) { return TryNonExclusiveQueryDeterministicParent(out foundNode, out enumerator, parentNode, key, v); } return TryNonExclusiveQueryEnumeratedParent(out foundNode, out enumerator, key, v, parentEnumerator); }
private static bool TryNonExclusiveQueryDeterministicParent( out ELNode foundNode, out ELNodeEnumerator enumerator, ELNode parentNode, object key, LogicVariable v) { // Deterministic parent path // The expression is UniqueParent/Something if (parentNode.IsExclusive) { throw new ELNodeExclusionException("Non-exclusive query of an exclusive node", parentNode, key); } if (v == null) { // fully deterministic path // UniqueParent/Key corresponds to at most one ELNode. enumerator = null; return parentNode.TryLookup(key, out foundNode); } // UniqueParent/Variable, so do a singly-nested iteration. foundNode = null; enumerator = new ELNodeEnumeratorLogicVariableFromNode(parentNode, v); return true; }
public ELNodeEnumeratorLogicVariableFromNode(ELNode parentNode, LogicVariable v) { this.parentNode = parentNode; this.variable = v; childIndex = parentNode.Children.Count - 1; }
internal void Start() { updateConcernBids = this.UpdateConcernBids; elRoot = this.KnowledgeBase().ELRoot; this.perceptionRoot = elRoot / Symbol.Intern("perception"); this.conversationalSpace = perceptionRoot / Symbol.Intern("conversational_space"); this.socialSpace = perceptionRoot / Symbol.Intern("social_space"); this.motorRoot = elRoot / Symbol.Intern("motor_state"); this.eventHistory = elRoot / Symbol.Intern("event_history"); this.lastDestination = elRoot / Symbol.Intern("last_destination"); ELNode.Store(lastDestination % null); // Need a placeholder last destination so that /last_destination/X doesn't fail. if (string.IsNullOrEmpty(CharacterName)) CharacterName = name; if (!KB.Global.IsTrue("register_character", gameObject, Symbol.Intern(CharacterName))) throw new Exception("Can't register prop " + name); try { gameObject.IsTrue(Symbol.Intern("do_all_character_initializations")); } catch (Exception e) { Debug.LogError("Exception while initializing character "+gameObject.name); Debug.LogException(e); } }
public void SetKB(KnowledgeBase kb) { root = kb.ELRoot; displayChildren.Add(root); WindowTitle = kb.Name + " KB"; }
private static bool TryExclusiveQuery( out ELNode foundNode, out ELNodeEnumerator enumerator, ELNode parentNode, ELNodeEnumerator parentEnumerator, object key, LogicVariable v) { // // Expression is Parent:Something // if (parentNode != null) { return TryExclusiveQueryDeterministicParent(out foundNode, out enumerator, parentNode, key, v); } return TryExclusiveQueryEnumeratedParent(out foundNode, out enumerator, parentEnumerator, key, v); }
private float RenderAt(ELNode node, float x, float y) { stringBuilder.Length = 0; var go = node.Key as GameObject; stringBuilder.Append(go != null ? ('$'+go.name) : (node.Key == null? "null" : node.Key.ToString())); stringBuilder.Append(node.ModeString); var suppressChildren = node.Children.Count > 1 && !displayChildren.Contains(node); if (suppressChildren) stringBuilder.Append(" ..."); var key = new GUIContent(stringBuilder.ToString()); var size = Style.CalcSize(key); if (mouseClicked && mouseClickY >= y && mouseClickY < y + size.y) ToggleNode(node); GUI.Label(new Rect(x, y, size.x, size.y), key, Style); x += size.x; if (node.Children.Count == 0 || suppressChildren) y += size.y; else foreach (var child in node.Children) { y = this.RenderAt(child, x, y); } return y; }
private void ToggleNode(ELNode node) { if (displayChildren.Contains(node)) displayChildren.Remove(node); else { displayChildren.Add(node); } }
void UpdateConcernBids(ELNode concern) { // Make sure this isn't the EL root (it's not an actual concern node). if (concern.Key != null) { ELNode bids; if (concern.TryLookup(SLocationBids, out bids)) { // Add its bids in foreach (var bid in bids.Children) { var destination = bid.Key as GameObject; if (destination == null) throw new Exception("Location bid is not a GameObject: "+bid.Key); var bidValue = Convert.ToSingle(bid.ExclusiveKeyValue<object>()); if (bidTotals.ContainsKey(destination)) bidTotals[destination] += bidValue; else bidTotals[destination] = bidValue; } } } }
/// <summary> /// Update the set of character's within this characters' conversational space /// and generate any necessary enter/leave events. /// </summary> private void UpdateSpace(Collider2D[] colliders, float radius, ELNode statusNode, string enterEvent, string exitEvent, bool updateNobodySpeaking) { var characterCount = Physics2D.OverlapCircleNonAlloc( transform.position, radius, colliders, 1 << gameObject.layer); if (characterCount==MaxConversationalSpaceColliders) throw new Exception("Too many colliders in conversational space!"); // Clean out entries that are no longer in the area statusNode.DeleteAll( node => { // Look to see if node's key (a character) appears in the colliders for (var i = 0; i<characterCount;i++) if (ReferenceEquals(node.Key, colliders[i].gameObject)) return false; // It doesn't, so the character left this character's conversational space. // Tell this character about it QueueEvent(exitEvent, node.Key); // Remove the character return true; }); // Add new entries for (var i = 0; i<characterCount;i++) { var character = colliders[i].gameObject; if (character != gameObject && !statusNode.ContainsKey(character) && myCurrentRoom.Contains(character)) { // The character just arrived in this character's conversational space // Tell this character QueueEvent(enterEvent, character); // Update the KB ELNode.Store(statusNode/character); } } if (updateNobodySpeaking) { bool nobodySpeaking = true; for (var i = 0; i<characterCount; i++) if (colliders[i].GetComponent<SimController>().IsSpeaking) nobodySpeaking = false; if (nobodySpeaking) ELNode.Store(perceptionRoot/SNobodySpeaking); else { if (perceptionRoot.ContainsKey(SNobodySpeaking)) { perceptionRoot.DeleteKey(SNobodySpeaking); pollActions = true; } } } }
/// <summary> /// Update the set of character's within this characters' conversational space /// and generate any necessary enter/leave events. /// </summary> private void UpdateSpace(Collider2D[] colliders, float radius, ELNode statusNode, string enterEvent, string exitEvent, bool updateNobodySpeaking) { var characterCount = Physics2D.OverlapCircleNonAlloc( transform.position, radius, colliders, 1 << gameObject.layer); if (characterCount == MaxConversationalSpaceColliders) { throw new Exception("Too many colliders in conversational space!"); } // Clean out entries that are no longer in the area statusNode.DeleteAll( node => { // Look to see if node's key (a character) appears in the colliders for (var i = 0; i < characterCount; i++) { if (ReferenceEquals(node.Key, colliders[i].gameObject)) { return(false); } } // It doesn't, so the character left this character's conversational space. // Tell this character about it QueueEvent(exitEvent, node.Key); // Remove the character return(true); }); // Add new entries for (var i = 0; i < characterCount; i++) { var character = colliders[i].gameObject; if (character != gameObject && !statusNode.ContainsKey(character) && myCurrentRoom != null && myCurrentRoom.Contains(character)) { // The character just arrived in this character's conversational space // Tell this character QueueEvent(enterEvent, character); // Update the KB ELNode.Store(statusNode / character); } } if (updateNobodySpeaking) { bool nobodySpeaking = true; for (var i = 0; i < characterCount; i++) { if (colliders[i].GetComponent <SimController>().IsSpeaking) { nobodySpeaking = false; } } if (currentlySpeaking) { nobodySpeaking = false; } if (nobodySpeaking) { ELNode.Store(perceptionRoot / SNobodySpeaking); } else { if (perceptionRoot.ContainsKey(SNobodySpeaking)) { perceptionRoot.DeleteKey(SNobodySpeaking); pollActions = true; } } } }
public ELNodeEnumeratorBindAndUnbindVariable(ELNode child, LogicVariable v) { this.child = child; this.variable = v; }
private static bool TryExclusiveQueryDeterministicParent( out ELNode foundNode, out ELNodeEnumerator enumerator, ELNode parentNode, object key, LogicVariable v) { // Deterministic parent path // UniqueParent:Something if (parentNode.IsNonExclusive) { throw new ELNodeExclusionException("Exclusive query of an non-exclusive node", parentNode, key); } if (v == null) { // Deterministic child path // UniqueParent:Key enumerator = null; return parentNode.TryLookup(key, out foundNode); } // Enumerated child path // UniqueParent:Variable if (parentNode.Children.Count > 0) { foundNode = null; enumerator = new ELNodeEnumeratorBindAndUnbindVariable(parentNode.Children[0], v); return true; } // parentNode is exclusive, but is childless, so we can't match. foundNode = null; enumerator = null; return false; }
public ELNodeEnumeratorBindFixedNodeToVariable(ELNode node, LogicVariable variableToBind) { this.node = node; this.variableToBind = variableToBind; }
private static bool TryExclusiveQueryEnumeratedParent( out ELNode foundNode, out ELNodeEnumerator enumerator, ELNodeEnumerator parentEnumerator, object key, LogicVariable v) { // Non-deterministic parent path // NonUniqueParent:Something foundNode = null; enumerator = (v == null) ? new ELNodeEnumeratorEnumerateParentAndLookupExclusiveKey(parentEnumerator, key) : (parentEnumerator.BindsVar(v)? (ELNodeEnumerator)new ELNodeEnumeratorPreboundVariable(parentEnumerator, v, true) : new ELNodeEnumeratorEnumerateParentAndBindVariable(parentEnumerator, v)); return true; }
internal void Start() { updateConcernBids = this.UpdateConcernBids; elRoot = this.KnowledgeBase().ELRoot; this.perceptionRoot = elRoot / Symbol.Intern("perception"); this.locationRoot = perceptionRoot / Symbol.Intern("location"); this.conversationalSpace = perceptionRoot / Symbol.Intern("conversational_space"); this.socialSpace = perceptionRoot / Symbol.Intern("social_space"); this.motorRoot = elRoot / Symbol.Intern("motor_state"); this.physiologicalStates = elRoot / Symbol.Intern("physiological_states"); this.eventHistory = elRoot / Symbol.Intern("event_history"); this.lastDestination = elRoot / Symbol.Intern("last_destination"); ELNode.Store(lastDestination % null); // Need a placeholder last destination so that /last_destination/X doesn't fail. if (string.IsNullOrEmpty(CharacterName)) CharacterName = name; if (!KB.Global.IsTrue("register_character", gameObject, Symbol.Intern(CharacterName), Symbol.Intern((Type)))) throw new Exception("Can't register character " + name); }
private void InitiateAction(object action) { if (action == null) { return; } var actionCopy = Term.CopyInstantiation(action); ELNode.Store(motorRoot / SLastAction % actionCopy); var structure = action as Structure; if (structure != null) { switch (structure.Functor.Name) { case "face": Face(structure.Argument <GameObject>(0)); break; case "say": // Say a fixed string Say(structure.Argument <string>(0), gameObject); break; case "cons": // It's a list of actions to initiate. InitiateAction(structure.Argument(0)); InitiateAction(structure.Argument(1)); break; case "pause": pauseUntil = Time.time + Convert.ToSingle(structure.Argument(0)); break; case "pickup": { var patient = structure.Argument <GameObject>(0); if (patient == gameObject) { throw new InvalidOperationException(name + ": tried to pickup() self!"); } if (patient == gameObject) { return; } if (patient == null) { throw new NullReferenceException("Argument to pickup is not a gameobject"); } var physob = patient.GetComponent <PhysicalObject>(); if (physob == null) { throw new NullReferenceException("Argument to pickup is not a physical object."); } physob.MoveTo(gameObject); break; } case "ingest": { var patient = structure.Argument <GameObject>(0); if (patient == null) { throw new NullReferenceException("Argument to ingest is not a gameobject"); } var physob = patient.GetComponent <PhysicalObject>(); if (physob == null) { throw new NullReferenceException("Argument to ingest is not a physical object."); } physob.Destroy(); // TODO: FIX LOCATION UPDATE SO WE DON'T NEED TO KLUGE THIS locationRoot.DeleteKey(patient); var propinfo = patient.GetComponent <PropInfo>(); if (propinfo != null) { if (propinfo.IsFood) { physiologicalStates.DeleteKey(Symbol.Intern("hungry")); } if (propinfo.IsBeverage) { physiologicalStates.DeleteKey(Symbol.Intern("thirsty")); } } break; } case "putdown": { var patient = structure.Argument <GameObject>(0); if (patient == gameObject) { throw new InvalidOperationException(name + ": tried to putdown() self!"); } if (patient == null) { throw new NullReferenceException("Argument to putdown is not a gameobject"); } var physob = patient.GetComponent <PhysicalObject>(); if (physob == null) { throw new NullReferenceException("Argument to putdown is not a physical object."); } var dest = structure.Argument <GameObject>(1); if (dest == null) { throw new NullReferenceException("Argument to putdown is not a gameobject"); } physob.MoveTo(dest); break; } case "flash": { flashColorA = structure.Argument <Color>(0); flashColorB = structure.Argument <Color>(1); flashPeriod = Convert.ToSingle(structure.Argument(2)); flashStartTime = Time.time; flashEndTime = flashStartTime + Convert.ToSingle(structure.Argument(3)); break; } case "get_in": GetIn(structure.Argument <GameObject>(0)); break; case "dismount": Dismount(); break; case "end_game": Application.Quit(); break; default: // Assume it's dialog this.IsTrue("log_dialog_act", structure); GameObject thisAddressee = ((structure.Arity >= 2) ? structure.Argument(1) as GameObject : gameObject) ?? gameObject; var talkingToSelf = thisAddressee == gameObject; if (!talkingToSelf || ShowMentalMonologue) { var textVar = new LogicVariable("DialogText"); object text = null; try { text = gameObject.SolveFor(textVar, "generate_text", structure, textVar); } catch (Exception e) { Debug.LogError(string.Format("Exception while generating text for {0}", gameObject.name)); Debug.LogException(e); } var textString = text as string; if (textString == null) { throw new Exception( "generate_text returned " + ISOPrologWriter.WriteToString(text) + " for " + ISOPrologWriter.WriteToString(structure)); } var talkingToPlayer = structure.Arity >= 2 && ReferenceEquals(structure.Argument(1), playerSymbol); SetSpeechTimeout(textString); if (talkingToPlayer) // Character is talking to zhimself { if (nlPrompt != null) { nlPrompt.OutputToPlayer(textString); } else { Say(string.Format("({0})", textString), thisAddressee); } } else { Say(textString, thisAddressee); } if (!talkingToPlayer && !talkingToSelf) { // Tell the other characters foreach (var node in socialSpace.Children) { var character = (GameObject)(node.Key); if (character != gameObject) { character.QueueEvent((Structure)Term.CopyInstantiation(structure)); } } // TODO: fix it so that when characters appear, the system computes their social // spaces from scratch. Then we won't need this kluge. if (!socialSpace.ContainsKey(thisAddressee)) { thisAddressee.QueueEvent((Structure)Term.CopyInstantiation(structure)); } } } break; } if (structure.Functor.Name != "pause") { // Report back to the character that the action has occurred. QueueEvent(structure); } } else { throw new InvalidOperationException("Unknown action: " + ISOPrologWriter.WriteToString(action)); } }