Example #1
0
        public float CalculateSEUtility(DriveType mainDriveType, Agent agent, Mapping mapping)
        {
            Entity target = GetEntityTarget(agent, mapping);
            float  amount = outputChangeType.CalculateAmount(agent, target, this, mapping);

            mapping.previousOutputChangeAmount = amount;

            float utility = outputChangeType.CalculateSEUtility(agent, target, this, mapping, mainDriveType, amount);

            // See if this change will also change any of the usesEquation Drives
            float equationDrivesUtility = 0f;

            foreach (DriveType driveType in agent.ActiveDrives().Keys)
            {
                // If this drive is the main drive for the plan it should not be considered a side-effect
                // it will be considered in the rate of drive change for the plan
                if (driveType.syncType == DriveType.SyncType.Equation && driveType != mainDriveType && driveType.includeInSECalculations)
                {
                    // Only looks at this specfic OutputChange
                    float equationDrivesAmount = driveType.driveTypeEquation.CalculateEquationDriveLevelChange(agent, driveType, mapping, this);

                    // DriveType to figure this change of drive level into the side effect utility
                    // TODO: Just use value for now since the other side effects use value - add in utility later
                    equationDrivesUtility += equationDrivesAmount * (driveType.sideEffectValue < 0.01f ? 1f : driveType.sideEffectValue);
                }
            }
            //Debug.Log(agent.name + ": " + mapping.mappingType.name + ": val: " + value + " amt: " + amount + " equ utl: " + equationDrivesUtility + " tot: " + (value * amount - equationDrivesUtility));
            //Debug.Log(value + " * " + amount + " - " + equationDrivesUtility);

            // Subtract the equationDrivesUtility since a positive value is bad (drive increases) and a negative value is good (drive decreases)
            return(utility - equationDrivesUtility);
        }
Example #2
0
        private void SwitchToAgent(int agentIndex)
        {
            agent = agents[agentIndex];

            // Change virtual camera to follow newly selected agent
            //vCamera.Follow = agent.transform;

            driveSliders = new List <Slider>();
            Transform driveTypeParent = transform.Find("DriveType Levels");

            foreach (Transform child in driveTypeParent)
            {
                Destroy(child.gameObject);
            }

            int i = 0;

            foreach (DriveType driveType in agent.ActiveDrives().Keys)
            {
                if (driveType.showInUI)
                {
                    RectTransform newDriveType = Instantiate(driveTypeSliderPrefab, driveTypeParent);
                    newDriveType.transform.position = new Vector3(newDriveType.transform.position.x, newDriveType.transform.position.y - 30 * i);
                    newDriveType.GetComponentInChildren <TextMeshProUGUI>().text = driveType.name;

                    driveSliders.Add(newDriveType.GetComponentInChildren <Slider>());
                    ++i;
                }
            }
        }
