package main import ( "slices" ) func (game *Game) FillPaths(target Paths, setting int) { for y := 0 ; y < game.Height; y++ { target[y] = slices.Repeat([]int{setting}, game.Width) } } func (game *Game) Neighbors(near Position) []Position { result := make([]Position, 0, 4) points := compass(near, 2) for _, pos := range points { if game.Inbounds(pos, 0) { result = append(result, pos) } } return result } func (game *Game) NeighborWalls(pos Position) []Position { neighbors := game.Neighbors(pos) result := make([]Position, 0) for _, at := range neighbors { cell := game.Level[at.Y][at.X] if cell == WALL { result = append(result, at) } } return result } func (game *Game) PathAddNeighbors(neighbors []Position, closed Map, near Position) []Position { points := compass(near, 1) for _, pos := range points { // NOTE: if you also add !game.Occupied(pos.x, pos.y) it ???? if closed[pos.Y][pos.X] == SPACE { closed[pos.Y][pos.X] = WALL neighbors = append(neighbors, pos) } } return neighbors } func (game *Game) CalculatePaths() { in_grid := make([][]int, game.Height, game.Height) game.FillPaths(in_grid, 1) in_grid[game.Player.Pos.Y][game.Player.Pos.X] = 0 game.FillPaths(game.Paths, PATH_LIMIT) closed := game.CloneMap() starting_pixels := make([]Position, 0, 10) open_pixels := make([]Position, 0, 10) counter := 0 for counter < game.Height * game.Width { x := counter % game.Width y := counter / game.Width if in_grid[y][x] == 0 { game.Paths[y][x] = 0 closed[y][x] = WALL starting_pixels = append(starting_pixels, Position{x, y}) } counter += 1 } for _, pos := range starting_pixels { open_pixels = game.PathAddNeighbors(open_pixels, closed, pos) } counter = 1 for counter < PATH_LIMIT && len(open_pixels) > 0 { next_open := make([]Position, 0, 10) for _, pos := range open_pixels { game.Paths[pos.Y][pos.X] = counter next_open = game.PathAddNeighbors(next_open, closed, pos) } open_pixels = next_open counter += 1 } for _, pos := range open_pixels { game.Paths[pos.Y][pos.X] = counter } } func (game *Game) EnemyPathing() { for enemy_at, _ := range game.Enemies { // get the four directions dirs := compass(enemy_at, 1) // sort by closest path number slices.SortFunc(dirs, func(a Position, b Position) int { return game.Paths[a.Y][a.X] - game.Paths[b.Y][b.X] }) // 0 dir is now the best direction move_to := dirs[0] // can we hear the player? occupied? can_hear := game.Paths[move_to.Y][move_to.X] < HEARING_DISTANCE occupied := game.Occupied(move_to) if can_hear && !occupied { // move the enemy in the best direction game.MoveEnemy(enemy_at, move_to) } } }