Split Atlas chunks into tiles and objects

This commit is contained in:
Marc Di Luzio 2020-07-03 17:00:04 +01:00
parent 74dcae6542
commit 062f9cfec8
11 changed files with 284 additions and 169 deletions

View file

@ -108,6 +108,7 @@ func TestServer_Radar(t *testing.T) {
assert.NotZero(t, resp.Range, "Radar should return valid range") assert.NotZero(t, resp.Range, "Radar should return valid range")
w := int(resp.Range*2 + 1) w := int(resp.Range*2 + 1)
assert.Equal(t, w*w, len(resp.Tiles), "radar should return correct number of tiles") assert.Equal(t, w*w, len(resp.Tiles), "radar should return correct number of tiles")
assert.Equal(t, w*w, len(resp.Objects), "radar should return correct number of objects")
} }
func TestServer_Rover(t *testing.T) { func TestServer_Rover(t *testing.T) {

View file

@ -59,6 +59,11 @@ func (s *Server) Rover(ctx context.Context, req *rove.RoverRequest) (*rove.Rover
return nil, fmt.Errorf("error getting rover: %s", err) return nil, fmt.Errorf("error getting rover: %s", err)
} else { } else {
var inv []byte
for _, i := range rover.Inventory {
inv = append(inv, byte(i.Type))
}
response = &rove.RoverResponse{ response = &rove.RoverResponse{
Name: rover.Name, Name: rover.Name,
Position: &rove.Vector{ Position: &rove.Vector{
@ -66,7 +71,7 @@ func (s *Server) Rover(ctx context.Context, req *rove.RoverRequest) (*rove.Rover
Y: int32(rover.Pos.Y), Y: int32(rover.Pos.Y),
}, },
Range: int32(rover.Range), Range: int32(rover.Range),
Inventory: rover.Inventory, Inventory: inv,
Integrity: int32(rover.Integrity), Integrity: int32(rover.Integrity),
} }
} }
@ -88,10 +93,11 @@ func (s *Server) Radar(ctx context.Context, req *rove.RadarRequest) (*rove.Radar
} else if rover, err := s.world.GetRover(resp); err != nil { } else if rover, err := s.world.GetRover(resp); err != nil {
return nil, fmt.Errorf("error getting rover attributes: %s", err) return nil, fmt.Errorf("error getting rover attributes: %s", err)
} else if radar, err := s.world.RadarFromRover(resp); err != nil { } else if radar, objs, err := s.world.RadarFromRover(resp); err != nil {
return nil, fmt.Errorf("error getting radar from rover: %s", err) return nil, fmt.Errorf("error getting radar from rover: %s", err)
} else { } else {
response.Objects = objs
response.Tiles = radar response.Tiles = radar
response.Range = int32(rover.Range) response.Range = int32(rover.Range)
} }

View file

@ -1,7 +1,6 @@
package atlas package atlas
import ( import (
"log"
"math/rand" "math/rand"
"github.com/mdiluz/rove/pkg/maths" "github.com/mdiluz/rove/pkg/maths"
@ -9,27 +8,28 @@ import (
"github.com/mdiluz/rove/pkg/vector" "github.com/mdiluz/rove/pkg/vector"
) )
// Tile describes the type of terrain
type Tile byte
const (
// TileNone is a keyword for nothing
TileNone = Tile(0)
// TileRock is solid rock ground
TileRock = Tile('.')
// TileSand is sand
TileSand = Tile(',')
)
// Chunk represents a fixed square grid of tiles // Chunk represents a fixed square grid of tiles
type Chunk struct { type Chunk struct {
// Tiles represents the tiles within the chunk // Tiles represents the tiles within the chunk
Tiles []byte `json:"tiles"` Tiles []byte `json:"tiles"`
}
// SpawnContent will create a chunk and fill it with spawned tiles // Objects represents the objects within the chunk
func (c *Chunk) SpawnContent(size int) { // only one possible object per tile for now
c.Tiles = make([]byte, size*size) Objects map[int]objects.Object `json:"objects"`
for i := 0; i < len(c.Tiles); i++ {
c.Tiles[i] = objects.Empty
}
// For now, fill it randomly with objects
for i := range c.Tiles {
if rand.Intn(16) == 0 {
c.Tiles[i] = objects.LargeRock
} else if rand.Intn(32) == 0 {
c.Tiles[i] = objects.SmallRock
}
}
} }
// Atlas represents a grid of Chunks // Atlas represents a grid of Chunks
@ -58,50 +58,101 @@ func NewAtlas(chunkSize int) Atlas {
WorldOrigin: vector.Vector{X: 0, Y: 0}, WorldOrigin: vector.Vector{X: 0, Y: 0},
} }
// Initialise the first chunk // Initialise the first chunk
a.Chunks[0].SpawnContent(chunkSize) a.Chunks[0].populate(chunkSize)
return a return a
} }
// SetTile sets an individual tile's kind // SetTile sets an individual tile's kind
func (a *Atlas) SetTile(v vector.Vector, tile byte) { func (a *Atlas) SetTile(v vector.Vector, tile Tile) {
// Get the chunk
c := a.worldSpaceToChunkWithGrow(v) c := a.worldSpaceToChunkWithGrow(v)
local := a.worldSpaceToChunkLocal(v)
a.setTile(c, local, byte(tile))
}
// SetObject sets the object on a tile
func (a *Atlas) SetObject(v vector.Vector, obj objects.Object) {
c := a.worldSpaceToChunkWithGrow(v)
local := a.worldSpaceToChunkLocal(v)
a.setObject(c, local, obj)
}
// QueryPosition will return information for a specific position
func (a *Atlas) QueryPosition(v vector.Vector) (byte, objects.Object) {
c := a.worldSpaceToChunkWithGrow(v)
local := a.worldSpaceToChunkLocal(v)
chunk := a.Chunks[c] chunk := a.Chunks[c]
if chunk.Tiles == nil { if chunk.Tiles == nil {
chunk.SpawnContent(a.ChunkSize) chunk.populate(a.ChunkSize)
}
i := a.chunkTileIndex(local)
return chunk.Tiles[i], chunk.Objects[i]
} }
local := a.worldSpaceToChunkLocal(v) // chunkTileID returns the tile index within a chunk
tileID := local.X + local.Y*a.ChunkSize func (a *Atlas) chunkTileIndex(local vector.Vector) int {
return local.X + local.Y*a.ChunkSize
// Sanity check
if tileID >= len(chunk.Tiles) || tileID < 0 {
log.Fatalf("Local tileID is not in valid chunk, somehow, this means something is very wrong")
} }
// Set the chunk back // populate will fill a chunk with data
chunk.Tiles[tileID] = tile func (c *Chunk) populate(size int) {
a.Chunks[c] = chunk c.Tiles = make([]byte, size*size)
c.Objects = make(map[int]objects.Object)
// Set up the tiles
for i := 0; i < len(c.Tiles); i++ {
if rand.Intn(3) == 0 {
c.Tiles[i] = byte(TileRock)
} else {
c.Tiles[i] = byte(TileSand)
}
} }
// GetTile will return an individual tile // Set up any objects
func (a *Atlas) GetTile(v vector.Vector) byte { for i := 0; i < len(c.Tiles); i++ {
// Get the chunk if rand.Intn(16) == 0 {
c := a.worldSpaceToChunkWithGrow(v) c.Objects[i] = objects.Object{Type: objects.LargeRock}
chunk := a.Chunks[c] }
if chunk.Tiles == nil { }
chunk.SpawnContent(a.ChunkSize)
} }
local := a.worldSpaceToChunkLocal(v) // setTile sets a tile in a specific chunk
tileID := local.X + local.Y*a.ChunkSize func (a *Atlas) setTile(chunk int, local vector.Vector, tile byte) {
c := a.Chunks[chunk]
// Sanity check if c.Tiles == nil {
if tileID >= len(chunk.Tiles) || tileID < 0 { c.populate(a.ChunkSize)
log.Fatalf("Local tileID is not in valid chunk, somehow, this means something is very wrong")
} }
return chunk.Tiles[tileID] c.Tiles[a.chunkTileIndex(local)] = tile
a.Chunks[chunk] = c
}
// setObject sets an object in a specific chunk
func (a *Atlas) setObject(chunk int, local vector.Vector, object objects.Object) {
c := a.Chunks[chunk]
if c.Tiles == nil {
c.populate(a.ChunkSize)
}
i := a.chunkTileIndex(local)
if object.Type != objects.None {
c.Objects[i] = object
} else {
delete(c.Objects, i)
}
a.Chunks[chunk] = c
}
// setTileAndObject sets both tile and object information for location in chunk
func (a *Atlas) setTileAndObject(chunk int, local vector.Vector, tile byte, object objects.Object) {
c := a.Chunks[chunk]
if c.Tiles == nil {
c.populate(a.ChunkSize)
}
i := a.chunkTileIndex(local)
c.Tiles[i] = tile
c.Objects[i] = object
a.Chunks[chunk] = c
} }
// worldSpaceToChunkLocal gets a chunk local coordinate for a tile // worldSpaceToChunkLocal gets a chunk local coordinate for a tile

