Files
go-mc/bot/path/movement.go
2020-09-23 23:52:28 -07:00

278 lines
6.3 KiB
Go

package path
import (
"fmt"
"github.com/Tnze/go-mc/bot/world"
"github.com/Tnze/go-mc/data/block"
)
// Cardinal directions.
type Direction uint8
func (d Direction) Offset() (x, y, z int) {
switch d {
case North:
return 0, 0, -1
case South:
return 0, 0, 1
case East:
return 1, 0, 0
case West:
return -1, 0, 0
}
panic(fmt.Sprintf("unknown direction value: %v", d))
}
func (d Direction) String() string {
switch d {
case North:
return "north"
case South:
return "south"
case East:
return "east"
case West:
return "west"
}
return fmt.Sprintf("Direction?<%d>", int(d))
}
// Valid direction values.
const (
North Direction = iota
South
West
East
)
func LadderDirection(bStateID world.BlockStatus) Direction {
return Direction(((uint32(bStateID) - block.Ladder.MinStateID) & 0xE) >> 1)
}
// 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,
DescendLadder, DescendLadderNorth, DescendLadderSouth, DescendLadderEast, DescendLadderWest,
AscendLadder,
}
// Valid movement values.
const (
Waypoint Movement = iota
TraverseNorth
TraverseSouth
TraverseEast
TraverseWest
TraverseNorthEast
TraverseNorthWest
TraverseSouthEast
TraverseSouthWest
DropNorth
DropSouth
DropEast
DropWest
AscendNorth
AscendSouth
AscendEast
AscendWest
DescendLadder
DescendLadderNorth
DescendLadderSouth
DescendLadderEast
DescendLadderWest
AscendLadder
)
func (m Movement) Possible(nav *Nav, x, y, z int, from V3, previous Movement) 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
}
b1, b2 := nav.World.GetBlockStatus(x, y+1, z), nav.World.GetBlockStatus(x, y+2, z)
u1, u2 := AirLikeBlock(b1) || IsLadder(b1), AirLikeBlock(b2) || IsLadder(b2)
return u1 && u2
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))
case DescendLadder, AscendLadder:
if bID := nav.World.GetBlockStatus(x, y+1, z); !AirLikeBlock(bID) && !IsLadder(bID) {
return false
}
return IsLadder(nav.World.GetBlockStatus(x, y, z))
case DescendLadderNorth, DescendLadderSouth, DescendLadderEast, DescendLadderWest:
for amt := 0; amt < 2; amt++ {
if bID := nav.World.GetBlockStatus(x, y+amt+1, z); !AirLikeBlock(bID) && !IsLadder(bID) {
return false
}
}
return IsLadder(nav.World.GetBlockStatus(x, y, z))
default:
panic(m)
}
}
func (m Movement) Offset() (x, y, z int) {
switch m {
case Waypoint:
return 0, 0, 0
case TraverseNorth:
return North.Offset()
case TraverseSouth:
return South.Offset()
case TraverseEast:
return East.Offset()
case TraverseWest:
return West.Offset()
case AscendLadder:
return 0, 1, 0
case DescendLadder:
return 0, -1, 0
case DropNorth, DescendLadderNorth:
return 0, -1, -1
case DropSouth, DescendLadderSouth:
return 0, -1, 1
case DropEast, DescendLadderEast:
return 1, -1, 0
case DropWest, DescendLadderWest:
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 2
case TraverseNorthWest, TraverseNorthEast, TraverseSouthWest, TraverseSouthEast:
return 2.5
case DropNorth, DropSouth, DropEast, DropWest:
return 4
case AscendNorth, AscendSouth, AscendEast, AscendWest:
return 4
case DescendLadderNorth, DescendLadderSouth, DescendLadderEast, DescendLadderWest:
return 1.5
case DescendLadder:
return 1
case AscendLadder:
return 3
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"
case DescendLadder:
return "descend-ladder"
case DescendLadderNorth:
return "descend-ladder-north"
case DescendLadderSouth:
return "descend-ladder-south"
case DescendLadderEast:
return "descend-ladder-east"
case DescendLadderWest:
return "descend-ladder-west"
case AscendLadder:
return "ascend-ladder"
default:
panic(m)
}
}