예제 #1
0
func (m *Mario) mutateStep(c int) {

	if m.figures[c].dead {
		m.stats.dead++
		m.figures[c].dead = false
		m.figures[c].cache = make(map[BoolMap]MarioOutput)
		m.figures[c].fig.pos = *m.lvl.NewFigurePos()
		m.figures[c].fig.vel = *util.NewVector(0, 0)

		needsMutation := true

		mutateChance := (float64(c) / float64(len(m.figures))) * 2.0
		forceCross := c >= len(m.figures)/2

		if forceCross || neural.Chance(mutateChance) {
			*m.figures[c].brain = *neural.Cross2(m.randNet(), m.randNet())
			m.stats.crossed++
			needsMutation = false
		}

		if m.figures[c].idleFrames >= idleThreshold {
			m.stats.culled++
			if needsMutation {
				needsMutation = false
				m.figures[c].brain.Mutate(0.75)
				m.figures[c].bestX *= 0.25
			}
		}

		if needsMutation || neural.Chance(0.01) {
			m.figures[c].brain.MutateWithMagnitude(0.01, 0.01)
			m.figures[c].bestX *= 0.975
		}

		m.figures[c].idleFrames = 0
		m.figures[c].idleX = 0
	} else {
		if m.figures[c].fig.pos.X > m.figures[c].bestX {
			m.figures[c].bestX = m.figures[c].fig.pos.X
		}

		if int(m.figures[c].fig.pos.X) > m.figures[c].idleX {
			m.figures[c].idleX = int(m.figures[c].fig.pos.X)
			m.figures[c].idleFrames = 0
		} else {
			m.figures[c].idleFrames++
			if m.figures[c].idleFrames >= idleThreshold {
				m.figures[c].dead = true
			}
		}

	}
}
예제 #2
0
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)
		}
	}

}
예제 #3
0
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
}
예제 #4
0
func NewLevel(w, h int) *Level {
	blockH := h / BLOCK_SIZE
	blockW := w / BLOCK_SIZE

	lvl := &Level{
		size:    *util.NewVector(float64(w), float64(h)),
		blocks:  make([][]*util.Vector, blockW, blockW),
		bmap:    make([][]BoolMap, blockW, blockW),
		figures: make([]*Figure, 0),
	}
	fmt.Println("Mario: generating level...")
	for c := 0; c < blockW; c++ {
		lvl.blocks[c] = make([]*util.Vector, blockH, blockH)
		for r := 0; r < blockH; r++ {
			lvl.blocks[c][r] = nil
		}
	}

	for c, obs := 0, 1; c < blockW; c, obs = c+1, obs+1 {

		pr := c
		if obs%OBSTACLE_SPACING == 0 {
			if neural.Chance(0.7) {
				lvl.makeHole(&c)
			} else {
				lvl.makeObstacle(&c)
			}
		} else {
			lvl.makeGround(&c)
		}
		obs += c - pr
	}

	fmt.Println("Mario: generating bool map...")
	for c := 0; c < blockW; c++ {
		lvl.bmap[c] = make([]BoolMap, blockH, blockH)
		for r := 0; r < blockH; r++ {
			lvl.bmap[c][r] = lvl.boolMapAtIdx(c, r)
		}
	}

	return lvl
}