WIP getting jumping to work
This commit is contained in:
@ -7,7 +7,7 @@ import (
|
||||
|
||||
var (
|
||||
safeStepBlocks = make(map[world.BlockStatus]struct{}, 1024)
|
||||
blocks = []block.Block{
|
||||
stepBlocks = []block.Block{
|
||||
block.Stone,
|
||||
block.Granite,
|
||||
block.PolishedGranite,
|
||||
@ -34,10 +34,35 @@ var (
|
||||
block.Sandstone,
|
||||
block.RedstoneOre,
|
||||
}
|
||||
|
||||
safeWalkBlocks = make(map[world.BlockStatus]struct{}, 128)
|
||||
walkBlocks = []block.Block{
|
||||
block.Air,
|
||||
block.Grass,
|
||||
block.Torch,
|
||||
block.OakSign,
|
||||
block.SpruceSign,
|
||||
block.BirchSign,
|
||||
block.AcaciaSign,
|
||||
block.JungleSign,
|
||||
block.DarkOakSign,
|
||||
block.OakWallSign,
|
||||
block.SpruceWallSign,
|
||||
block.BirchWallSign,
|
||||
block.AcaciaWallSign,
|
||||
block.JungleWallSign,
|
||||
block.DarkOakWallSign,
|
||||
block.Cornflower,
|
||||
}
|
||||
|
||||
additionalCostBlocks = map[*block.Block]int{
|
||||
&block.Rail: 120,
|
||||
&block.PoweredRail: 200,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
for _, b := range blocks {
|
||||
for _, b := range stepBlocks {
|
||||
if b.MinStateID == b.MaxStateID {
|
||||
safeStepBlocks[world.BlockStatus(b.MinStateID)] = struct{}{}
|
||||
} else {
|
||||
@ -46,4 +71,24 @@ func init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, b := range walkBlocks {
|
||||
if b.MinStateID == b.MaxStateID {
|
||||
safeWalkBlocks[world.BlockStatus(b.MinStateID)] = struct{}{}
|
||||
} else {
|
||||
for i := b.MinStateID; i <= b.MaxStateID; i++ {
|
||||
safeWalkBlocks[world.BlockStatus(i)] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SteppableBlock(bID world.BlockStatus) bool {
|
||||
_, ok := safeStepBlocks[bID]
|
||||
return ok
|
||||
}
|
||||
|
||||
func AirLikeBlock(bID world.BlockStatus) bool {
|
||||
_, ok := safeWalkBlocks[bID]
|
||||
return ok
|
||||
}
|
||||
|
10
bot/path/inputs.go
Normal file
10
bot/path/inputs.go
Normal file
@ -0,0 +1,10 @@
|
||||
package path
|
||||
|
||||
// Inputs describes the desired movements of the player.
|
||||
type Inputs struct {
|
||||
Yaw, Pitch float64
|
||||
|
||||
ThrottleX, ThrottleZ float64
|
||||
|
||||
Jump bool
|
||||
}
|
179
bot/path/movement.go
Normal file
179
bot/path/movement.go
Normal file
@ -0,0 +1,179 @@
|
||||
package path
|
||||
|
||||
// Movement represents a single type of movement in a path.
|
||||
type Movement uint8
|
||||
|
||||
var allMovements = []Movement{TraverseNorth, TraverseSouth, TraverseEast, TraverseWest,
|
||||
TraverseNorthWest, TraverseNorthEast, TraverseSouthWest, TraverseSouthEast,
|
||||
DropNorth, DropSouth, DropEast, DropWest,
|
||||
AscendNorth, AscendSouth, AscendEast, AscendWest,
|
||||
}
|
||||
|
||||
// Valid movement values.
|
||||
const (
|
||||
Waypoint Movement = iota
|
||||
TraverseNorth
|
||||
TraverseSouth
|
||||
TraverseEast
|
||||
TraverseWest
|
||||
TraverseNorthEast
|
||||
TraverseNorthWest
|
||||
TraverseSouthEast
|
||||
TraverseSouthWest
|
||||
DropNorth
|
||||
DropSouth
|
||||
DropEast
|
||||
DropWest
|
||||
AscendNorth
|
||||
AscendSouth
|
||||
AscendEast
|
||||
AscendWest
|
||||
)
|
||||
|
||||
func (m Movement) Possible(nav *Nav, x, y, z int, from V3) bool {
|
||||
// fmt.Printf("%s.Possible(%d,%d,%d)\n", m, x, y, z)
|
||||
switch m {
|
||||
case Waypoint, TraverseNorth, TraverseSouth, TraverseEast, TraverseWest:
|
||||
if !SteppableBlock(nav.World.GetBlockStatus(x, y, z)) {
|
||||
return false
|
||||
}
|
||||
return AirLikeBlock(nav.World.GetBlockStatus(x, y+1, z)) && AirLikeBlock(nav.World.GetBlockStatus(x, y+2, z))
|
||||
|
||||
case TraverseNorthWest, TraverseNorthEast, TraverseSouthWest, TraverseSouthEast:
|
||||
if !SteppableBlock(nav.World.GetBlockStatus(x, y, z)) {
|
||||
return false
|
||||
}
|
||||
if !AirLikeBlock(nav.World.GetBlockStatus(x, y+1, z)) || !AirLikeBlock(nav.World.GetBlockStatus(x, y+2, z)) {
|
||||
return false
|
||||
}
|
||||
if !AirLikeBlock(nav.World.GetBlockStatus(from.X, y+1, z)) || !AirLikeBlock(nav.World.GetBlockStatus(from.X, y+2, z)) {
|
||||
return false
|
||||
}
|
||||
return AirLikeBlock(nav.World.GetBlockStatus(x, y+1, from.Z)) && AirLikeBlock(nav.World.GetBlockStatus(x, y+2, from.Z))
|
||||
|
||||
case DropNorth, DropSouth, DropEast, DropWest:
|
||||
for amt := 0; amt < 3; amt++ {
|
||||
if !AirLikeBlock(nav.World.GetBlockStatus(x, y+amt+1, z)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return SteppableBlock(nav.World.GetBlockStatus(x, y, z))
|
||||
|
||||
case AscendNorth, AscendSouth, AscendEast, AscendWest:
|
||||
if !AirLikeBlock(nav.World.GetBlockStatus(x, y+1, z)) || !AirLikeBlock(nav.World.GetBlockStatus(x, y+2, z)) {
|
||||
return false
|
||||
}
|
||||
return SteppableBlock(nav.World.GetBlockStatus(x, y, z)) &&
|
||||
AirLikeBlock(nav.World.GetBlockStatus(from.X, from.Y+1, from.Z)) &&
|
||||
AirLikeBlock(nav.World.GetBlockStatus(from.X, from.Y+2, from.Z))
|
||||
|
||||
default:
|
||||
panic(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (m Movement) Offset() (x, y, z int) {
|
||||
switch m {
|
||||
case Waypoint:
|
||||
return 0, 0, 0
|
||||
case TraverseNorth:
|
||||
return 0, 0, -1
|
||||
case TraverseSouth:
|
||||
return 0, 0, 1
|
||||
case TraverseEast:
|
||||
return 1, 0, 0
|
||||
case TraverseWest:
|
||||
return -1, 0, 0
|
||||
|
||||
case DropNorth:
|
||||
return 0, -1, -1
|
||||
case DropSouth:
|
||||
return 0, -1, 1
|
||||
case DropEast:
|
||||
return 1, -1, 0
|
||||
case DropWest:
|
||||
return -1, -1, 0
|
||||
case AscendNorth:
|
||||
return 0, 1, -1
|
||||
case AscendSouth:
|
||||
return 0, 1, 1
|
||||
case AscendEast:
|
||||
return 1, 1, 0
|
||||
case AscendWest:
|
||||
return -1, 1, 0
|
||||
|
||||
case TraverseNorthWest:
|
||||
return -1, 0, -1
|
||||
case TraverseNorthEast:
|
||||
return 1, 0, -1
|
||||
case TraverseSouthWest:
|
||||
return -1, 0, 1
|
||||
case TraverseSouthEast:
|
||||
return 1, 0, 1
|
||||
|
||||
default:
|
||||
panic(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (m Movement) BaseCost() float64 {
|
||||
switch m {
|
||||
case Waypoint:
|
||||
return 0
|
||||
case TraverseNorth, TraverseSouth, TraverseEast, TraverseWest:
|
||||
return 1
|
||||
case TraverseNorthWest, TraverseNorthEast, TraverseSouthWest, TraverseSouthEast:
|
||||
return 1.5
|
||||
|
||||
case DropNorth, DropSouth, DropEast, DropWest:
|
||||
return 2
|
||||
case AscendNorth, AscendSouth, AscendEast, AscendWest:
|
||||
return 2.25
|
||||
default:
|
||||
panic(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (m Movement) String() string {
|
||||
switch m {
|
||||
case Waypoint:
|
||||
return "waypoint"
|
||||
case TraverseNorth:
|
||||
return "traverse-north"
|
||||
case TraverseSouth:
|
||||
return "traverse-south"
|
||||
case TraverseEast:
|
||||
return "traverse-east"
|
||||
case TraverseWest:
|
||||
return "traverse-west"
|
||||
|
||||
case DropNorth:
|
||||
return "drop-north"
|
||||
case DropSouth:
|
||||
return "drop-south"
|
||||
case DropEast:
|
||||
return "drop-east"
|
||||
case DropWest:
|
||||
return "drop-west"
|
||||
|
||||
case AscendNorth:
|
||||
return "jump-north"
|
||||
case AscendSouth:
|
||||
return "jump-south"
|
||||
case AscendEast:
|
||||
return "jump-east"
|
||||
case AscendWest:
|
||||
return "jump-west"
|
||||
|
||||
case TraverseNorthWest:
|
||||
return "traverse-northwest"
|
||||
case TraverseNorthEast:
|
||||
return "traverse-northeast"
|
||||
case TraverseSouthWest:
|
||||
return "traverse-southwest"
|
||||
case TraverseSouthEast:
|
||||
return "traverse-southeast"
|
||||
default:
|
||||
panic(m)
|
||||
}
|
||||
}
|
@ -2,8 +2,9 @@
|
||||
package path
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/Tnze/go-mc/bot/world"
|
||||
"github.com/Tnze/go-mc/data/block"
|
||||
"github.com/beefsack/go-astar"
|
||||
)
|
||||
|
||||
@ -36,27 +37,14 @@ func (n *Nav) Path() (path []astar.Pather, distance float64, found bool) {
|
||||
})
|
||||
}
|
||||
|
||||
// Movement represents a single type of movement in a path.
|
||||
type Movement uint8
|
||||
|
||||
var allMovements = []Movement{TraverseNorth, TraverseSouth, TraverseEast, TraverseWest}
|
||||
|
||||
// Valid movement values.
|
||||
const (
|
||||
Waypoint Movement = iota
|
||||
TraverseNorth
|
||||
TraverseSouth
|
||||
TraverseEast
|
||||
TraverseWest
|
||||
)
|
||||
|
||||
// Tile represents a point in a path. All tiles in a path are adjaceent their
|
||||
// preceeding tiles.
|
||||
type Tile struct {
|
||||
Nav *Nav
|
||||
|
||||
Movement Movement
|
||||
Pos V3
|
||||
Movement Movement
|
||||
Pos V3
|
||||
ExtraCost int
|
||||
}
|
||||
|
||||
func (t Tile) PathNeighborCost(to astar.Pather) float64 {
|
||||
@ -67,12 +55,17 @@ func (t Tile) PathNeighborCost(to astar.Pather) float64 {
|
||||
func (t Tile) PathEstimatedCost(to astar.Pather) float64 {
|
||||
other := to.(Tile)
|
||||
cost := t.Pos.Cost(other.Pos)
|
||||
|
||||
return cost + other.Movement.BaseCost()
|
||||
}
|
||||
|
||||
func (t Tile) PathNeighbors() []astar.Pather {
|
||||
possibles := make([]astar.Pather, 0, 8)
|
||||
|
||||
if t.PathEstimatedCost(Tile{Pos: t.Nav.Start}) > 1200 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if t.Pos == t.Nav.Dest && t.Movement != Waypoint {
|
||||
dupe := t
|
||||
dupe.Movement = Waypoint
|
||||
@ -82,7 +75,7 @@ func (t Tile) PathNeighbors() []astar.Pather {
|
||||
for _, m := range allMovements {
|
||||
x, y, z := m.Offset()
|
||||
pos := V3{X: t.Pos.X + x, Y: t.Pos.Y + y, Z: t.Pos.Z + z}
|
||||
if m.Possible(t.Nav, pos.X, pos.Y, pos.Z) {
|
||||
if m.Possible(t.Nav, pos.X, pos.Y, pos.Z, t.Pos) {
|
||||
possibles = append(possibles, Tile{
|
||||
Nav: t.Nav,
|
||||
Movement: m,
|
||||
@ -95,63 +88,18 @@ func (t Tile) PathNeighbors() []astar.Pather {
|
||||
return possibles
|
||||
}
|
||||
|
||||
func (m Movement) Possible(nav *Nav, x, y, z int) bool {
|
||||
// fmt.Printf("%s.Possible(%d,%d,%d)\n", m, x, y, z)
|
||||
switch m {
|
||||
case Waypoint, TraverseNorth, TraverseSouth, TraverseEast, TraverseWest:
|
||||
b := nav.World.GetBlockStatus(x, y, z)
|
||||
if _, safe := safeStepBlocks[b]; !safe {
|
||||
return false
|
||||
}
|
||||
above1 := uint32(nav.World.GetBlockStatus(x, y+1, z))
|
||||
above2 := uint32(nav.World.GetBlockStatus(x, y+2, z))
|
||||
return above1 == block.Air.MinStateID && above2 == block.Air.MinStateID
|
||||
default:
|
||||
panic(m)
|
||||
func (t Tile) Inputs(dX, dY, dZ float64) Inputs {
|
||||
// Sufficient for simple movements.
|
||||
at := math.Atan2(-dX, -dZ)
|
||||
out := Inputs{
|
||||
ThrottleX: math.Sin(at),
|
||||
ThrottleZ: math.Cos(at),
|
||||
}
|
||||
}
|
||||
|
||||
func (m Movement) Offset() (x, y, z int) {
|
||||
switch m {
|
||||
case Waypoint:
|
||||
return 0, 0, 0
|
||||
case TraverseNorth:
|
||||
return 0, 0, -1
|
||||
case TraverseSouth:
|
||||
return 0, 0, 1
|
||||
case TraverseEast:
|
||||
return 1, 0, 0
|
||||
case TraverseWest:
|
||||
return -1, 0, 0
|
||||
default:
|
||||
panic(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (m Movement) BaseCost() float64 {
|
||||
switch m {
|
||||
case Waypoint:
|
||||
return 0
|
||||
case TraverseNorth, TraverseSouth, TraverseEast, TraverseWest:
|
||||
return 1
|
||||
default:
|
||||
panic(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (m Movement) String() string {
|
||||
switch m {
|
||||
case Waypoint:
|
||||
return "waypoint"
|
||||
case TraverseNorth:
|
||||
return "traverse-north"
|
||||
case TraverseSouth:
|
||||
return "traverse-south"
|
||||
case TraverseEast:
|
||||
return "traverse-east"
|
||||
case TraverseWest:
|
||||
return "traverse-west"
|
||||
default:
|
||||
panic(m)
|
||||
switch t.Movement {
|
||||
case AscendNorth, AscendSouth, AscendEast, AscendWest:
|
||||
out.Jump = math.Sqrt(dX*dX+dZ*dZ) < 1.75
|
||||
out.Yaw = 0
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
Reference in New Issue
Block a user