public override Vector2[] MakeDecisions(FlockControl.UnityState us) { generateRewards(us); Vector2[] sfs = new Vector2[us.birds.Length]; float[] mags = new float[sfs.Length]; for (int i = 0; i < us.birds.Length; i++) { if (!us.birds [i].Moving) { sfs [i] = Vector2.zero; mags [i] = 0; continue; } sfs [i] = getStaticForces(us, i); mags[i] = sfs[i].magnitude; } Vector2[] forces = new Vector2[us.birds.Length]; for (int i = 0; i < us.birds.Length; i++) { if (!us.birds [i].Moving) { forces [i] = Vector2.zero; continue; } Vector2 df = repulsion(us.birds, mags, us.birds [i]) + aligment(us.birds, mags, us.birds [i]); Vector2 f = sfs [i] + df; forces [i] = steer(us.birds [i], f); } return(forces); }
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); }
public void SetScore(FlockControl.UnityState us) { for (int i = 0; i < us.birds.Length; i++) { scores[i] = calcScore(us, us.birds[i]); } }
public void InitializeGrid(FlockControl.UnityState us) { graph = new List <GraphPoint>(); memoized = new Dictionary <GraphPoint, PathDistance>(); CircleCollider2D cd = GetComponent <CircleCollider2D>(); gameObject.transform.localScale = new Vector3(CHECK_DISTANCE * us.maxSize, CHECK_DISTANCE * us.maxSize); initCF(us); Collider2D[] others = new Collider2D[1]; grid = new bool[(int)(us.roomWidth), (int)(us.roomHeight)]; for (int x = 0; x < us.roomWidth; x++) { for (int y = 0; y < us.roomHeight; y++) { if (Vector2.SqrMagnitude(new Vector2(x, y) - (Vector2)us.goal.transform.position) < us.goal.transform.localScale.x * us.goal.transform.localScale.x) { grid [(int)x, (int)y] = true; continue; } transform.position = new Vector2(x, y); int hit = cd.OverlapCollider(cf, others); grid [x, y] = hit == 0; } } initGraph(us.goal.transform.position); }
public void InitializeGrid(FlockControl.UnityState us) { CircleCollider2D cd = GetComponent <CircleCollider2D>(); gameObject.transform.localScale = new Vector3(CHECK_DISTANCE * us.maxSize, CHECK_DISTANCE * us.maxSize); ContactFilter2D cf = new ContactFilter2D(); cf.useTriggers = true; cf.layerMask = LayerMask.GetMask("Wall"); cf.useLayerMask = true; Collider2D[] others = new Collider2D[NUM_COLLIDERS]; grid = new bool[(int)(us.roomWidth / GRID_STEP), (int)(us.roomHeight / GRID_STEP)]; for (float x = 0; x < us.roomWidth; x += GRID_STEP) { for (float y = 0; y < us.roomHeight; y += GRID_STEP) { transform.position = new Vector2(x, y); int hit = cd.OverlapCollider(cf, others); int gx = (int)(x / GRID_STEP); int gy = (int)(y / GRID_STEP); if (Vector2.SqrMagnitude(new Vector2(x, y) - (Vector2)us.goal.transform.position) < us.goal.transform.localScale.x * us.goal.transform.localScale.x) { grid [gx, gy] = true; continue; } grid [gx, gy] = hit == 0; } } // @Javiar: Foreach node in the grid, look at its eight neighbors // Also be sure to include the goal position in the graph you make, even though its neighbors will likely be in the grid }
private void initCF(FlockControl.UnityState us) { gameObject.transform.localScale = new Vector3(CHECK_DISTANCE * us.maxSize, CHECK_DISTANCE * us.maxSize); cf = new ContactFilter2D(); cf.useTriggers = true; cf.layerMask = LayerMask.GetMask("Wall"); cf.useLayerMask = true; }
private int giveToken(FlockControl.UnityState us, int bird, int tokens, bool[] nextGotToken) { nextGotToken [bird] = true; BirdControl me = us.birds [bird]; Vector2[] path = pf.CalculatePath(me); rewardForces [bird] = rewardPathfind(path, me); return(tokens - 1); }
public virtual Vector2[] MakeDecisions(FlockControl.UnityState us) { Vector2[] decisions = new Vector2[us.birds.Length]; for (int i = 0; i < decisions.Length; i++) { decisions [i] = Vector2.zero; } return(decisions); }
private Vector2 getStaticForces(FlockControl.UnityState us, int birdNumber) { BirdControl me = us.birds [birdNumber]; Vector2 cohes = cohesion(us.birds, me); Vector2 obstcl = obstacle(us.walls, me); Vector2 goal = rewardForces [me.Number]; Vector2 bndry = boundary(us, me); return(cohes + obstcl + goal + bndry); }
private Vector2 boundary(FlockControl.UnityState us, BirdControl me) { float xForce = 0; float yForce = 0; // Also, in this case, we are limiting the individual forces in the x and y dimensions to the force and distance of the genomes boundary // Whereas in other forces we limit the vector(x,y) to the corresponding parameters if (me.transform.position.x < us.roomWidth / 2) { float xDist = me.transform.position.x; if (xDist <= genome.Boundary.Distance) { xForce = genome.Boundary.Constant / Mathf.Pow(xDist, genome.Boundary.Exponent); } } else { float xDist = us.roomWidth - me.transform.position.x; if (xDist <= genome.Boundary.Distance) { xForce = -1 * genome.Boundary.Constant / Mathf.Pow(xDist, genome.Boundary.Exponent); } } if (me.transform.position.y < us.roomHeight / 2) { float yDist = me.transform.position.y; if (yDist <= genome.Boundary.Distance) { yForce = genome.Boundary.Constant / Mathf.Pow(yDist, genome.Boundary.Exponent); } } else { float yDist = us.roomHeight - me.transform.position.y; if (yDist <= genome.Boundary.Distance) { yForce = -1 * genome.Boundary.Constant / Mathf.Pow(yDist, genome.Boundary.Exponent); } } return(new Vector2(xForce, yForce)); }
public override void StartGeneration(FlockControl.UnityState us) { pf.InitializeGrid(us); genome = dna.Next(); gotRewardToken = new bool[us.birds.Length]; }
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; }
public virtual void StartGeneration(FlockControl.UnityState us) { }