static bool isJumpPossible(GeneColumn start, GeneColumn end) { if (start == null || end == null) { return(false); } int xBlockDistance = Mathf.Abs(start.GlobalX - end.GlobalX); int direction = start.GlobalX < end.GlobalX ? 1 : -1; GeneColumn iterator = start.SeekNthColumn(direction); float xPixelDistance = xBlockDistance * Global.TilePixelWidth; float d = xPixelDistance; float H = maxJumpHeight; float K = -4 * H / (d * d); for (int i = 1; i <= xBlockDistance; i++) { float xi = Global.TilePixelWidth * i; float yi = K * xi * (xi - d); int maxObstacleHeight = (int)(yi / Global.TilePixelWidth) + start.ObstacleHeight; if (maxObstacleHeight < iterator.ObstacleHeight) { return(false); } iterator = iterator.SeekNthColumn(direction); if (iterator == null) { return(false); } } return(true); }
public override String ToString() { String r = ""; if (CurrentChunkHead != null) { for (int j = MaxHeight - 1; j >= 0; j--) { r += $"{j,6:000000}: "; for (GeneColumn iterator = CurrentChunkHead; iterator != CurrentChunkTail; iterator = iterator.Next) { r += $"{iterator.CellAtY(j)}"; } r += "\n"; } int Width = CurrentChunkTail.GlobalX - CurrentChunkHead.GlobalX + 1; int digitosLargura = (Width - 1).ToString().Length; for (int digito = 0; digito < digitosLargura; digito++) { r += " "; for (int x = 0; x < Width; x++) { var xs = x.ToString(); r += xs.Length > digito ? $"{xs[digito]}" : "0"; } r += "\n"; } } return(r); }
private int getGroundFitness() { int groundFitness = 0; int holeLength = 0; for (GeneColumn x = this.Head.Next; x.Next != null; x = x.Next) { if (x.Previous.ObstacleHeight == 0) { holeLength++; if (holeLength > maxJumpStraightXDistance) { groundFitness -= 100; } } else { holeLength = 0; } var ghDiff = Mathf.Abs(x.Previous.ObstacleHeight - x.ObstacleHeight); if (ghDiff > maxBlockJumpHeight) { groundFitness -= 100 * ghDiff; } else { // The closer they are, the better groundFitness += 10 - (2 * ghDiff); } } return(groundFitness); }
private void mutateGroundHeightAtX(GeneColumn x) { var changeDirection = random.Next(2) == 1 ? 1 : -1; var shift = changeDirection; x.GroundHeight += shift; }
internal void Mutate(float mutationRate) { Random r = new Random(); for (GeneColumn x = GenerationHead; x != null && x.GlobalX <= GenerationTail.GlobalX; x = x.Next ) { if (r.NextDouble() < mutationRate) { // Ground mutation mutateGroundHeightAtX(x); } if (r.NextDouble() < mutationRate) { // Spike mutation mutateSpikeAtX(x); } if (r.NextDouble() < mutationRate) { // Clock mutation mutateClockAtX(x); } if (r.NextDouble() < mutationRate) { // Clock extra time mutation mutateClockExtraTimeAtX(x); } } isFitnessUpdated = false; }
public GeneColumn SeekNthColumn(int n) { if (n == 0) { return(this); } int totalSteps = Mathf.Abs(n); GeneColumn iterator = this; if (n < 0) { for (int i = 0; i < totalSteps; i++) { iterator = iterator.Previous; if (iterator == null) { return(null); } } return(iterator); } else { for (int i = 0; i < totalSteps; i++) { iterator = iterator.Next; if (iterator == null) { return(null); } } return(iterator); } }
public MapIndividual(GeneColumn head, GeneColumn generationHead, GeneColumn generationTail, bool isLeftGeneration) { if (!arePlayerMoveConstsCalculated) { calculatePlayerMoveConstants(); } this.Head = head; this.GenerationHead = generationHead; this.GenerationTail = generationTail; this.IsLeftGeneration = isLeftGeneration; GeneColumn iterator; if (generationTail != null) { iterator = GenerationTail; } else { iterator = Head; } while (iterator.Next != null) { iterator = iterator.Next; } this.Tail = iterator; this.Width = this.Tail.GlobalX - this.Head.GlobalX + 1; this.maxSpikes = this.Width / 10F; }
public GeneColumn(GeneColumn left, GeneColumn right, int globalX, int groundHeight, bool hasSpike, bool hasClock, bool isMutable) { this.Previous = left; this.Next = right; this.GlobalX = globalX; this.GroundHeight = groundHeight; this.IsMutable = isMutable; }
public GeneColumn(int globalX, GeneColumn previous, GeneColumn next) : this( previous, next, globalX, random.Next(0, 4), // GroundHeight random.Next(0, 2) == 0 ? false : true, // HasSpike random.Next(0, 2) == 0 ? false : true, // HasClock true // is mutable ) { }
public void Clone(GeneColumn gc) { this.GroundHeight = gc.GroundHeight; this.HasSpike = gc.HasSpike; this.HasClock = gc.HasClock; this.ClockPlaced = gc.ClockPlaced; this.GlobalX = gc.GlobalX; this.ClockExtraTime = gc.ClockExtraTime; this.IsMutable = gc.IsMutable; }
private List <MapIndividual> createLeftPopulation() { List <MapIndividual> population = new List <MapIndividual>(populationSize); for (int i = 0; i < populationSize; i++) { GeneColumn referenceHead = getLeftReferenceChunkClone(); GeneColumn generationHead = getRandomGenerationChunkOnLeftAndLink(referenceHead); population.Add(new MapIndividual(generationHead, generationHead, referenceHead.Previous, true)); } return(population); }
private GeneColumn getRandomGenerationChunkOnRightAndLink(GeneColumn referenceTail) { // Creating generation head and linking to reference tail GeneColumn generationIterator = new GeneColumn(referenceTail.GlobalX + 1, referenceTail, null); referenceTail.Next = generationIterator; for (int i = 1; i < generationChunkSize; i++) { GeneColumn generationNextColumn = new GeneColumn(generationIterator.GlobalX + 1, generationIterator, null); generationIterator.Next = generationNextColumn; generationIterator = generationNextColumn; } return(generationIterator); // generation chunk tail }
private GeneColumn getRandomGenerationChunkOnLeftAndLink(GeneColumn referenceHead) { // Creating generation tail and linking to reference head GeneColumn generationIterator = new GeneColumn(referenceHead.GlobalX - 1, null, referenceHead); referenceHead.Previous = generationIterator; for (int i = 1; i < generationChunkSize; i++) { GeneColumn generationPreviousColumn = new GeneColumn(generationIterator.GlobalX - 1, null, generationIterator); generationIterator.Previous = generationPreviousColumn; generationIterator = generationPreviousColumn; } return(generationIterator); // generation chunk head }
public GeneColumn NextSafe() { GeneColumn iterator = Next; while (iterator != null) { if (iterator.IsSafe) { return(iterator); } iterator = iterator.Next; } return(null); }
public GeneColumn PreviousSafe() { GeneColumn iterator = Previous; while (iterator != null) { if (iterator.IsSafe) { return(iterator); } iterator = iterator.Previous; } return(null); }
public void UpdateWorldAroundX(int x) { var newLeftChunkLimit = x - (int)(renderChunkWidth / 2); trimCells(newLeftChunkLimit); leftChunkLimit = newLeftChunkLimit; mMapGenerator.SetCurrentChunkHead(leftChunkLimit); mMapGenerator.SetCurrentChunkTail(rightChunkLimit); for (int i = 0; i < 2; i++) { /* * This external for is a "workaround" for the weird ground block being * placed in lieu of a few clock items. * The second pass seems to fix it. */ for (GeneColumn iterator = mMapGenerator.CurrentChunkHead; iterator != mMapGenerator.CurrentChunkTail.Next; iterator = iterator.Next) { for (int j = 0; j > -mMapGenerator.MaxHeight; j--) // Height is inverted { char cellCode = iterator.CellAtY(j); if (cellCode == 'C') { ClockItem clock = (ClockItem)clockScene.Instance(); clock.GlobalPosition = MapToWorld(new Vector2(iterator.GlobalX, j)) + (new Vector2(32F, 32F)); clock.ExtraTime = iterator.ClockExtraTime; clock.SourceGeneColumn = iterator; AddChild(clock); iterator.ClockPlaced = true; break; // Not necessary to proceed } else { SetCell(iterator.GlobalX, j, tileFromCode(cellCode)); } } if (iterator.GlobalX % 10 == 0 && !placedXLabels.Contains(iterator.GlobalX)) { // Place a Global X Label CellXLabel xlabel = (CellXLabel)cellXLabelScene.Instance(); xlabel.GlobalX = iterator.GlobalX; xlabel.GlobalPosition = MapToWorld(new Vector2(iterator.GlobalX, -9)) + (new Vector2(32F, 32F)); AddChild(xlabel); } } } }
public GeneColumn GetGlobalColumn(int x) { while (currentGlobalX != x) { if (x < currentGlobalX) { movingHead = movingHead.Previous; } else { movingHead = movingHead.Next; } } return(movingHead); }
private int getClockFitness() { float idealExtraTime = ((Width) * Global.TilePixelWidth / Global.PlayerMaxXSpeed) * 15.0F; float extraTime = 0F; for (GeneColumn x = this.Head; x != null; x = x.Next) { if (x.HasClock) { extraTime += x.ClockExtraTime; } } int clockFitness = (int)((5 * idealExtraTime) - Mathf.Abs(idealExtraTime - extraTime)); return(clockFitness); }
private List <MapIndividual> createRightPopulation() { List <MapIndividual> population = new List <MapIndividual>(populationSize); for (int i = 0; i < populationSize; i++) { GeneColumn referenceTail = getRightReferenceChunkClone(); GeneColumn referenceHead = referenceTail; while (referenceHead.Previous != null) { referenceHead = referenceHead.Previous; } GeneColumn generationTail = getRandomGenerationChunkOnRightAndLink(referenceTail); population.Add(new MapIndividual(referenceHead, referenceTail.Next, generationTail, false)); } return(population); }
private void createBaseChunkAroundX(int initialOrigin, int baseChunkSize) { // Here, we are initializing the first base reference chunk // TODO: add a GA generation for this chunk. For now, it's static. var chunkLeftmostX = initialOrigin - baseChunkSize / 2; var currentX = chunkLeftmostX; GeneColumn previousGC = new GeneColumn(null, null, currentX, 3, false, false, false); this.movingHead = previousGC; this.GlobalHead = previousGC; for (++currentX; currentX < (this.LeftmostGlobalX + baseChunkSize); currentX++) { GeneColumn currentGC = new GeneColumn(previousGC, null, currentX, 3, false, false, false); previousGC.Next = currentGC; previousGC = currentGC; } GlobalTail = previousGC; }
private GeneColumn getRightReferenceChunk() { GeneColumn referenceTail = new GeneColumn(GlobalTail); GeneColumn iterator = new GeneColumn(referenceTail.Previous); referenceTail.Next = null; referenceTail.Previous = iterator; iterator.Next = referenceTail; for (int i = 0; i < referenceChunkSize; i++) { GeneColumn temp = new GeneColumn(iterator.Previous); temp.Next = iterator; iterator.Previous = temp; iterator = temp; } iterator.Previous = null; return(referenceTail); }
private GeneColumn getLeftReferenceChunkClone() { GeneColumn globalReferenceIterator = GlobalHead; GeneColumn referenceHead = new GeneColumn(globalReferenceIterator); GeneColumn referenceCloneIterator = new GeneColumn(globalReferenceIterator.Next, referenceHead, null); referenceHead.Next = referenceCloneIterator; globalReferenceIterator = globalReferenceIterator.Next; for (int i = 0; i < referenceChunkSize - 1; i++) { if (globalReferenceIterator == null) { break; } GeneColumn nextColumn = new GeneColumn(globalReferenceIterator, referenceCloneIterator, null); referenceCloneIterator.Next = nextColumn; referenceCloneIterator = nextColumn; globalReferenceIterator = globalReferenceIterator.Next; } return(referenceHead); }
private GeneColumn getRightReferenceChunkClone() { // On the right reference clone, we start from the global tail GeneColumn globalReferenceIterator = GlobalTail; GeneColumn referenceTail = new GeneColumn(globalReferenceIterator); GeneColumn referenceCloneIterator = new GeneColumn(globalReferenceIterator.Previous, null, referenceTail); referenceTail.Previous = referenceCloneIterator; globalReferenceIterator = globalReferenceIterator.Previous; for (int i = 0; i < referenceChunkSize - 1; i++) { if (globalReferenceIterator == null) { break; } GeneColumn previousColumn = new GeneColumn(globalReferenceIterator, null, referenceCloneIterator); referenceCloneIterator.Previous = previousColumn; referenceCloneIterator = previousColumn; globalReferenceIterator = globalReferenceIterator.Previous; } return(referenceTail); }
private int getSpikeFitness() { int spikeFitness = 0; int spikeLength = 0; int totalSpikes = 0; for (GeneColumn x = this.Head; x != null; x = x.Next) { if (x.HasSpike) { totalSpikes++; x = x.Next; spikeLength = 1; while (x != null && x.HasSpike) { x = x.Next; spikeLength++; totalSpikes++; } // Compute fitness penalty if (spikeLength > maxJumpStraightXDistance) { spikeFitness -= spikeLength * spikePenalty; } } if (x == null) { break; } } // Also, if there are too many spikes in chunk, penalize as well. if (totalSpikes > maxSpikes) { spikeFitness -= (totalSpikes - (int)maxSpikes) * spikePenalty; } return(spikeFitness); }
public MapIndividual(GeneColumn head) { this.Head = head; var iterator = head; if (head.IsMutable) { this.GenerationHead = head; this.IsLeftGeneration = true; while (iterator.Next != null && iterator.Next.IsMutable) { iterator = iterator.Next; } this.GenerationTail = iterator; } else { this.IsLeftGeneration = false; while (!iterator.IsMutable) { iterator = iterator.Next; } this.GenerationHead = iterator; while (iterator.Next != null) { iterator = iterator.Next; } this.GenerationTail = iterator; } while (iterator.Next != null) { iterator = iterator.Next; } this.Tail = iterator; this.Width = this.Tail.GlobalX - this.Head.GlobalX + 1; this.maxSpikes = this.Width / 10F; }
internal void SetCurrentChunkHead(int leftChunkLimit) { if (CurrentChunkHead != null) { if (CurrentChunkHead.GlobalX >= leftChunkLimit) { while (CurrentChunkHead.GlobalX != leftChunkLimit) { CurrentChunkHead = CurrentChunkHead.Previous; } } else { while (CurrentChunkHead.GlobalX != leftChunkLimit) { CurrentChunkHead = CurrentChunkHead.Next; } } } else { this.CurrentChunkHead = GetGlobalColumn(leftChunkLimit); } }
internal void SetCurrentChunkTail(int rightChunkLimit) { if (CurrentChunkTail != null) { if (CurrentChunkTail.GlobalX >= rightChunkLimit) { while (CurrentChunkTail.GlobalX != rightChunkLimit) { CurrentChunkTail = CurrentChunkTail.Previous; } } else { while (CurrentChunkTail.GlobalX != rightChunkLimit) { CurrentChunkTail = CurrentChunkTail.Next; } } } else { this.CurrentChunkTail = GetGlobalColumn(rightChunkLimit); } }
private void mutateSpikeAtX(GeneColumn x) { x.HasSpike = !x.HasSpike; }
private void mutateClockAtX(GeneColumn x) { x.HasClock = !x.HasClock; }
private void mutateClockExtraTimeAtX(GeneColumn x) { x.ClockExtraTime += (float)random.NextDouble() - 0.5F; }