View file

@ -3,6 +3,7 @@ package atlas
import ( import (
"testing" "testing"
"github.com/mdiluz/rove/pkg/objects"
"github.com/mdiluz/rove/pkg/vector" "github.com/mdiluz/rove/pkg/vector"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -19,8 +20,8 @@ func TestAtlas_toChunk(t *testing.T) {
assert.NotNil(t, a) assert.NotNil(t, a)
// Get a tile to spawn the chunks // Get a tile to spawn the chunks
a.GetTile(vector.Vector{X: -1, Y: -1}) a.QueryPosition(vector.Vector{X: -1, Y: -1})
a.GetTile(vector.Vector{X: 0, Y: 0}) a.QueryPosition(vector.Vector{X: 0, Y: 0})
// Chunks should look like: // Chunks should look like:
// 2 | 3 // 2 | 3
@ -38,8 +39,8 @@ func TestAtlas_toChunk(t *testing.T) {
a = NewAtlas(2) a = NewAtlas(2)
assert.NotNil(t, a) assert.NotNil(t, a)
// Get a tile to spawn the chunks // Get a tile to spawn the chunks
a.GetTile(vector.Vector{X: -2, Y: -2}) a.QueryPosition(vector.Vector{X: -2, Y: -2})
a.GetTile(vector.Vector{X: 1, Y: 1}) a.QueryPosition(vector.Vector{X: 1, Y: 1})
// Chunks should look like: // Chunks should look like:
// 2 | 3 // 2 | 3
// ----- // -----
@ -56,8 +57,8 @@ func TestAtlas_toChunk(t *testing.T) {
a = NewAtlas(2) a = NewAtlas(2)
assert.NotNil(t, a) assert.NotNil(t, a)
// Get a tile to spawn the chunks // Get a tile to spawn the chunks
a.GetTile(vector.Vector{X: 5, Y: 5}) a.QueryPosition(vector.Vector{X: 5, Y: 5})
a.GetTile(vector.Vector{X: -5, Y: -5}) a.QueryPosition(vector.Vector{X: -5, Y: -5})
// Chunks should look like: // Chunks should look like:
// 12| 13|| 14| 15 // 12| 13|| 14| 15
// ---------------- // ----------------
@ -82,15 +83,30 @@ func TestAtlas_GetSetTile(t *testing.T) {
// Set the origin tile to 1 and test it // Set the origin tile to 1 and test it
a.SetTile(vector.Vector{X: 0, Y: 0}, 1) a.SetTile(vector.Vector{X: 0, Y: 0}, 1)
tile := a.GetTile(vector.Vector{X: 0, Y: 0}) tile, _ := a.QueryPosition(vector.Vector{X: 0, Y: 0})
assert.Equal(t, byte(1), tile) assert.Equal(t, byte(1), tile)
// Set another tile to 1 and test it // Set another tile to 1 and test it
a.SetTile(vector.Vector{X: 5, Y: -2}, 2) a.SetTile(vector.Vector{X: 5, Y: -2}, 2)
tile = a.GetTile(vector.Vector{X: 5, Y: -2}) tile, _ = a.QueryPosition(vector.Vector{X: 5, Y: -2})
assert.Equal(t, byte(2), tile) assert.Equal(t, byte(2), tile)
} }
func TestAtlas_GetSetObject(t *testing.T) {
a := NewAtlas(10)
assert.NotNil(t, a)
// Set the origin tile to 1 and test it
a.SetObject(vector.Vector{X: 0, Y: 0}, objects.Object{Type: objects.LargeRock})
_, obj := a.QueryPosition(vector.Vector{X: 0, Y: 0})
assert.Equal(t, objects.Object{Type: objects.LargeRock}, obj)
// Set another tile to 1 and test it
a.SetObject(vector.Vector{X: 5, Y: -2}, objects.Object{Type: objects.SmallRock})
_, obj = a.QueryPosition(vector.Vector{X: 5, Y: -2})
assert.Equal(t, objects.Object{Type: objects.SmallRock}, obj)
}
func TestAtlas_Grown(t *testing.T) { func TestAtlas_Grown(t *testing.T) {
// Start with a small example // Start with a small example
a := NewAtlas(2) a := NewAtlas(2)
@ -103,21 +119,21 @@ func TestAtlas_Grown(t *testing.T) {
a.SetTile(vector.Vector{X: 1, Y: -2}, 3) a.SetTile(vector.Vector{X: 1, Y: -2}, 3)
// Check tile values // Check tile values
tile := a.GetTile(vector.Vector{X: 0, Y: 0}) tile, _ := a.QueryPosition(vector.Vector{X: 0, Y: 0})
assert.Equal(t, byte(1), tile) assert.Equal(t, byte(1), tile)
tile = a.GetTile(vector.Vector{X: -1, Y: -1}) tile, _ = a.QueryPosition(vector.Vector{X: -1, Y: -1})
assert.Equal(t, byte(2), tile) assert.Equal(t, byte(2), tile)
tile = a.GetTile(vector.Vector{X: 1, Y: -2}) tile, _ = a.QueryPosition(vector.Vector{X: 1, Y: -2})
assert.Equal(t, byte(3), tile) assert.Equal(t, byte(3), tile)
tile = a.GetTile(vector.Vector{X: 0, Y: 0}) tile, _ = a.QueryPosition(vector.Vector{X: 0, Y: 0})
assert.Equal(t, byte(1), tile) assert.Equal(t, byte(1), tile)
tile = a.GetTile(vector.Vector{X: -1, Y: -1}) tile, _ = a.QueryPosition(vector.Vector{X: -1, Y: -1})
assert.Equal(t, byte(2), tile) assert.Equal(t, byte(2), tile)
tile = a.GetTile(vector.Vector{X: 1, Y: -2}) tile, _ = a.QueryPosition(vector.Vector{X: 1, Y: -2})
assert.Equal(t, byte(3), tile) assert.Equal(t, byte(3), tile)
} }

View file

@ -1,6 +1,7 @@
package game package game
import ( import (
"github.com/mdiluz/rove/pkg/objects"
"github.com/mdiluz/rove/pkg/vector" "github.com/mdiluz/rove/pkg/vector"
) )
@ -16,7 +17,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 []byte `json:"inventory"` Inventory []objects.Object `json:"inventory"`
// Integrity represents current rover health // Integrity represents current rover health
Integrity int `json:"integrity"` Integrity int `json:"integrity"`

View file

@ -101,8 +101,8 @@ func (w *World) SpawnRover() (string, error) {
// Seach until we error (run out of world) // Seach until we error (run out of world)
for { for {
tile := w.Atlas.GetTile(rover.Pos) _, obj := w.Atlas.QueryPosition(rover.Pos)
if !objects.IsBlocking(tile) { if !obj.IsBlocking() {
break break
} else { } else {
// Try and spawn to the east of the blockage // Try and spawn to the east of the blockage
@ -136,13 +136,11 @@ func (w *World) DestroyRover(rover string) error {
w.worldMutex.Lock() w.worldMutex.Lock()
defer w.worldMutex.Unlock() defer w.worldMutex.Unlock()
i, ok := w.Rovers[rover] _, ok := w.Rovers[rover]
if !ok { if !ok {
return fmt.Errorf("no rover matching id") return fmt.Errorf("no rover matching id")
} }
// Clear the tile
w.Atlas.SetTile(i.Pos, objects.Empty)
delete(w.Rovers, rover) delete(w.Rovers, rover)
return nil return nil
} }
@ -175,7 +173,7 @@ func (w *World) SetRoverPosition(rover string, pos vector.Vector) error {
} }
// RoverInventory returns the inventory of a requested rover // RoverInventory returns the inventory of a requested rover
func (w *World) RoverInventory(rover string) ([]byte, error) { func (w *World) RoverInventory(rover string) ([]objects.Object, error) {
w.worldMutex.RLock() w.worldMutex.RLock()
defer w.worldMutex.RUnlock() defer w.worldMutex.RUnlock()
@ -201,8 +199,8 @@ func (w *World) WarpRover(rover string, pos vector.Vector) error {
} }
// Check the tile is not blocked // Check the tile is not blocked
tile := w.Atlas.GetTile(pos) _, obj := w.Atlas.QueryPosition(pos)
if objects.IsBlocking(tile) { if obj.IsBlocking() {
return fmt.Errorf("can't warp rover to occupied tile, check before warping") return fmt.Errorf("can't warp rover to occupied tile, check before warping")
} }
@ -224,8 +222,8 @@ func (w *World) MoveRover(rover string, b bearing.Bearing) (vector.Vector, error
newPos := i.Pos.Added(b.Vector()) newPos := i.Pos.Added(b.Vector())
// Get the tile and verify it's empty // Get the tile and verify it's empty
tile := w.Atlas.GetTile(newPos) _, obj := w.Atlas.QueryPosition(newPos)
if !objects.IsBlocking(tile) { if !obj.IsBlocking() {
// Perform the move // Perform the move
i.Pos = newPos i.Pos = newPos
w.Rovers[rover] = i w.Rovers[rover] = i
@ -243,34 +241,35 @@ func (w *World) MoveRover(rover string, b bearing.Bearing) (vector.Vector, error
} }
// RoverStash will stash an item at the current rovers position // RoverStash will stash an item at the current rovers position
func (w *World) RoverStash(rover string) (byte, error) { func (w *World) RoverStash(rover string) (objects.Type, error) {
w.worldMutex.Lock() w.worldMutex.Lock()
defer w.worldMutex.Unlock() defer w.worldMutex.Unlock()
r, ok := w.Rovers[rover] r, ok := w.Rovers[rover]
if !ok { if !ok {
return objects.Empty, fmt.Errorf("no rover matching id") return objects.None, fmt.Errorf("no rover matching id")
} }
tile := w.Atlas.GetTile(r.Pos) _, obj := w.Atlas.QueryPosition(r.Pos)
if !objects.IsStashable(tile) { if !obj.IsStashable() {
return objects.Empty, nil return objects.None, nil
} }
r.Inventory = append(r.Inventory, tile) r.Inventory = append(r.Inventory, obj)
w.Rovers[rover] = r w.Rovers[rover] = r
w.Atlas.SetTile(r.Pos, objects.Empty) w.Atlas.SetObject(r.Pos, objects.Object{Type: objects.None})
return tile, nil return obj.Type, nil
} }
// RadarFromRover can be used to query what a rover can currently see // RadarFromRover can be used to query what a rover can currently see
func (w *World) RadarFromRover(rover string) ([]byte, error) { func (w *World) RadarFromRover(rover string) (radar []byte, objs []byte, err error) {
w.worldMutex.RLock() w.worldMutex.RLock()
defer w.worldMutex.RUnlock() defer w.worldMutex.RUnlock()
r, ok := w.Rovers[rover] r, ok := w.Rovers[rover]
if !ok { if !ok {
return nil, fmt.Errorf("no rover matching id") err = fmt.Errorf("no rover matching id")
return
} }
// The radar should span in range direction on each axis, plus the row/column the rover is currently on // The radar should span in range direction on each axis, plus the row/column the rover is currently on
@ -288,18 +287,19 @@ func (w *World) RadarFromRover(rover string) ([]byte, error) {
} }
// Gather up all tiles within the range // Gather up all tiles within the range
var radar = make([]byte, radarSpan*radarSpan) radar = make([]byte, radarSpan*radarSpan)
objs = make([]byte, radarSpan*radarSpan)
for j := radarMin.Y; j <= radarMax.Y; j++ { for j := radarMin.Y; j <= radarMax.Y; j++ {
for i := radarMin.X; i <= radarMax.X; i++ { for i := radarMin.X; i <= radarMax.X; i++ {
q := vector.Vector{X: i, Y: j} q := vector.Vector{X: i, Y: j}
tile := w.Atlas.GetTile(q) tile, obj := w.Atlas.QueryPosition(q)
// Get the position relative to the bottom left of the radar // Get the position relative to the bottom left of the radar
relative := q.Added(radarMin.Negated()) relative := q.Added(radarMin.Negated())
index := relative.X + relative.Y*radarSpan index := relative.X + relative.Y*radarSpan
radar[index] = tile radar[index] = tile
objs[index] = byte(obj.Type)
} }
} }
@ -312,14 +312,11 @@ func (w *World) RadarFromRover(rover string) ([]byte, error) {
if dist.X <= r.Range && dist.Y <= r.Range { if dist.X <= r.Range && dist.Y <= r.Range {
relative := r.Pos.Added(radarMin.Negated()) relative := r.Pos.Added(radarMin.Negated())
index := relative.X + relative.Y*radarSpan index := relative.X + relative.Y*radarSpan
radar[index] = objects.Rover objs[index] = byte(objects.Rover)
} }
} }
// Add this rover return radar, objs, nil
radar[len(radar)/2] = objects.Rover
return radar, nil
} }
// Enqueue will queue the commands given // Enqueue will queue the commands given
@ -433,7 +430,14 @@ func PrintTiles(tiles []byte) {
num := int(math.Sqrt(float64(len(tiles)))) num := int(math.Sqrt(float64(len(tiles))))
for j := num - 1; j >= 0; j-- { for j := num - 1; j >= 0; j-- {
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
fmt.Printf("%c", tiles[i+num*j])
t := tiles[i+num*j]
if t != 0 {
fmt.Printf("%c", t)
} else {
fmt.Printf(" ")
}
} }
fmt.Print("\n") fmt.Print("\n")
} }

View file

@ -3,6 +3,7 @@ package game
import ( import (
"testing" "testing"
"github.com/mdiluz/rove/pkg/atlas"
"github.com/mdiluz/rove/pkg/bearing" "github.com/mdiluz/rove/pkg/bearing"
"github.com/mdiluz/rove/pkg/objects" "github.com/mdiluz/rove/pkg/objects"
"github.com/mdiluz/rove/pkg/vector" "github.com/mdiluz/rove/pkg/vector"
@ -84,7 +85,7 @@ func TestWorld_GetSetMovePosition(t *testing.T) {
assert.Equal(t, pos, newPos, "Failed to correctly move position for rover") assert.Equal(t, pos, newPos, "Failed to correctly move position for rover")
// Place a tile in front of the rover // Place a tile in front of the rover
world.Atlas.SetTile(vector.Vector{X: 0, Y: 2}, objects.LargeRock) world.Atlas.SetObject(vector.Vector{X: 0, Y: 2}, objects.Object{Type: objects.LargeRock})
newPos, err = world.MoveRover(a, b) newPos, err = world.MoveRover(a, b)
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")
} }
@ -102,14 +103,15 @@ func TestWorld_RadarFromRover(t *testing.T) {
assert.NoError(t, world.WarpRover(b, bpos), "Failed to warp rover") assert.NoError(t, world.WarpRover(b, bpos), "Failed to warp rover")
assert.NoError(t, world.WarpRover(a, vector.Vector{X: 0, Y: 0}), "Failed to warp rover") assert.NoError(t, world.WarpRover(a, vector.Vector{X: 0, Y: 0}), "Failed to warp rover")
radar, err := world.RadarFromRover(a) radar, objs, err := world.RadarFromRover(a)
assert.NoError(t, err, "Failed to get radar from rover") assert.NoError(t, err, "Failed to get radar from rover")
fullRange := 4 + 4 + 1 fullRange := 4 + 4 + 1
assert.Equal(t, fullRange*fullRange, len(radar), "Radar returned wrong length") assert.Equal(t, fullRange*fullRange, len(radar), "Radar returned wrong length")
assert.Equal(t, fullRange*fullRange, len(objs), "Radar returned wrong length")
// Test the expected values // Test the expected values
assert.Equal(t, objects.Rover, radar[1+fullRange]) assert.Equal(t, byte(objects.Rover), objs[1+fullRange])
assert.Equal(t, objects.Rover, radar[4+4*fullRange]) assert.Equal(t, byte(objects.Rover), objs[4+4*fullRange])
} }
func TestWorld_RoverStash(t *testing.T) { func TestWorld_RoverStash(t *testing.T) {
@ -125,18 +127,20 @@ func TestWorld_RoverStash(t *testing.T) {
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")
world.Atlas.SetTile(pos, objects.SmallRock) // Set to a traversible tile
world.Atlas.SetTile(pos, atlas.TileRock)
world.Atlas.SetObject(pos, objects.Object{Type: objects.SmallRock})
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, objects.SmallRock, o, "Failed to get correct object") assert.Equal(t, objects.SmallRock, o, "Failed to get correct object")
tile := world.Atlas.GetTile(pos) _, obj := world.Atlas.QueryPosition(pos)
assert.Equal(t, objects.Empty, tile, "Stash failed to remove object from atlas") assert.Equal(t, objects.None, obj.Type, "Stash failed to remove object from atlas")
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, objects.SmallRock, inv[0]) assert.Equal(t, objects.Object{Type: objects.SmallRock}, inv[0])
} }
func TestWorld_RoverDamage(t *testing.T) { func TestWorld_RoverDamage(t *testing.T) {
@ -155,7 +159,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.SetTile(vector.Vector{X: 0.0, Y: 1.0}, objects.LargeRock) world.Atlas.SetObject(vector.Vector{X: 0.0, Y: 1.0}, objects.Object{Type: objects.LargeRock})
vec, err := world.MoveRover(a, bearing.North) vec, err := world.MoveRover(a, bearing.North)
assert.NoError(t, err, "Failed to move rover") assert.NoError(t, err, "Failed to move rover")
@ -176,19 +180,22 @@ func TestWorld_RoverRepair(t *testing.T) {
Y: 0.0, Y: 0.0,
} }
world.Atlas.SetTile(pos, atlas.TileNone)
world.Atlas.SetObject(pos, objects.Object{Type: objects.None})
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")
originalInfo, err := world.GetRover(a) originalInfo, err := world.GetRover(a)
assert.NoError(t, err, "couldn't get rover info") assert.NoError(t, err, "couldn't get rover info")
world.Atlas.SetTile(pos, objects.SmallRock) world.Atlas.SetObject(pos, objects.Object{Type: objects.SmallRock})
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, objects.SmallRock, o, "Failed to get correct object") assert.Equal(t, objects.SmallRock, o, "Failed to get correct object")
world.Atlas.SetTile(vector.Vector{X: 0.0, Y: 1.0}, objects.LargeRock) world.Atlas.SetObject(vector.Vector{X: 0.0, Y: 1.0}, objects.Object{Type: objects.LargeRock})
vec, err := world.MoveRover(a, bearing.North) vec, err := world.MoveRover(a, bearing.North)
assert.NoError(t, err, "Failed to move rover") assert.NoError(t, err, "Failed to move rover")

View file

@ -1,28 +1,37 @@
package objects package objects
// Type represents an object type
type Type byte
// Types of objects
const ( const (
// Empty represents an non-existant object // None represents no object at all
Empty = byte(' ') None = Type(0)
// Rover represents a live rover // Rover represents a live rover
Rover = byte('R') Rover = Type('R')
// SmallRock is a small stashable rock // SmallRock is a small stashable rock
SmallRock = byte('o') SmallRock = Type('o')
// LargeRock is a large blocking rock // LargeRock is a large blocking rock
LargeRock = byte('O') LargeRock = Type('o')
) )
// Object represents an object in the world
type Object struct {
Type Type `json:"type"`
}
// IsBlocking checks if an object is a blocking object // IsBlocking checks if an object is a blocking object
func IsBlocking(object byte) bool { func (o *Object) IsBlocking() bool {
var blocking = [...]byte{ var blocking = [...]Type{
Rover, Rover,
LargeRock, LargeRock,
} }
for _, t := range blocking { for _, t := range blocking {
if object == t { if o.Type == t {
return true return true
} }
} }
@ -30,13 +39,13 @@ func IsBlocking(object byte) bool {
} }
// IsStashable checks if an object is stashable // IsStashable checks if an object is stashable
func IsStashable(object byte) bool { func (o *Object) IsStashable() bool {
var stashable = [...]byte{ var stashable = [...]Type{
SmallRock, SmallRock,
} }
for _, t := range stashable { for _, t := range stashable {
if object == t { if o.Type == t {
return true return true
} }
} }

View file

@ -42,6 +42,7 @@ type Command struct {
// The command to execute // The command to execute
// "move" - Move the rover in a direction, requires bearing // "move" - Move the rover in a direction, requires bearing
// "stash" - Stashes item at current location in rover inventory // "stash" - Stashes item at current location in rover inventory
// "repair" - Repairs the rover using an inventory object
Command string `protobuf:"bytes,1,opt,name=command,proto3" json:"command,omitempty"` Command string `protobuf:"bytes,1,opt,name=command,proto3" json:"command,omitempty"`
// The bearing, example: NE // The bearing, example: NE
Bearing string `protobuf:"bytes,2,opt,name=bearing,proto3" json:"bearing,omitempty"` Bearing string `protobuf:"bytes,2,opt,name=bearing,proto3" json:"bearing,omitempty"`
@ -294,6 +295,8 @@ type RadarResponse struct {
Range int32 `protobuf:"varint,1,opt,name=range,proto3" json:"range,omitempty"` Range int32 `protobuf:"varint,1,opt,name=range,proto3" json:"range,omitempty"`
// A 1D array representing range*2 + 1 squared set of tiles, origin bottom left and in row->column order // A 1D array representing range*2 + 1 squared set of tiles, origin bottom left and in row->column order
Tiles []byte `protobuf:"bytes,2,opt,name=tiles,proto3" json:"tiles,omitempty"` Tiles []byte `protobuf:"bytes,2,opt,name=tiles,proto3" json:"tiles,omitempty"`
// A similar array to the tile array, but containing objects
Objects []byte `protobuf:"bytes,3,opt,name=objects,proto3" json:"objects,omitempty"`
} }
func (x *RadarResponse) Reset() { func (x *RadarResponse) Reset() {
@ -342,6 +345,13 @@ func (x *RadarResponse) GetTiles() []byte {
return nil return nil
} }
func (x *RadarResponse) GetObjects() []byte {
if x != nil {
return x.Objects
}
return nil
}
// Empty placeholder // Empty placeholder
type RegisterResponse struct { type RegisterResponse struct {
state protoimpl.MessageState state protoimpl.MessageState
@ -751,64 +761,66 @@ var file_rove_rove_proto_rawDesc = []byte{
0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22,
0x28, 0x0a, 0x0c, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0c, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3b, 0x0a, 0x0d, 0x52, 0x61, 0x64, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x55, 0x0a, 0x0d, 0x52, 0x61, 0x64,
0x61, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x61, 0x61, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x61,
0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x05, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x12, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x05, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x22, 0x12, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x65, 0x22, 0x28, 0x0a, 0x0c, 0x52, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x28, 0x0a, 0x0c, 0x52,
0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x9f, 0x01, 0x0a, 0x0d, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61,
0x52, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x9f, 0x01, 0x0a, 0x0d, 0x52, 0x6f, 0x76, 0x65, 0x72, 0x52,
0x65, 0x12, 0x28, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x08, 0x70,
0x72, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x08, 0x70, 0x6f, 0x73,
0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x04, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69,
0x1c, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09,
0x28, 0x05, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x22, 0x0f, 0x0a, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x6e, 0x74,
0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x71, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x49, 0x6e,
0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x22, 0x0f, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75,
0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x69, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x71, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74,
0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65,
0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x69, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e,
0x61, 0x64, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x65, 0x78, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79,
0x05, 0x52, 0x04, 0x74, 0x69, 0x63, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x12, 0x12, 0x0a,
0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x04, 0x74, 0x69, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x69, 0x63,
0x6e, 0x22, 0x24, 0x0a, 0x06, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x02, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x24, 0x0a, 0x06, 0x56,
0x20, 0x01, 0x28, 0x05, 0x52, 0x01, 0x79, 0x32, 0xf8, 0x02, 0x0a, 0x04, 0x52, 0x6f, 0x76, 0x65, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x12, 0x44, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x01,
0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x79, 0x32, 0xf8, 0x02, 0x0a, 0x04, 0x52, 0x6f, 0x76, 0x65, 0x12, 0x44, 0x0a, 0x06, 0x53, 0x74,
0x14, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x09, 0x12, 0x07, 0x2f, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x6f, 0x76, 0x65,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4f, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x65, 0x72, 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x0f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x09, 0x12, 0x07, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x12, 0x4f, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x72,
0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x22, 0x09, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73,
0x73, 0x74, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x4f, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4,
0x6e, 0x64, 0x73, 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x93, 0x02, 0x0e, 0x22, 0x09, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x01,
0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x6f, 0x76, 0x2a, 0x12, 0x4f, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x12, 0x15, 0x2e,
0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71,
0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x22, 0x09, 0x2f, 0x63, 0x6f, 0x6d, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
0x6d, 0x61, 0x6e, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x43, 0x0a, 0x05, 0x52, 0x61, 0x64, 0x61, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3,
0x72, 0x12, 0x12, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0xe4, 0x93, 0x02, 0x0e, 0x22, 0x09, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x3a,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x61, 0x64, 0x01, 0x2a, 0x12, 0x43, 0x0a, 0x05, 0x52, 0x61, 0x64, 0x61, 0x72, 0x12, 0x12, 0x2e, 0x72, 0x6f,
0x61, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x76, 0x65, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x02, 0x0b, 0x22, 0x06, 0x2f, 0x72, 0x61, 0x64, 0x61, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x43, 0x0a, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x61, 0x64, 0x61, 0x72, 0x52, 0x65, 0x73, 0x70,
0x05, 0x52, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x12, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x6f, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0b, 0x22, 0x06, 0x2f, 0x72,
0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x61, 0x64, 0x61, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x43, 0x0a, 0x05, 0x52, 0x6f, 0x76, 0x65, 0x72,
0x65, 0x2e, 0x52, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x12, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71,
0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0b, 0x22, 0x06, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x72, 0x6f, 0x76, 0x65, 0x2e, 0x52, 0x6f, 0x76, 0x65,
0x01, 0x2a, 0x42, 0x21, 0x5a, 0x1f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x2f, 0x6d, 0x64, 0x69, 0x6c, 0x75, 0x7a, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x0b, 0x22, 0x06, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x42, 0x21, 0x5a, 0x1f,
0x2f, 0x72, 0x6f, 0x76, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x64, 0x69, 0x6c, 0x75,
0x7a, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x72, 0x6f, 0x76, 0x65, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View file

@ -212,7 +212,7 @@
"properties": { "properties": {
"command": { "command": {
"type": "string", "type": "string",
"title": "The command to execute\n\"move\" - Move the rover in a direction, requires bearing\n\"stash\" - Stashes item at current location in rover inventory" "title": "The command to execute\n\"move\" - Move the rover in a direction, requires bearing\n\"stash\" - Stashes item at current location in rover inventory\n\"repair\" - Repairs the rover using an inventory object"
}, },
"bearing": { "bearing": {
"type": "string", "type": "string",
@ -261,6 +261,11 @@
"type": "string", "type": "string",
"format": "byte", "format": "byte",
"title": "A 1D array representing range*2 + 1 squared set of tiles, origin bottom left and in row-\u003ecolumn order" "title": "A 1D array representing range*2 + 1 squared set of tiles, origin bottom left and in row-\u003ecolumn order"
},
"objects": {
"type": "string",
"format": "byte",
"title": "A similar array to the tile array, but containing objects"
} }
} }
}, },

View file

@ -98,6 +98,9 @@ message RadarResponse {
// A 1D array representing range*2 + 1 squared set of tiles, origin bottom left and in row->column order // A 1D array representing range*2 + 1 squared set of tiles, origin bottom left and in row->column order
bytes tiles = 2; bytes tiles = 2;
// A similar array to the tile array, but containing objects
bytes objects = 3;
} }
// Empty placeholder // Empty placeholder