Exemplo n.º 1
0
    private float calcScore(FlockControl.UnityState us, BirdControl me)
    {
        float score = 0;

        float gd = (us.goal.transform.position - transform.position).magnitude;

        score += GOAL_CONST * Mathf.Min(ASYMPTOTE, 1 / Mathf.Sqrt(gd));

        if (!me.Moving)
        {
            return(score);
        }

        foreach (BirdControl b in us.birds)
        {
            if (b.Equals(me) || !b.Moving)
            {
                continue;
            }

            float d = me.GetDistance(b).dist;
            score += BIRD_CONST * Mathf.Min(ASYMPTOTE, 1 / Mathf.Sqrt(d));
        }

        for (int i = 0; i < us.walls.Length; i++)
        {
            float d = me.WallDistance(i).dist;
            score += WALL_CONST * Mathf.Min(ASYMPTOTE, 1 / Mathf.Sqrt(d));
        }

        return(score);
    }
    private Vector2 cohesion(BirdControl[] birds, BirdControl me)
    {
        Vector2 force = Vector2.zero;

        foreach (BirdControl b in birds)
        {
            if (b.Equals(me) || !b.Moving)
            {
                continue;
            }
            BirdControl.CachedDelta cd = me.GetDistance(b);
            if (cd.dist > genome.Cohesion.Distance)
            {
                continue;
            }
            force += calcForce(cd.norm, cd.dist, genome.Cohesion);
        }
        return(force);
    }
    private Vector2 repulsion(BirdControl[] birds, float[] forces, BirdControl me)
    {
        Vector2 force = Vector2.zero;

        foreach (BirdControl b in birds)
        {
            if (b.Equals(me) || !b.Moving)
            {
                continue;
            }

            BirdControl.CachedDelta cd = me.GetDistance(b);
            if (cd.dist > genome.Repulse.Distance)
            {
                continue;
            }
            force += calcForce(-1 * cd.norm, cd.dist, genome.Repulse);            // * forces[b.Number];
        }
        return(force);
    }
    private Vector2 aligment(BirdControl[] birds, float[] forces, BirdControl me)
    {
        Vector2 force = Vector2.zero;

        foreach (BirdControl b in birds)
        {
            if (b.Equals(me) || !b.Moving)
            {
                continue;
            }

            BirdControl.CachedDelta cd = me.GetDistance(b);
            if (cd.dist > genome.Align.Distance)
            {
                continue;
            }
            float mag = calcForce(cd.norm, cd.dist, genome.Align).magnitude;            // * forces[b.Number];
            force += b.Velocity.normalized * mag;
        }
        return(force);
    }
    private void generateRewards(FlockControl.UnityState us)
    {
        int pathfindTokens = PATHFIND_TOKENS;

        rewardForces = new Vector2[us.birds.Length];
        bool[] nextGotToken = new bool[us.birds.Length];

        /* In this function, we give away a number of tokens equal to PATHFIND_TOKENS to birds so that they use the more computational expensive pathfinding.
         * We prioritize the birds that previously received tokens, then birds with no leaders, but we want to make sure that as the number of active birds falls,
         * we still give away all of our tokens to birds that are active. If we have more tokens than active birds, every bird should use pathfinding.
         */

        // First we give priority to birds that are already holding tokens
        for (int bird = 0; bird < us.birds.Length; bird++)
        {
            BirdControl me = us.birds [bird];
            if (!gotRewardToken [bird] || !me.Moving)
            {
                continue;
            }
            if (Random.value > genome.Pathfind.Carryover)
            {
                continue;
            }
            // This bird had a token and carries it over in this frame
            pathfindTokens = giveToken(us, bird, pathfindTokens, nextGotToken);
        }

        // Then we prioritize birds with no leaders
        int[] birdIndex = range(us.birds.Length);
        shuffle(birdIndex);
        for (int i = 0; i < birdIndex.Length && pathfindTokens > 0; i++)
        {
            int         bird = birdIndex [i];
            BirdControl me   = us.birds [bird];
            if (!me.Moving || nextGotToken [bird])
            {
                continue;
            }

            bool hasLeader = false;
            foreach (BirdControl b in us.birds)
            {
                if (b.Equals(me) || !b.Moving)
                {
                    continue;
                }

                float dist = me.GetDistance(b).dist;
                // Distance here is used a bit differently than in other cases, but it is trained just the same and does not result in any issues.
                if (dist > genome.Pathfind.Distance)
                {
                    continue;
                }

                hasLeader = hasLeader || inView(b, me);
            }

            if (hasLeader)
            {
                continue;
            }
            // This bird has no leader so use a token
            pathfindTokens = giveToken(us, bird, pathfindTokens, nextGotToken);
        }

        // Now we give out the rest of the tokens randomly
        birdIndex = range(us.birds.Length);
        shuffle(birdIndex);
        for (int i = 0; i < birdIndex.Length && pathfindTokens > 0; i++)
        {
            int         bird = birdIndex [i];
            BirdControl me   = us.birds [bird];
            if (!me.Moving || nextGotToken [bird])
            {
                continue;
            }
            // This bird has received a token through random chance
            pathfindTokens = giveToken(us, bird, pathfindTokens, nextGotToken);
        }

        // The remainder of the birds do not receive tokens and so just do simple pathfinding towards the goal
        for (int bird = 0; bird < us.birds.Length; bird++)
        {
            BirdControl me = us.birds [bird];
            if (!me.Moving)
            {
                continue;
            }
            if (nextGotToken [bird])
            {
                // This bird already received a token
                continue;
            }
            rewardForces [bird] = rewardSimple(us.goal.transform.position, me);
        }

        gotRewardToken = nextGotToken;
    }