Beispiel #1
0
 /// <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));
     }
 }
Beispiel #2
0
 private void SetSpeechTimeout(string speech)
 {
     currentlySpeaking = true;
     ELNode.Store(motorRoot / SIAmSpeaking);
     clearSpeechTime = Time.time
                       + Math.Max(
         SpeechDelayMinimum,
         Math.Min(SpeechDelayMaximum, speech.Length * SpeechDelaySecondsPerChar));
 }
Beispiel #3
0
    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));
                    }
                }
            }
        }
    }
Beispiel #4
0
    void UpdateLocomotionBidsAndPath()
    {
        //foreach (var pair in bidTotals)
        //    bidTotals[pair.Key] = 0;
        bidTotals.Clear();
        elRoot.WalkTree(SConcerns, 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 != null && currentPath != null && !CurrentDestination.DockingTiles().Contains(currentPath.FinalTile)))
            {
                if (newDestination)
                {
                    Dismount();
                    ELNode.Store(eventHistory / new Structure("goto", winner)); // Log change for debugging purposes.
                }
                CurrentDestination = winner;
                if (currentDestination.DockingTiles().Contains(gameObject.TilePosition()))
                {
                    QueueEvent("arrived_at", currentDestination);
                }
                else
                {
                    currentPath = planner.Plan(gameObject.TilePosition(), CurrentDestination.DockingTiles());
                }
            }
        }
    }
Beispiel #5
0
    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));
                    }
                }
            }
        }
    }
Beispiel #6
0
 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));
     }
 }
Beispiel #7
0
    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));
        }
    }
Beispiel #8
0
    /// <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;
                }
            }
        }
    }