Split Atlas chunks into tiles and objects
This commit is contained in:
parent
74dcae6542
commit
062f9cfec8
11 changed files with 284 additions and 169 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"`
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue