158 lines
3 KiB
Go
158 lines
3 KiB
Go
package game
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
)
|
|
|
|
// TODO: Pull this out into math package and get more test coverage
|
|
|
|
// Abs gets the absolute value of an int
|
|
func Abs(x int) int {
|
|
if x < 0 {
|
|
return -x
|
|
}
|
|
return x
|
|
}
|
|
|
|
// pmod is a mositive modulo
|
|
// golang's % is a "remainder" function si misbehaves for negative modulus inputs
|
|
func Pmod(x, d int) int {
|
|
x = x % d
|
|
if x >= 0 {
|
|
return x
|
|
} else if d < 0 {
|
|
return x - d
|
|
} else {
|
|
return x + d
|
|
}
|
|
}
|
|
|
|
// Max returns the highest int
|
|
func Max(x int, y int) int {
|
|
if x < y {
|
|
return y
|
|
}
|
|
return x
|
|
}
|
|
|
|
// Min returns the lowest int
|
|
func Min(x int, y int) int {
|
|
if x > y {
|
|
return y
|
|
}
|
|
return x
|
|
}
|
|
|
|
// Vector desribes a 3D vector
|
|
type Vector struct {
|
|
X int `json:"x"`
|
|
Y int `json:"y"`
|
|
}
|
|
|
|
// Add adds one vector to another
|
|
func (v *Vector) Add(v2 Vector) {
|
|
v.X += v2.X
|
|
v.Y += v2.Y
|
|
}
|
|
|
|
// Added calculates a new vector
|
|
func (v Vector) Added(v2 Vector) Vector {
|
|
v.Add(v2)
|
|
return v
|
|
}
|
|
|
|
// Negated returns a negated vector
|
|
func (v Vector) Negated() Vector {
|
|
return Vector{-v.X, -v.Y}
|
|
}
|
|
|
|
// Length returns the length of the vector
|
|
func (v Vector) Length() float64 {
|
|
return math.Sqrt(float64(v.X*v.X + v.Y*v.Y))
|
|
}
|
|
|
|
// Distance returns the distance between two vectors
|
|
func (v Vector) Distance(v2 Vector) float64 {
|
|
// Negate the two vectors and calciate the length
|
|
return v.Added(v2.Negated()).Length()
|
|
}
|
|
|
|
// Multiplied returns the vector multiplied by an int
|
|
func (v Vector) Multiplied(val int) Vector {
|
|
return Vector{v.X * val, v.Y * val}
|
|
}
|
|
|
|
// Divided returns the vector divided by an int
|
|
func (v Vector) Divided(val int) Vector {
|
|
return Vector{v.X / val, v.Y / val}
|
|
}
|
|
|
|
// Direction describes a compass direction
|
|
type Direction int
|
|
|
|
const (
|
|
North Direction = iota
|
|
NorthEast
|
|
East
|
|
SouthEast
|
|
South
|
|
SouthWest
|
|
West
|
|
NorthWest
|
|
)
|
|
|
|
// DirectionString simply describes the strings associated with a direction
|
|
type DirectionString struct {
|
|
Long string
|
|
Short string
|
|
}
|
|
|
|
// DirectionStrings is the set of strings for each direction
|
|
var DirectionStrings = []DirectionString{
|
|
{"North", "N"},
|
|
{"NorthEast", "NE"},
|
|
{"East", "E"},
|
|
{"SouthEast", "SE"},
|
|
{"South", "S"},
|
|
{"SouthWest", "SW"},
|
|
{"West", "W"},
|
|
{"NorthWest", "NW"},
|
|
}
|
|
|
|
// String converts a Direction to a String
|
|
func (d Direction) String() string {
|
|
return DirectionStrings[d].Long
|
|
}
|
|
|
|
// ShortString converts a Direction to a short string version
|
|
func (d Direction) ShortString() string {
|
|
return DirectionStrings[d].Short
|
|
}
|
|
|
|
// DirectionFromString gets the Direction from a string
|
|
func DirectionFromString(s string) (Direction, error) {
|
|
for i, d := range DirectionStrings {
|
|
if strings.ToLower(d.Long) == strings.ToLower(s) || strings.ToLower(d.Short) == strings.ToLower(s) {
|
|
return Direction(i), nil
|
|
}
|
|
}
|
|
return -1, fmt.Errorf("Unknown direction: %s", s)
|
|
}
|
|
|
|
var DirectionVectors = []Vector{
|
|
{0, 1}, // N
|
|
{1, 1}, // NE
|
|
{1, 0}, // E
|
|
{1, -1}, // SE
|
|
{0, -1}, // S
|
|
{-1, 1}, // SW
|
|
{-1, 0}, // W
|
|
{-1, 1}, // NW
|
|
}
|
|
|
|
// Vector converts a Direction to a Vector
|
|
func (d Direction) Vector() Vector {
|
|
return DirectionVectors[d]
|
|
}
|