Example #3
0
        public override bool Check(InputCondition inputCondition, Agent agent, Mapping mapping, Entity target, bool isRecheck)
        {
            Agent targetAgent = target as Agent;

            if (targetAgent != null)
            {
                DriveType driveType = (DriveType)inputCondition.levelType;
                if (targetAgent.ActiveDrives().ContainsKey(driveType))
                {
                    float driveLevel = targetAgent.drives[driveType].GetLevel();
                    if (driveLevel >= inputCondition.min && driveLevel <= inputCondition.max)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Example #4
0
        public virtual bool GetPlans(Agent agent, Plans previousPlans, int previousPlansIndex, bool previouslyInterrupted,
                                     out DriveType currentDriveType, out Dictionary <DriveType, float> currentDriveTypesRanked,
                                     out Dictionary <DriveType, Plans> allPlans)
        {
            currentDriveType = null;
            Plans currentPlans = null;

            // Find mapping for highest priority drive
            currentDriveTypesRanked = RankDrives(agent.ActiveDrives());

            allPlans = new Dictionary <DriveType, Plans>();
            foreach (DriveType driveType in currentDriveTypesRanked.Keys)
            {
                currentPlans = plannerTypes[0].CreatePlansForDriveType(agent, driveType, false);
                if (currentPlans == null)
                {
                    return(false);
                }

                allPlans.Add(driveType, currentPlans);

                //Debug.Log(agent.name + ": GetPlans for " + driveType.name + " found " + currentPlans.rootMappings.Count + " plans.");

                // If there is at least one complete plan we quit early
                // TODO: Improve this - planner should mark the Plans statuses
                // TODO: Add a minimum utility threshold so it doesn't quit and go with a bad plan
                List <Mapping> excludeRootMappings = null;
                if (previouslyInterrupted && previousPlans != null)
                {
                    excludeRootMappings = new List <Mapping>()
                    {
                        previousPlans.rootMappings[previousPlansIndex]
                    }
                }
                ;
                if (currentPlans.GetCompletePlans(excludeRootMappings).Count > 0)
                {
                    //Debug.Log(agent.name + ": GetPlans for " + driveType.name + " found a completed plan.");
                    currentDriveType = driveType;
                    return(true);
                }
            }
            return(false);
        }
Example #5
0
        void Update()
        {
            if (Input.GetKeyDown("p"))
            {
                if (Time.timeScale == 1)
                {
                    Time.timeScale = 0;
                }
                else
                {
                    Time.timeScale = 1;
                }
            }

            if (!EventSystem.current.IsPointerOverGameObject())
            {
                if (selectedEntityType != null)
                {
                    Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                    RaycastHit hit;
                    if (Physics.Raycast(ray, out hit, 300, LayerMask.GetMask("Ground", "WorldObject")))
                    {
                        Vector3 locationOnGrid = hit.point;
                        if (terrainActions != null)
                        {
                            locationOnGrid = terrainActions.FindGridLocation(hit.point, currentBuildHeight);
                        }
                        //Vector3 locationOnGrid = terrainActions.FindGridLocation(hit.point, currentBuildHeight);

                        locationOnGrid.y = hit.point.y;

                        // Place selected entity outline in the world at hit location
                        if (entityGhost != null)
                        {
                            if (!entityGhost.activeSelf)
                            {
                                entityGhost.SetActive(true);
                            }
                            entityGhost.transform.position = locationOnGrid;

                            // TODO: What about moving agents? - Do a OnTriggerEnter for the ghosts which could just clear out previousGhostPosition
                            if (previousGhostPosition != entityGhost.transform.position)
                            {
                                buildableStatus = GetBuildableStatus(selectedEntityType, entityGhost);
                                if (selectedEntityType.rotateToTerrain)
                                {
                                    // Rotate and transform ghost so that it is just above the terrain
                                    entityGhost.transform.up = hit.normal;
                                }
                                else if (terrainActions != null)
                                {
                                    // Calculate distance to move entityGhost in its up direction (normal to terrain)
                                    terrainActions.MoveObjectAboveTerrain(entityGhost);
                                }

                                previousGhostPosition = entityGhost.transform.position;

                                //TODO: Makes a utility function for changing all of a nested objects materials
                                Renderer[] renderers = entityGhost.GetComponentsInChildren <Renderer>();
                                if (renderers.Length == 0)
                                {
                                    Debug.LogError("Entity Ghost has no renderer! " + entityGhost.name);
                                }

                                Material material;
                                if (buildableStatus == BuildableStatus.Invalid)
                                {
                                    material = invalidPlacementMaterial;
                                }
                                else
                                {
                                    material = validPlacementMaterial;
                                }

                                for (int i = 0; i < renderers.Length; i++)
                                {
                                    if (renderers[i].material != material)
                                    {
                                        Material[] materials = new Material[renderers[i].materials.Length];
                                        for (var j = 0; j < renderers[i].materials.Length; j++)
                                        {
                                            materials[j] = material;
                                        }
                                        renderers[i].materials = materials;
                                    }
                                }
                            }

                            if (Input.GetKeyDown("r"))
                            {
                                entityGhost.transform.Rotate(new Vector3(0, 90, 0));
                                previousGhostPosition = Vector3.zero;
                            }
                        }
                        if (Input.GetMouseButtonDown(0))
                        {
                            Quaternion rotation = Quaternion.identity;
                            Vector3    scale    = Vector3.one;
                            if (entityGhost != null)
                            {
                                rotation = entityGhost.transform.rotation;
                                scale    = entityGhost.transform.localScale;

                                // TODO: Fix this so its not so much of a hack - the .02 prevents the flashing from ghost over placed object
                                // Could make every ghost be .02 larger and then always subtract .02 - also only do scale is FI can be scaled
                                if (scale.x.ToString().IndexOf(".02") != -1)
                                {
                                    scale.x = Mathf.Round(scale.x);
                                    scale.y = Mathf.Round(scale.y);
                                    scale.z = Mathf.Round(scale.z);
                                }
                            }

                            // Create Entity with owner permissions set to selected faction and the selected agent if not in overhead view
                            List <Agent> owners = new List <Agent>();
                            //if (!overheadCamera.enabled)
                            //    owners.Add(agent);
                            GameObject newGameObject;
                            if (entityGhost != null)
                            {
                                newGameObject = selectedEntityType.CreateEntity(prefabVariantIndex, entityGhost.transform.position, rotation, scale, agent);
                            }
                            else
                            {
                                newGameObject = selectedEntityType.CreateEntity(prefabVariantIndex, locationOnGrid, rotation, scale, agent);
                            }

                            if (selectedEntityType is AgentType)
                            {
                                // Add agent to the list of agents
                                newGameObject.name = selectedEntityType.name;
                                Agent a = newGameObject.GetComponent <Agent>();
                                agents.Add(a);
                                AddAgent(a);
                            }
                        }
                    }
                    else if (entityGhost != null && entityGhost.activeSelf)
                    {
                        entityGhost.SetActive(false);
                    }
                }
                else
                {
                    // No Entity Selected - Allow player to select entities with mouse click
                    // TODO: Add a create box select (hold mouse button down) and multi-entity select
                    if (Input.GetMouseButtonDown(0))
                    {
                        Debug.Log("Mouse Button Clicked");
                        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

                        Entity entity = null;
                        if (for2D)
                        {
                            RaycastHit2D[] hits = Physics2D.RaycastAll(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero,
                                                                       LayerMask.GetMask("Agent", "WorldObject", "AgentEvent"));
                            if (hits.Length > 0)
                            {
                                float bestDistance = float.PositiveInfinity;
                                foreach (RaycastHit2D hit in hits)
                                {
                                    if (hit.distance < bestDistance)
                                    {
                                        Entity[] hitEntities = hit.collider.gameObject.GetComponentsInParent <Entity>();
                                        foreach (Entity hitEntity in hitEntities)
                                        {
                                            if (hitEntity.inEntityInventory == null && hitEntity.enabled)
                                            {
                                                bestDistance = hit.distance;
                                                entity       = hitEntity;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            RaycastHit[] hits = Physics.RaycastAll(ray, 500, LayerMask.GetMask("Agent", "WorldObject", "AgentEvent"),
                                                                   QueryTriggerInteraction.Collide);
                            if (hits.Length > 0)
                            {
                                float bestDistance = float.PositiveInfinity;
                                foreach (RaycastHit hit in hits)
                                {
                                    if (hit.distance < bestDistance)
                                    {
                                        Entity[] hitEntities = hit.collider.gameObject.GetComponentsInParent <Entity>();
                                        foreach (Entity hitEntity in hitEntities)
                                        {
                                            if (hitEntity.inEntityInventory == null && hitEntity.enabled)
                                            {
                                                bestDistance = hit.distance;
                                                entity       = hitEntity;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (driveSliders == null)
            {
                Transform driveTypeParent = transform.Find("DriveType Levels");

                driveSliders = new List <Slider>();
                int i = 0;
                foreach (DriveType driveType in agent.ActiveDrives().Keys)
                {
                    if (driveType.showInUI)
                    {
                        RectTransform newDriveType = Instantiate(driveTypeSliderPrefab, driveTypeParent);
                        newDriveType.transform.position = new Vector3(newDriveType.transform.position.x, newDriveType.transform.position.y - 30 * i);
                        newDriveType.GetComponentInChildren <TextMeshProUGUI>().text = driveType.name;

                        driveSliders.Add(newDriveType.GetComponentInChildren <Slider>());
                        ++i;
                    }
                }
            }

            driveText.text = "";
            int sliderIndex = 0;

            foreach (var drive in agent.ActiveDrives())
            {
                if (drive.Key.name != "None" && drive.Key.showInUI)
                {
                    float driveLevel = drive.Value.GetLevel();
                    driveText.text += drive.Key.name + ": " + Mathf.Round(driveLevel) + "\n";
                    driveSliders[sliderIndex].value = driveLevel / 100f;
                    sliderIndex++;
                }
            }

            drivesRankedText.text = "";
            int driveNumber = 1;

            if (agent.decider.currentDriveTypesRanked != null)
            {
                foreach (KeyValuePair <DriveType, float> drive in agent.decider.currentDriveTypesRanked)
                {
                    drivesRankedText.text += driveNumber + ": " + drive.Key.name + " (" + System.Math.Round(drive.Value, 3) + ")\n";
                    ++driveNumber;
                }
            }

            if (agent.decider.CurrentDriveType != null)
            {
                drivesRankedText.text += "Current: " + agent.decider.CurrentDriveType.name + "\n";
            }
            else
            {
                drivesRankedText.text += "Current: None\n";
            }

            if (showAgentsMappingType)
            {
                for (int i = 0; i < markerTexts.Count; i++)
                {
                    if (!agents[i].gameObject.activeSelf)
                    {
                        if (agents[i] == agent)
                        {
                            HandleCameraSwitching(true);
                        }

                        agents.Remove(agents[i]);

                        GameObject item = markerTexts[i].gameObject;
                        markerTexts.Remove(markerTexts[i]);
                        Destroy(item);
                        continue;
                    }

                    SetMarkerAboveObject(agents[i].gameObject, markerTexts[i]);

                    markerTexts[i].color = Color.white;
                    if (agents[i].decider.CurrentMapping != null)
                    {
                        markerTexts[i].text = agents[i].decider.CurrentMapping.mappingType.name;
                    }
                    else
                    {
                        markerTexts[i].text = "None";
                    }

                    /*
                     * // TODO: Get this to float up and not cover the mappingType name
                     * HistoryType.OutputChangeLog outputChangeLog = agents[i].historyType.GetLastOutputChangeLog(agents[i]);
                     * if (outputChangeLog != null && outputChangeLog.time > Time.time - 2f)
                     * {
                     *  markerTexts[i].text = outputChangeLog.outputChange.ToString();
                     *  if (outputChangeLog.outputChange.floatValue != outputChangeLog.amount)
                     *      markerTexts[i].text += "\nActual Amount = " + outputChangeLog.amount;
                     *  if (outputChangeLog.succeeded)
                     *      markerTexts[i].color = Color.green;
                     *  else
                     *      markerTexts[i].color = Color.red;
                     * }
                     */
                }
            }

            HandleCameraSwitching();

            // TODO: Only do this every X seconds
            nameText.text = agent.name + " - " + agent.CurrentAge();
            timeText.text = timeManager.PrettyPrintDateTime();
        }
Example #6
0
        // Agent is acting - should the current Mapping be interrupted?
        // This will not start a new plan - it will just cause the current plan to stop and then plan next time
        public virtual bool ShouldInterrupt(Agent agent, Mapping currentMapping, DriveType currentDriveType, float currentPlanUtility,
                                            float lastReplanTime, out float newReplanTime)
        {
            newReplanTime = lastReplanTime;

            if (currentMapping.mappingType.actionType.interruptType == ActionType.InterruptType.Never)
            {
                return(false);
            }

            if (currentMapping.mappingType.actionType.replanFrequency > Time.time - lastReplanTime)
            {
                return(false);
            }

            // Replan and see if there is reason to switch up plans
            newReplanTime = Time.time;

            // Find mapping for highest priority drive
            Dictionary <DriveType, float> currentDriveTypesRanked = RankDrives(agent.ActiveDrives());

            Plans currentPlans;

            foreach (DriveType driveType in currentDriveTypesRanked.Keys)
            {
                if ((currentMapping.mappingType.actionType.interruptType == ActionType.InterruptType.Always) ||
                    (currentMapping.mappingType.actionType.interruptType == ActionType.InterruptType.OnlyDrivesThatCanInterrupt && driveType.canCauseInterruptions) ||
                    (currentMapping.mappingType.actionType.interruptType == ActionType.InterruptType.OnlySpecifiedDrives &&
                     currentMapping.mappingType.actionType.interruptingDriveTypes.Contains(driveType)))
                {
                    Debug.Log(agent.name + ": Checking to see if should interrupt " + currentMapping + " for " + driveType);
                    currentPlans = plannerTypes[0].CreatePlansForDriveType(agent, driveType, true);
                    Mapping bestRootMapping = GetBestPlan(agent, currentPlans, out float bestUtility);

                    // TODO: Should this log the generated Plans?

                    // If it finds one plan that is good enough then interrupt
                    List <Mapping> rootMappings = currentPlans.GetCompletePlans();
                    if (rootMappings.Count > 0)
                    {
                        foreach (Mapping rootMapping in rootMappings)
                        {
                            // Since this is in the middle of the action the last planning utility calculation for current plan
                            // Should be good enough - but it might make sense to recalulate the utility for the current plan
                            if (bestUtility - currentPlanUtility > currentMapping.mappingType.actionType.minGreaterUtilityToInterrupt)
                            {
                                Debug.Log(agent.name + ": Found better plan - interrupting " + currentMapping);
                                Debug.Log(agent.name + ": New Root Mapping " + rootMapping);
                                Debug.Log(agent.name + ": Utility change: " + currentPlanUtility + " -> " + bestUtility);
                                plannerTypes[0].NotifyOfInterrupt(agent, currentPlans, rootMapping);
                                return(true);
                            }
                            else
                            {
                                Debug.Log(agent.name + ": NOT interrupting " + currentMapping);
                                Debug.Log(agent.name + ": Checked Root Mapping " + rootMapping);
                                Debug.Log(agent.name + ": Utility change: " + currentPlanUtility + " -> " + bestUtility);
                                agent.historyType.RecordDeciderLog(agent, HistoryType.DeciderRunType.PlannedNoInterrupt, currentMapping);
                            }
                        }
                    }
                }

                if (driveType == currentDriveType)
                {
                    // Don't consider DriveTypes ranked lower than the current DriveType
                    break;
                }
            }

            return(false);
        }