func (f *Flappy) mutateFlock() { sort.Sort(f.birds) randNet := func() *neural.Net { return f.birds[int(neural.RandMax(float64(len(f.birds))))].brain } best := f.birds[0].brain for c := range f.birds { if f.birds[c].dead { f.birds[c].dead = false f.birds[c].bird.pos = *f.lvl.NewBirdPos() f.birds[c].bird.vel = *util.NewVector(SCROLL_SPEED, 0) f.birds[c].brain = neural.Cross(best, randNet()) if neural.Chance(0.1) { // penalize best achievement due to mutation f.birds[c].bestX *= 0.99 f.birds[c].brain.Mutate(0.33) } } else { f.birds[c].bird.pos = f.birds[c].bird.nextPos f.birds[c].bestX = math.Max(f.birds[c].bird.pos.X, f.birds[c].bestX) } } }
func NewLevel(w, h int) *Level { lvl := &Level{ size: *util.NewVector(float64(w), float64(h)), pylons: make([]util.Vector, 0), birds: make([]*Bird, 0), } // min offset from top && bottom yOffset := float64(PylonHole) for off := pylonSpacing; off < w; off += pylonSpacing { hole := neural.RandMax(float64(h)-yOffset*2.0) + yOffset lvl.pylons = append(lvl.pylons, *util.NewVector(float64(off), hole)) } return lvl }
func (l *Level) makeHole(c *int) { size := int(3 + neural.RandMax(2)) height := int(l.size.Y/float64(BLOCK_SIZE)) - 1 - 3 skip := OBSTACLE_SPACING * 2 if neural.Chance(0.75) { size = skip for iter := 0; iter < skip; iter++ { if iter+*c >= len(l.blocks) { break } if iter%5 == 0 { x := float64((iter + *c) * BLOCK_SIZE) y := float64((height + 3) * BLOCK_SIZE) l.blocks[iter+*c][height+3] = util.NewVector(x, y) } } } if neural.Chance(0.3) { for iter := -2; iter < size+3; iter++ { xIdx := iter + *c if xIdx < 0 || xIdx >= len(l.blocks) { continue } x := float64(xIdx * BLOCK_SIZE) y := float64(height * BLOCK_SIZE) l.blocks[xIdx][height] = util.NewVector(x, y) } } *c += size }