commit
89123394cd
11 changed files with 246 additions and 153 deletions
|
@ -22,6 +22,9 @@ const (
|
||||||
// GlyphRoverLive represents a live rover
|
// GlyphRoverLive represents a live rover
|
||||||
GlyphRoverLive = Glyph('R')
|
GlyphRoverLive = Glyph('R')
|
||||||
|
|
||||||
|
// GlyphRoverDormant represents a dormant rover
|
||||||
|
GlyphRoverDormant = Glyph('r')
|
||||||
|
|
||||||
// GlyphRockSmall is a small stashable rock
|
// GlyphRockSmall is a small stashable rock
|
||||||
GlyphRockSmall = Glyph('o')
|
GlyphRockSmall = Glyph('o')
|
||||||
|
|
||||||
|
@ -51,6 +54,8 @@ func ObjectGlyph(o roveapi.Object) Glyph {
|
||||||
return GlyphRoverLive
|
return GlyphRoverLive
|
||||||
case roveapi.Object_RockSmall:
|
case roveapi.Object_RockSmall:
|
||||||
return GlyphRockSmall
|
return GlyphRockSmall
|
||||||
|
case roveapi.Object_RoverDormant:
|
||||||
|
return GlyphRoverDormant
|
||||||
case roveapi.Object_RockLarge:
|
case roveapi.Object_RockLarge:
|
||||||
return GlyphRockLarge
|
return GlyphRockLarge
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package atlas
|
package rove
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mdiluz/rove/pkg/maths"
|
"github.com/mdiluz/rove/pkg/maths"
|
|
@ -1,4 +1,4 @@
|
||||||
package atlas
|
package rove
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -1,4 +1,4 @@
|
||||||
package atlas
|
package rove
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
@ -6,7 +6,6 @@ import (
|
||||||
|
|
||||||
"github.com/mdiluz/rove/pkg/maths"
|
"github.com/mdiluz/rove/pkg/maths"
|
||||||
"github.com/mdiluz/rove/proto/roveapi"
|
"github.com/mdiluz/rove/proto/roveapi"
|
||||||
"github.com/ojrac/opensimplex-go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// chunk represents a fixed square grid of tiles
|
// chunk represents a fixed square grid of tiles
|
||||||
|
@ -34,29 +33,23 @@ type chunkBasedAtlas struct {
|
||||||
// ChunkSize is the x/y dimensions of each square chunk
|
// ChunkSize is the x/y dimensions of each square chunk
|
||||||
ChunkSize int `json:"chunksize"`
|
ChunkSize int `json:"chunksize"`
|
||||||
|
|
||||||
// terrainNoise describes the noise function for the terrain
|
// worldGen is the internal world generator
|
||||||
terrainNoise opensimplex.Noise
|
worldGen WorldGen
|
||||||
|
|
||||||
// terrainNoise describes the noise function for the terrain
|
|
||||||
objectNoise opensimplex.Noise
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
noiseSeed = 1024
|
noiseSeed = 1024
|
||||||
terrainNoiseScale = 6
|
|
||||||
objectNoiseScale = 3
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewChunkAtlas creates a new empty atlas
|
// NewChunkAtlas creates a new empty atlas
|
||||||
func NewChunkAtlas(chunkSize int) Atlas {
|
func NewChunkAtlas(chunkSize int) Atlas {
|
||||||
// Start up with one chunk
|
// Start up with one chunk
|
||||||
a := chunkBasedAtlas{
|
a := chunkBasedAtlas{
|
||||||
ChunkSize: chunkSize,
|
ChunkSize: chunkSize,
|
||||||
Chunks: make([]chunk, 1),
|
Chunks: make([]chunk, 1),
|
||||||
LowerBound: maths.Vector{X: 0, Y: 0},
|
LowerBound: maths.Vector{X: 0, Y: 0},
|
||||||
UpperBound: maths.Vector{X: chunkSize, Y: chunkSize},
|
UpperBound: maths.Vector{X: chunkSize, Y: chunkSize},
|
||||||
terrainNoise: opensimplex.New(noiseSeed),
|
worldGen: NewNoiseWorldGen(noiseSeed),
|
||||||
objectNoise: opensimplex.New(noiseSeed),
|
|
||||||
}
|
}
|
||||||
// Initialise the first chunk
|
// Initialise the first chunk
|
||||||
a.populate(0)
|
a.populate(0)
|
||||||
|
@ -105,31 +98,15 @@ func (a *chunkBasedAtlas) populate(chunk int) {
|
||||||
origin := a.chunkOriginInWorldSpace(chunk)
|
origin := a.chunkOriginInWorldSpace(chunk)
|
||||||
for i := 0; i < a.ChunkSize; i++ {
|
for i := 0; i < a.ChunkSize; i++ {
|
||||||
for j := 0; j < a.ChunkSize; j++ {
|
for j := 0; j < a.ChunkSize; j++ {
|
||||||
|
loc := maths.Vector{X: origin.X + i, Y: origin.Y + j}
|
||||||
|
|
||||||
// Get the terrain noise value for this location
|
// Set the tile
|
||||||
t := a.terrainNoise.Eval2(float64(origin.X+i)/terrainNoiseScale, float64(origin.Y+j)/terrainNoiseScale)
|
c.Tiles[j*a.ChunkSize+i] = byte(a.worldGen.GetTile(loc))
|
||||||
var tile roveapi.Tile
|
|
||||||
switch {
|
|
||||||
case t > 0.5:
|
|
||||||
tile = roveapi.Tile_Gravel
|
|
||||||
case t > 0.05:
|
|
||||||
tile = roveapi.Tile_Sand
|
|
||||||
default:
|
|
||||||
tile = roveapi.Tile_Rock
|
|
||||||
}
|
|
||||||
c.Tiles[j*a.ChunkSize+i] = byte(tile)
|
|
||||||
|
|
||||||
// Get the object noise value for this location
|
// Set the object
|
||||||
o := a.objectNoise.Eval2(float64(origin.X+i)/objectNoiseScale, float64(origin.Y+j)/objectNoiseScale)
|
obj := a.worldGen.GetObject(loc)
|
||||||
var obj = roveapi.Object_ObjectUnknown
|
if obj.Type != roveapi.Object_ObjectUnknown {
|
||||||
switch {
|
c.Objects[j*a.ChunkSize+i] = obj
|
||||||
case o > 0.6:
|
|
||||||
obj = roveapi.Object_RockLarge
|
|
||||||
case o > 0.5:
|
|
||||||
obj = roveapi.Object_RockSmall
|
|
||||||
}
|
|
||||||
if obj != roveapi.Object_ObjectUnknown {
|
|
||||||
c.Objects[j*a.ChunkSize+i] = Object{Type: roveapi.Object(obj)}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,12 +213,11 @@ func (a *chunkBasedAtlas) worldSpaceToChunkWithGrow(v maths.Vector) int {
|
||||||
|
|
||||||
// Create the new empty atlas
|
// Create the new empty atlas
|
||||||
newAtlas := chunkBasedAtlas{
|
newAtlas := chunkBasedAtlas{
|
||||||
ChunkSize: a.ChunkSize,
|
ChunkSize: a.ChunkSize,
|
||||||
LowerBound: lower,
|
LowerBound: lower,
|
||||||
UpperBound: upper,
|
UpperBound: upper,
|
||||||
Chunks: make([]chunk, size.X*size.Y),
|
Chunks: make([]chunk, size.X*size.Y),
|
||||||
terrainNoise: a.terrainNoise,
|
worldGen: a.worldGen,
|
||||||
objectNoise: a.objectNoise,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log that we're resizing
|
// Log that we're resizing
|
|
@ -1,4 +1,4 @@
|
||||||
package atlas
|
package rove
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mdiluz/rove/proto/roveapi"
|
"github.com/mdiluz/rove/proto/roveapi"
|
||||||
|
@ -8,12 +8,16 @@ import (
|
||||||
type Object struct {
|
type Object struct {
|
||||||
// The type of the object
|
// The type of the object
|
||||||
Type roveapi.Object `json:"type"`
|
Type roveapi.Object `json:"type"`
|
||||||
|
|
||||||
|
// Data is an internal type used for certain types of object
|
||||||
|
Data []byte `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBlocking checks if an object is a blocking object
|
// IsBlocking checks if an object is a blocking object
|
||||||
func (o *Object) IsBlocking() bool {
|
func (o *Object) IsBlocking() bool {
|
||||||
var blocking = [...]roveapi.Object{
|
var blocking = [...]roveapi.Object{
|
||||||
roveapi.Object_RoverLive,
|
roveapi.Object_RoverLive,
|
||||||
|
roveapi.Object_RoverDormant,
|
||||||
roveapi.Object_RockLarge,
|
roveapi.Object_RockLarge,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package rove
|
package rove
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mdiluz/rove/pkg/atlas"
|
"github.com/google/uuid"
|
||||||
"github.com/mdiluz/rove/pkg/maths"
|
"github.com/mdiluz/rove/pkg/maths"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,7 +33,7 @@ type Rover struct {
|
||||||
Range int `json:"range"`
|
Range int `json:"range"`
|
||||||
|
|
||||||
// Inventory represents any items the rover is carrying
|
// Inventory represents any items the rover is carrying
|
||||||
Inventory []atlas.Object `json:"inventory"`
|
Inventory []Object `json:"inventory"`
|
||||||
|
|
||||||
// Capacity is the maximum number of inventory items
|
// Capacity is the maximum number of inventory items
|
||||||
Capacity int `json:"capacity"`
|
Capacity int `json:"capacity"`
|
||||||
|
@ -51,6 +54,19 @@ type Rover struct {
|
||||||
Logs []RoverLogEntry `json:"logs"`
|
Logs []RoverLogEntry `json:"logs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultRover returns a default rover object with default settings
|
||||||
|
func DefaultRover() Rover {
|
||||||
|
return Rover{
|
||||||
|
Range: 4,
|
||||||
|
Integrity: 10,
|
||||||
|
MaximumIntegrity: 10,
|
||||||
|
Capacity: 10,
|
||||||
|
Charge: 10,
|
||||||
|
MaximumCharge: 10,
|
||||||
|
Name: GenerateRoverName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AddLogEntryf adds an entry to the rovers log
|
// AddLogEntryf adds an entry to the rovers log
|
||||||
func (r *Rover) AddLogEntryf(format string, args ...interface{}) {
|
func (r *Rover) AddLogEntryf(format string, args ...interface{}) {
|
||||||
text := fmt.Sprintf(format, args...)
|
text := fmt.Sprintf(format, args...)
|
||||||
|
@ -62,3 +78,36 @@ func (r *Rover) AddLogEntryf(format string, args ...interface{}) {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var wordsFile = os.Getenv("WORDS_FILE")
|
||||||
|
var roverWords []string
|
||||||
|
|
||||||
|
// GenerateRoverName generates a new rover name
|
||||||
|
func GenerateRoverName() string {
|
||||||
|
|
||||||
|
// Try and load the rover words file
|
||||||
|
if len(roverWords) == 0 {
|
||||||
|
// Try and load the words file
|
||||||
|
if file, err := os.Open(wordsFile); err != nil {
|
||||||
|
log.Printf("Couldn't read words file [%s], running without words: %s\n", wordsFile, err)
|
||||||
|
} else {
|
||||||
|
defer file.Close()
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
roverWords = append(roverWords, scanner.Text())
|
||||||
|
}
|
||||||
|
if scanner.Err() != nil {
|
||||||
|
log.Printf("Failure during word file scan: %s\n", scanner.Err())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign a random name if we have words
|
||||||
|
if len(roverWords) > 0 {
|
||||||
|
// Loop until we find a unique name
|
||||||
|
return fmt.Sprintf("%s-%s", roverWords[rand.Intn(len(roverWords))], roverWords[rand.Intn(len(roverWords))])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to a unique string
|
||||||
|
return uuid.New().String()
|
||||||
|
}
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
package rove
|
package rove
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/mdiluz/rove/pkg/atlas"
|
|
||||||
"github.com/mdiluz/rove/pkg/maths"
|
"github.com/mdiluz/rove/pkg/maths"
|
||||||
"github.com/mdiluz/rove/proto/roveapi"
|
"github.com/mdiluz/rove/proto/roveapi"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +22,7 @@ type World struct {
|
||||||
Rovers map[string]Rover `json:"rovers"`
|
Rovers map[string]Rover `json:"rovers"`
|
||||||
|
|
||||||
// Atlas represends the world map of chunks and tiles
|
// Atlas represends the world map of chunks and tiles
|
||||||
Atlas atlas.Atlas `json:"atlas"`
|
Atlas Atlas `json:"atlas"`
|
||||||
|
|
||||||
// Commands is the set of currently executing command streams per rover
|
// Commands is the set of currently executing command streams per rover
|
||||||
CommandQueue map[string]CommandStream `json:"commands"`
|
CommandQueue map[string]CommandStream `json:"commands"`
|
||||||
|
@ -37,36 +33,15 @@ type World struct {
|
||||||
worldMutex sync.RWMutex
|
worldMutex sync.RWMutex
|
||||||
// Mutex to lock around command operations
|
// Mutex to lock around command operations
|
||||||
cmdMutex sync.RWMutex
|
cmdMutex sync.RWMutex
|
||||||
// Set of possible words to use for names
|
|
||||||
words []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var wordsFile = os.Getenv("WORDS_FILE")
|
|
||||||
|
|
||||||
// NewWorld creates a new world object
|
// NewWorld creates a new world object
|
||||||
func NewWorld(chunkSize int) *World {
|
func NewWorld(chunkSize int) *World {
|
||||||
|
|
||||||
// Try and load the words file
|
|
||||||
var lines []string
|
|
||||||
if file, err := os.Open(wordsFile); err != nil {
|
|
||||||
log.Printf("Couldn't read words file [%s], running without words: %s\n", wordsFile, err)
|
|
||||||
} else {
|
|
||||||
defer file.Close()
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
for scanner.Scan() {
|
|
||||||
lines = append(lines, scanner.Text())
|
|
||||||
}
|
|
||||||
if scanner.Err() != nil {
|
|
||||||
log.Printf("Failure during word file scan: %s\n", scanner.Err())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &World{
|
return &World{
|
||||||
Rovers: make(map[string]Rover),
|
Rovers: make(map[string]Rover),
|
||||||
CommandQueue: make(map[string]CommandStream),
|
CommandQueue: make(map[string]CommandStream),
|
||||||
CommandIncoming: make(map[string]CommandStream),
|
CommandIncoming: make(map[string]CommandStream),
|
||||||
Atlas: atlas.NewChunkAtlas(chunkSize),
|
Atlas: NewChunkAtlas(chunkSize),
|
||||||
words: lines,
|
|
||||||
TicksPerDay: 24,
|
TicksPerDay: 24,
|
||||||
CurrentTicks: 0,
|
CurrentTicks: 0,
|
||||||
}
|
}
|
||||||
|
@ -78,27 +53,7 @@ func (w *World) SpawnRover() (string, error) {
|
||||||
defer w.worldMutex.Unlock()
|
defer w.worldMutex.Unlock()
|
||||||
|
|
||||||
// Initialise the rover
|
// Initialise the rover
|
||||||
rover := Rover{
|
rover := DefaultRover()
|
||||||
Range: 4,
|
|
||||||
Integrity: 10,
|
|
||||||
MaximumIntegrity: 10,
|
|
||||||
Capacity: 10,
|
|
||||||
Charge: 10,
|
|
||||||
MaximumCharge: 10,
|
|
||||||
Name: uuid.New().String(),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign a random name if we have words
|
|
||||||
if len(w.words) > 0 {
|
|
||||||
for {
|
|
||||||
// Loop until we find a unique name
|
|
||||||
name := fmt.Sprintf("%s-%s", w.words[rand.Intn(len(w.words))], w.words[rand.Intn(len(w.words))])
|
|
||||||
if _, ok := w.Rovers[name]; !ok {
|
|
||||||
rover.Name = name
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn in a random place near the origin
|
// Spawn in a random place near the origin
|
||||||
rover.Pos = maths.Vector{
|
rover.Pos = maths.Vector{
|
||||||
|
@ -240,7 +195,7 @@ func (w *World) SetRoverPosition(rover string, pos maths.Vector) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RoverInventory returns the inventory of a requested rover
|
// RoverInventory returns the inventory of a requested rover
|
||||||
func (w *World) RoverInventory(rover string) ([]atlas.Object, error) {
|
func (w *World) RoverInventory(rover string) ([]Object, error) {
|
||||||
w.worldMutex.RLock()
|
w.worldMutex.RLock()
|
||||||
defer w.worldMutex.RUnlock()
|
defer w.worldMutex.RUnlock()
|
||||||
|
|
||||||
|
@ -346,7 +301,7 @@ func (w *World) RoverStash(rover string) (roveapi.Object, error) {
|
||||||
r.AddLogEntryf("stashed %c", obj.Type)
|
r.AddLogEntryf("stashed %c", obj.Type)
|
||||||
r.Inventory = append(r.Inventory, obj)
|
r.Inventory = append(r.Inventory, obj)
|
||||||
w.Rovers[rover] = r
|
w.Rovers[rover] = r
|
||||||
w.Atlas.SetObject(r.Pos, atlas.Object{Type: roveapi.Object_ObjectUnknown})
|
w.Atlas.SetObject(r.Pos, Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
return obj.Type, nil
|
return obj.Type, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package rove
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mdiluz/rove/pkg/atlas"
|
|
||||||
"github.com/mdiluz/rove/pkg/maths"
|
"github.com/mdiluz/rove/pkg/maths"
|
||||||
"github.com/mdiluz/rove/proto/roveapi"
|
"github.com/mdiluz/rove/proto/roveapi"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -90,7 +89,7 @@ func TestWorld_GetSetMovePosition(t *testing.T) {
|
||||||
assert.Contains(t, rover.Logs[len(rover.Logs)-1].Text, "moved", "Rover logs should contain the move")
|
assert.Contains(t, rover.Logs[len(rover.Logs)-1].Text, "moved", "Rover logs should contain the move")
|
||||||
|
|
||||||
// Place a tile in front of the rover
|
// Place a tile in front of the rover
|
||||||
world.Atlas.SetObject(maths.Vector{X: 0, Y: 2}, atlas.Object{Type: roveapi.Object_RockLarge})
|
world.Atlas.SetObject(maths.Vector{X: 0, Y: 2}, Object{Type: roveapi.Object_RockLarge})
|
||||||
newPos, err = world.MoveRover(a, b)
|
newPos, err = world.MoveRover(a, b)
|
||||||
assert.NoError(t, err, "Failed to move rover")
|
assert.NoError(t, err, "Failed to move rover")
|
||||||
assert.Equal(t, pos, newPos, "Failed to correctly not move position for rover into wall")
|
assert.Equal(t, pos, newPos, "Failed to correctly not move position for rover into wall")
|
||||||
|
@ -110,7 +109,9 @@ func TestWorld_RadarFromRover(t *testing.T) {
|
||||||
|
|
||||||
// Warp the rovers into position
|
// Warp the rovers into position
|
||||||
bpos := maths.Vector{X: -3, Y: -3}
|
bpos := maths.Vector{X: -3, Y: -3}
|
||||||
|
world.Atlas.SetObject(bpos, Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
assert.NoError(t, world.WarpRover(b, bpos), "Failed to warp rover")
|
assert.NoError(t, world.WarpRover(b, bpos), "Failed to warp rover")
|
||||||
|
world.Atlas.SetObject(maths.Vector{X: 0, Y: 0}, Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
assert.NoError(t, world.WarpRover(a, maths.Vector{X: 0, Y: 0}), "Failed to warp rover")
|
assert.NoError(t, world.WarpRover(a, maths.Vector{X: 0, Y: 0}), "Failed to warp rover")
|
||||||
|
|
||||||
radar, objs, err := world.RadarFromRover(a)
|
radar, objs, err := world.RadarFromRover(a)
|
||||||
|
@ -142,7 +143,7 @@ func TestWorld_RoverStash(t *testing.T) {
|
||||||
Y: 0.0,
|
Y: 0.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
world.Atlas.SetObject(pos, atlas.Object{Type: roveapi.Object_ObjectUnknown})
|
world.Atlas.SetObject(pos, Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
err = world.WarpRover(a, pos)
|
err = world.WarpRover(a, pos)
|
||||||
assert.NoError(t, err, "Failed to set position for rover")
|
assert.NoError(t, err, "Failed to set position for rover")
|
||||||
|
|
||||||
|
@ -151,7 +152,7 @@ func TestWorld_RoverStash(t *testing.T) {
|
||||||
|
|
||||||
for i := 0; i < rover.Capacity; i++ {
|
for i := 0; i < rover.Capacity; i++ {
|
||||||
// Place an object
|
// Place an object
|
||||||
world.Atlas.SetObject(pos, atlas.Object{Type: roveapi.Object_RockSmall})
|
world.Atlas.SetObject(pos, Object{Type: roveapi.Object_RockSmall})
|
||||||
|
|
||||||
// Pick it up
|
// Pick it up
|
||||||
o, err := world.RoverStash(a)
|
o, err := world.RoverStash(a)
|
||||||
|
@ -166,7 +167,7 @@ func TestWorld_RoverStash(t *testing.T) {
|
||||||
inv, err := world.RoverInventory(a)
|
inv, err := world.RoverInventory(a)
|
||||||
assert.NoError(t, err, "Failed to get inventory")
|
assert.NoError(t, err, "Failed to get inventory")
|
||||||
assert.Equal(t, i+1, len(inv))
|
assert.Equal(t, i+1, len(inv))
|
||||||
assert.Equal(t, atlas.Object{Type: roveapi.Object_RockSmall}, inv[i])
|
assert.Equal(t, Object{Type: roveapi.Object_RockSmall}, inv[i])
|
||||||
|
|
||||||
// Check that this did reduce the charge
|
// Check that this did reduce the charge
|
||||||
info, err := world.GetRover(a)
|
info, err := world.GetRover(a)
|
||||||
|
@ -183,7 +184,7 @@ func TestWorld_RoverStash(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place an object
|
// Place an object
|
||||||
world.Atlas.SetObject(pos, atlas.Object{Type: roveapi.Object_RockSmall})
|
world.Atlas.SetObject(pos, Object{Type: roveapi.Object_RockSmall})
|
||||||
|
|
||||||
// Try to pick it up
|
// Try to pick it up
|
||||||
o, err := world.RoverStash(a)
|
o, err := world.RoverStash(a)
|
||||||
|
@ -221,7 +222,7 @@ func TestWorld_RoverDamage(t *testing.T) {
|
||||||
info, err := world.GetRover(a)
|
info, err := world.GetRover(a)
|
||||||
assert.NoError(t, err, "couldn't get rover info")
|
assert.NoError(t, err, "couldn't get rover info")
|
||||||
|
|
||||||
world.Atlas.SetObject(maths.Vector{X: 0.0, Y: 1.0}, atlas.Object{Type: roveapi.Object_RockLarge})
|
world.Atlas.SetObject(maths.Vector{X: 0.0, Y: 1.0}, Object{Type: roveapi.Object_RockLarge})
|
||||||
|
|
||||||
vec, err := world.MoveRover(a, roveapi.Bearing_North)
|
vec, err := world.MoveRover(a, roveapi.Bearing_North)
|
||||||
assert.NoError(t, err, "Failed to move rover")
|
assert.NoError(t, err, "Failed to move rover")
|
||||||
|
@ -243,7 +244,7 @@ func TestWorld_RoverRepair(t *testing.T) {
|
||||||
Y: 0.0,
|
Y: 0.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
world.Atlas.SetObject(pos, atlas.Object{Type: roveapi.Object_ObjectUnknown})
|
world.Atlas.SetObject(pos, Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
|
|
||||||
err = world.WarpRover(a, pos)
|
err = world.WarpRover(a, pos)
|
||||||
assert.NoError(t, err, "Failed to set position for rover")
|
assert.NoError(t, err, "Failed to set position for rover")
|
||||||
|
@ -252,12 +253,12 @@ func TestWorld_RoverRepair(t *testing.T) {
|
||||||
assert.NoError(t, err, "couldn't get rover info")
|
assert.NoError(t, err, "couldn't get rover info")
|
||||||
|
|
||||||
// Pick up something to repair with
|
// Pick up something to repair with
|
||||||
world.Atlas.SetObject(pos, atlas.Object{Type: roveapi.Object_RockSmall})
|
world.Atlas.SetObject(pos, Object{Type: roveapi.Object_RockSmall})
|
||||||
o, err := world.RoverStash(a)
|
o, err := world.RoverStash(a)
|
||||||
assert.NoError(t, err, "Failed to stash")
|
assert.NoError(t, err, "Failed to stash")
|
||||||
assert.Equal(t, roveapi.Object_RockSmall, o, "Failed to get correct object")
|
assert.Equal(t, roveapi.Object_RockSmall, o, "Failed to get correct object")
|
||||||
|
|
||||||
world.Atlas.SetObject(maths.Vector{X: 0.0, Y: 1.0}, atlas.Object{Type: roveapi.Object_RockLarge})
|
world.Atlas.SetObject(maths.Vector{X: 0.0, Y: 1.0}, Object{Type: roveapi.Object_RockLarge})
|
||||||
|
|
||||||
// Try and bump into the rock
|
// Try and bump into the rock
|
||||||
vec, err := world.MoveRover(a, roveapi.Bearing_North)
|
vec, err := world.MoveRover(a, roveapi.Bearing_North)
|
||||||
|
@ -277,7 +278,7 @@ func TestWorld_RoverRepair(t *testing.T) {
|
||||||
assert.Contains(t, newinfo.Logs[len(newinfo.Logs)-1].Text, "repair", "Rover logs should contain the repair")
|
assert.Contains(t, newinfo.Logs[len(newinfo.Logs)-1].Text, "repair", "Rover logs should contain the repair")
|
||||||
|
|
||||||
// Check again that it can't repair past the max
|
// Check again that it can't repair past the max
|
||||||
world.Atlas.SetObject(pos, atlas.Object{Type: roveapi.Object_RockSmall})
|
world.Atlas.SetObject(pos, Object{Type: roveapi.Object_RockSmall})
|
||||||
o, err = world.RoverStash(a)
|
o, err = world.RoverStash(a)
|
||||||
assert.NoError(t, err, "Failed to stash")
|
assert.NoError(t, err, "Failed to stash")
|
||||||
assert.Equal(t, roveapi.Object_RockSmall, o, "Failed to get correct object")
|
assert.Equal(t, roveapi.Object_RockSmall, o, "Failed to get correct object")
|
||||||
|
@ -308,7 +309,7 @@ func TestWorld_Charge(t *testing.T) {
|
||||||
|
|
||||||
// Ensure the path ahead is empty
|
// Ensure the path ahead is empty
|
||||||
world.Atlas.SetTile(initialPos.Added(maths.BearingToVector(roveapi.Bearing_North)), roveapi.Tile_Rock)
|
world.Atlas.SetTile(initialPos.Added(maths.BearingToVector(roveapi.Bearing_North)), roveapi.Tile_Rock)
|
||||||
world.Atlas.SetObject(initialPos.Added(maths.BearingToVector(roveapi.Bearing_North)), atlas.Object{Type: roveapi.Object_ObjectUnknown})
|
world.Atlas.SetObject(initialPos.Added(maths.BearingToVector(roveapi.Bearing_North)), Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
|
|
||||||
// Try and move north (along unblocked path)
|
// Try and move north (along unblocked path)
|
||||||
newPos, err := world.MoveRover(a, roveapi.Bearing_North)
|
newPos, err := world.MoveRover(a, roveapi.Bearing_North)
|
||||||
|
@ -372,6 +373,8 @@ func TestWorld_Broadcast(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Warp rovers near to eachother
|
// Warp rovers near to eachother
|
||||||
|
world.Atlas.SetObject(maths.Vector{X: 0, Y: 0}, Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
|
world.Atlas.SetObject(maths.Vector{X: 1, Y: 0}, Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
assert.NoError(t, world.WarpRover(a, maths.Vector{X: 0, Y: 0}))
|
assert.NoError(t, world.WarpRover(a, maths.Vector{X: 0, Y: 0}))
|
||||||
assert.NoError(t, world.WarpRover(b, maths.Vector{X: 1, Y: 0}))
|
assert.NoError(t, world.WarpRover(b, maths.Vector{X: 1, Y: 0}))
|
||||||
|
|
||||||
|
@ -390,7 +393,7 @@ func TestWorld_Broadcast(t *testing.T) {
|
||||||
assert.Contains(t, rb.Logs[len(rb.Logs)-1].Text, "ABC", "Rover A should have logged it's broadcast")
|
assert.Contains(t, rb.Logs[len(rb.Logs)-1].Text, "ABC", "Rover A should have logged it's broadcast")
|
||||||
|
|
||||||
// Warp B outside of the range of A
|
// Warp B outside of the range of A
|
||||||
world.Atlas.SetObject(maths.Vector{X: ra.Range, Y: 0}, atlas.Object{Type: roveapi.Object_ObjectUnknown})
|
world.Atlas.SetObject(maths.Vector{X: ra.Range, Y: 0}, Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
assert.NoError(t, world.WarpRover(b, maths.Vector{X: ra.Range, Y: 0}))
|
assert.NoError(t, world.WarpRover(b, maths.Vector{X: ra.Range, Y: 0}))
|
||||||
|
|
||||||
// Broadcast from a again
|
// Broadcast from a again
|
||||||
|
@ -407,7 +410,7 @@ func TestWorld_Broadcast(t *testing.T) {
|
||||||
assert.Contains(t, rb.Logs[len(rb.Logs)-1].Text, "XYZ", "Rover A should have logged it's broadcast")
|
assert.Contains(t, rb.Logs[len(rb.Logs)-1].Text, "XYZ", "Rover A should have logged it's broadcast")
|
||||||
|
|
||||||
// Warp B outside of the range of A
|
// Warp B outside of the range of A
|
||||||
world.Atlas.SetObject(maths.Vector{X: ra.Range + 1, Y: 0}, atlas.Object{Type: roveapi.Object_ObjectUnknown})
|
world.Atlas.SetObject(maths.Vector{X: ra.Range + 1, Y: 0}, Object{Type: roveapi.Object_ObjectUnknown})
|
||||||
assert.NoError(t, world.WarpRover(b, maths.Vector{X: ra.Range + 1, Y: 0}))
|
assert.NoError(t, world.WarpRover(b, maths.Vector{X: ra.Range + 1, Y: 0}))
|
||||||
|
|
||||||
// Broadcast from a again
|
// Broadcast from a again
|
||||||
|
|
93
pkg/rove/worldgen.go
Normal file
93
pkg/rove/worldgen.go
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
package rove
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/mdiluz/rove/pkg/maths"
|
||||||
|
"github.com/mdiluz/rove/proto/roveapi"
|
||||||
|
"github.com/ojrac/opensimplex-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WorldGen describes a world gen algorythm
|
||||||
|
type WorldGen interface {
|
||||||
|
// GetTile generates a tile for a location
|
||||||
|
GetTile(v maths.Vector) roveapi.Tile
|
||||||
|
|
||||||
|
// GetObject generates an object for a location
|
||||||
|
GetObject(v maths.Vector) Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoiseWorldGen returns a noise based world generator
|
||||||
|
type NoiseWorldGen struct {
|
||||||
|
// noise describes the noise function
|
||||||
|
noise opensimplex.Noise
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNoiseWorldGen creates a new noise based world generator
|
||||||
|
func NewNoiseWorldGen(seed int64) WorldGen {
|
||||||
|
return &NoiseWorldGen{
|
||||||
|
noise: opensimplex.New(seed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
terrainNoiseScale = 6
|
||||||
|
rockNoiseScale = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetTile returns the chosen tile at a location
|
||||||
|
func (g *NoiseWorldGen) GetTile(v maths.Vector) roveapi.Tile {
|
||||||
|
t := g.noise.Eval2(float64(v.X)/terrainNoiseScale, float64(v.Y)/terrainNoiseScale)
|
||||||
|
switch {
|
||||||
|
case t > 0.5:
|
||||||
|
return roveapi.Tile_Gravel
|
||||||
|
case t > 0.05:
|
||||||
|
return roveapi.Tile_Sand
|
||||||
|
default:
|
||||||
|
return roveapi.Tile_Rock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetObject returns the chosen object at a location
|
||||||
|
func (g *NoiseWorldGen) GetObject(v maths.Vector) (obj Object) {
|
||||||
|
o := g.noise.Eval2(float64(v.X)/rockNoiseScale, float64(v.Y)/rockNoiseScale)
|
||||||
|
switch {
|
||||||
|
case o > 0.6:
|
||||||
|
obj.Type = roveapi.Object_RockLarge
|
||||||
|
case o > 0.5:
|
||||||
|
obj.Type = roveapi.Object_RockSmall
|
||||||
|
}
|
||||||
|
|
||||||
|
// Very rarely spawn a dormant rover
|
||||||
|
if obj.Type == roveapi.Object_ObjectUnknown {
|
||||||
|
// TODO: Make this better, ideally with noise
|
||||||
|
if v.X%25 == 0 && v.Y%25 == 0 && v.X != 0 && v.Y != 0 {
|
||||||
|
obj.Type = roveapi.Object_RoverDormant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post process any spawned objects
|
||||||
|
switch obj.Type {
|
||||||
|
case roveapi.Object_RoverDormant:
|
||||||
|
// Create the rover
|
||||||
|
r := DefaultRover()
|
||||||
|
|
||||||
|
// Set the rover variables
|
||||||
|
r.Pos = v
|
||||||
|
|
||||||
|
// For now, mark the log as corrupted
|
||||||
|
r.AddLogEntryf("log corrupted")
|
||||||
|
|
||||||
|
// Marshal the rover data into the object data
|
||||||
|
b, err := json.Marshal(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("couldn't marshal rover, should never fail: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the bytes
|
||||||
|
obj.Data = b
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj
|
||||||
|
}
|
|
@ -162,10 +162,12 @@ const (
|
||||||
Object_ObjectUnknown Object = 0
|
Object_ObjectUnknown Object = 0
|
||||||
// RoverLive represents a live rover
|
// RoverLive represents a live rover
|
||||||
Object_RoverLive Object = 1
|
Object_RoverLive Object = 1
|
||||||
|
// RoverDormant describes a dormant rover
|
||||||
|
Object_RoverDormant Object = 2
|
||||||
// RockSmall is a small stashable rock
|
// RockSmall is a small stashable rock
|
||||||
Object_RockSmall Object = 2
|
Object_RockSmall Object = 3
|
||||||
// RockLarge is a large blocking rock
|
// RockLarge is a large blocking rock
|
||||||
Object_RockLarge Object = 3
|
Object_RockLarge Object = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for Object.
|
// Enum value maps for Object.
|
||||||
|
@ -173,14 +175,16 @@ var (
|
||||||
Object_name = map[int32]string{
|
Object_name = map[int32]string{
|
||||||
0: "ObjectUnknown",
|
0: "ObjectUnknown",
|
||||||
1: "RoverLive",
|
1: "RoverLive",
|
||||||
2: "RockSmall",
|
2: "RoverDormant",
|
||||||
3: "RockLarge",
|
3: "RockSmall",
|
||||||
|
4: "RockLarge",
|
||||||
}
|
}
|
||||||
Object_value = map[string]int32{
|
Object_value = map[string]int32{
|
||||||
"ObjectUnknown": 0,
|
"ObjectUnknown": 0,
|
||||||
"RoverLive": 1,
|
"RoverLive": 1,
|
||||||
"RockSmall": 2,
|
"RoverDormant": 2,
|
||||||
"RockLarge": 3,
|
"RockSmall": 3,
|
||||||
|
"RockLarge": 4,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1269,39 +1273,40 @@ var file_roveapi_roveapi_proto_rawDesc = []byte{
|
||||||
0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4e, 0x6f, 0x72, 0x74, 0x68,
|
0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4e, 0x6f, 0x72, 0x74, 0x68,
|
||||||
0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x61, 0x73, 0x74, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05,
|
0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x61, 0x73, 0x74, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05,
|
||||||
0x53, 0x6f, 0x75, 0x74, 0x68, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x65, 0x73, 0x74, 0x10,
|
0x53, 0x6f, 0x75, 0x74, 0x68, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x65, 0x73, 0x74, 0x10,
|
||||||
0x04, 0x2a, 0x48, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x11, 0x0a, 0x0d, 0x4f,
|
0x04, 0x2a, 0x5a, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x11, 0x0a, 0x0d, 0x4f,
|
||||||
0x62, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0d,
|
0x62, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0d,
|
||||||
0x0a, 0x09, 0x52, 0x6f, 0x76, 0x65, 0x72, 0x4c, 0x69, 0x76, 0x65, 0x10, 0x01, 0x12, 0x0d, 0x0a,
|
0x0a, 0x09, 0x52, 0x6f, 0x76, 0x65, 0x72, 0x4c, 0x69, 0x76, 0x65, 0x10, 0x01, 0x12, 0x10, 0x0a,
|
||||||
0x09, 0x52, 0x6f, 0x63, 0x6b, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09,
|
0x0c, 0x52, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x74, 0x10, 0x02, 0x12,
|
||||||
0x52, 0x6f, 0x63, 0x6b, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x10, 0x03, 0x2a, 0x37, 0x0a, 0x04, 0x54,
|
0x0d, 0x0a, 0x09, 0x52, 0x6f, 0x63, 0x6b, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x10, 0x03, 0x12, 0x0d,
|
||||||
0x69, 0x6c, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x69, 0x6c, 0x65, 0x55, 0x6e, 0x6b, 0x6e, 0x6f,
|
0x0a, 0x09, 0x52, 0x6f, 0x63, 0x6b, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x10, 0x04, 0x2a, 0x37, 0x0a,
|
||||||
0x77, 0x6e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x6f, 0x63, 0x6b, 0x10, 0x01, 0x12, 0x0a,
|
0x04, 0x54, 0x69, 0x6c, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x69, 0x6c, 0x65, 0x55, 0x6e, 0x6b,
|
||||||
0x0a, 0x06, 0x47, 0x72, 0x61, 0x76, 0x65, 0x6c, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x61,
|
0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x6f, 0x63, 0x6b, 0x10, 0x01,
|
||||||
0x6e, 0x64, 0x10, 0x03, 0x32, 0xcf, 0x02, 0x0a, 0x04, 0x52, 0x6f, 0x76, 0x65, 0x12, 0x4d, 0x0a,
|
0x12, 0x0a, 0x0a, 0x06, 0x47, 0x72, 0x61, 0x76, 0x65, 0x6c, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04,
|
||||||
0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x2e,
|
0x53, 0x61, 0x6e, 0x64, 0x10, 0x03, 0x32, 0xcf, 0x02, 0x0a, 0x04, 0x52, 0x6f, 0x76, 0x65, 0x12,
|
||||||
|
0x4d, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
|
||||||
|
0x1c, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||||
|
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e,
|
||||||
0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74,
|
0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74,
|
||||||
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x6f,
|
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41,
|
||||||
0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
|
0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x72, 0x6f, 0x76,
|
||||||
0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x08,
|
0x65, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71,
|
||||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61,
|
0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x52,
|
||||||
0x70, 0x69, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x67,
|
0x00, 0x12, 0x3e, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x72,
|
||||||
0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65,
|
||||||
0x3e, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x72, 0x6f, 0x76,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e,
|
||||||
0x65, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
|
0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f,
|
0x00, 0x12, 0x38, 0x0a, 0x05, 0x52, 0x61, 0x64, 0x61, 0x72, 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x76,
|
||||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
0x65, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x38, 0x0a, 0x05, 0x52, 0x61, 0x64, 0x61, 0x72, 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61,
|
0x74, 0x1a, 0x16, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x61, 0x64, 0x61,
|
||||||
0x70, 0x69, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x06, 0x53,
|
||||||
0x16, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52,
|
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x06, 0x53, 0x74, 0x61,
|
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e,
|
||||||
0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74,
|
0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65,
|
||||||
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x72, 0x6f,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68,
|
||||||
0x76, 0x65, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70,
|
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x64, 0x69, 0x6c, 0x75, 0x7a, 0x2f, 0x72, 0x6f,
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
0x76, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69,
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x64, 0x69, 0x6c, 0x75, 0x7a, 0x2f, 0x72, 0x6f, 0x76, 0x65,
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x61, 0x70, 0x69, 0x62, 0x06,
|
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -151,11 +151,14 @@ enum Object {
|
||||||
// RoverLive represents a live rover
|
// RoverLive represents a live rover
|
||||||
RoverLive = 1;
|
RoverLive = 1;
|
||||||
|
|
||||||
|
// RoverDormant describes a dormant rover
|
||||||
|
RoverDormant = 2;
|
||||||
|
|
||||||
// RockSmall is a small stashable rock
|
// RockSmall is a small stashable rock
|
||||||
RockSmall = 2;
|
RockSmall = 3;
|
||||||
|
|
||||||
// RockLarge is a large blocking rock
|
// RockLarge is a large blocking rock
|
||||||
RockLarge = 3;
|
RockLarge = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Tile {
|
enum Tile {
|
||||||
|
|
Loading…
Add table
Reference in a new issue