rove/pkg/game/math.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]
}