Add "broadcast" command
This will send a readable ascii triplet to all rovers in range
This commit is contained in:
parent
30ca488890
commit
d4d82c38e0
4 changed files with 120 additions and 2 deletions
|
@ -12,6 +12,9 @@ const (
|
||||||
|
|
||||||
// CommandRecharge Will use one tick to charge the rover
|
// CommandRecharge Will use one tick to charge the rover
|
||||||
CommandRecharge = "recharge"
|
CommandRecharge = "recharge"
|
||||||
|
|
||||||
|
// CommandBroadcast will broadcast a message to nearby rovers within range
|
||||||
|
CommandBroadcast = "broadcast"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Command represends a single command to execute
|
// Command represends a single command to execute
|
||||||
|
@ -20,6 +23,9 @@ type Command struct {
|
||||||
|
|
||||||
// Used in the move command
|
// Used in the move command
|
||||||
Bearing string `json:"bearing,omitempty"`
|
Bearing string `json:"bearing,omitempty"`
|
||||||
|
|
||||||
|
// Used in the broadcast command
|
||||||
|
Message []byte `json:"message,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandStream is a list of commands to execute in order
|
// CommandStream is a list of commands to execute in order
|
||||||
|
|
|
@ -168,6 +168,40 @@ func (w *World) RoverRecharge(rover string) (int, error) {
|
||||||
return i.Charge, nil
|
return i.Charge, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RoverBroadcast broadcasts a message to nearby rovers
|
||||||
|
func (w *World) RoverBroadcast(rover string, message []byte) (err error) {
|
||||||
|
w.worldMutex.Lock()
|
||||||
|
defer w.worldMutex.Unlock()
|
||||||
|
|
||||||
|
i, ok := w.Rovers[rover]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Failed to find rover with name: %s", rover)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use up a charge as needed, if available
|
||||||
|
if i.Charge == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i.Charge--
|
||||||
|
|
||||||
|
// Check all rovers
|
||||||
|
for r, rover := range w.Rovers {
|
||||||
|
if rover.Name == i.Name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this rover is within range
|
||||||
|
if i.Pos.Distance(rover.Pos) < float64(i.Range) {
|
||||||
|
rover.AddLogEntryf("recieved %s from %s", string(message), i.Name)
|
||||||
|
w.Rovers[r] = rover
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i.AddLogEntryf("broadcasted %s", string(message))
|
||||||
|
w.Rovers[rover] = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// DestroyRover Removes an rover from the game
|
// DestroyRover Removes an rover from the game
|
||||||
func (w *World) DestroyRover(rover string) error {
|
func (w *World) DestroyRover(rover string) error {
|
||||||
w.worldMutex.Lock()
|
w.worldMutex.Lock()
|
||||||
|
@ -399,6 +433,15 @@ func (w *World) Enqueue(rover string, commands ...Command) error {
|
||||||
if _, err := bearing.FromString(c.Bearing); err != nil {
|
if _, err := bearing.FromString(c.Bearing); err != nil {
|
||||||
return fmt.Errorf("unknown bearing: %s", c.Bearing)
|
return fmt.Errorf("unknown bearing: %s", c.Bearing)
|
||||||
}
|
}
|
||||||
|
case CommandBroadcast:
|
||||||
|
if len(c.Message) > 3 {
|
||||||
|
return fmt.Errorf("too many characters in message (limit 3): %d", len(c.Message))
|
||||||
|
}
|
||||||
|
for _, b := range c.Message {
|
||||||
|
if b < 37 || b > 126 {
|
||||||
|
return fmt.Errorf("invalid message character: %c", b)
|
||||||
|
}
|
||||||
|
}
|
||||||
case CommandStash:
|
case CommandStash:
|
||||||
case CommandRepair:
|
case CommandRepair:
|
||||||
case CommandRecharge:
|
case CommandRecharge:
|
||||||
|
@ -494,6 +537,10 @@ func (w *World) ExecuteCommand(c *Command, rover string) (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case CommandBroadcast:
|
||||||
|
if err := w.RoverBroadcast(rover, c.Message); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown command: %s", c.Command)
|
return fmt.Errorf("unknown command: %s", c.Command)
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,3 +365,63 @@ func TestWorld_Daytime(t *testing.T) {
|
||||||
world.ExecuteCommandQueues()
|
world.ExecuteCommandQueues()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWorld_Broadcast(t *testing.T) {
|
||||||
|
world := NewWorld(8)
|
||||||
|
|
||||||
|
a, err := world.SpawnRover()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
b, err := world.SpawnRover()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Warp rovers near to eachother
|
||||||
|
assert.NoError(t, world.WarpRover(a, vector.Vector{X: 0, Y: 0}))
|
||||||
|
assert.NoError(t, world.WarpRover(b, vector.Vector{X: 1, Y: 0}))
|
||||||
|
|
||||||
|
// Broadcast from a
|
||||||
|
assert.NoError(t, world.RoverBroadcast(a, []byte{'A', 'B', 'C'}))
|
||||||
|
|
||||||
|
// Check if b heard it
|
||||||
|
ra, err := world.GetRover(a)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, ra.MaximumCharge-1, ra.Charge, "A should have used a charge to broadcast")
|
||||||
|
assert.Contains(t, ra.Logs[len(ra.Logs)-1].Text, "ABC", "Rover B should have heard the broadcast")
|
||||||
|
|
||||||
|
// Check if a logged it
|
||||||
|
rb, err := world.GetRover(b)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
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
|
||||||
|
assert.NoError(t, world.WarpRover(b, vector.Vector{X: ra.Range, Y: 0}))
|
||||||
|
|
||||||
|
// Broadcast from a again
|
||||||
|
assert.NoError(t, world.RoverBroadcast(a, []byte{'X', 'Y', 'Z'}))
|
||||||
|
|
||||||
|
// Check if b heard it
|
||||||
|
ra, err = world.GetRover(b)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotContains(t, ra.Logs[len(ra.Logs)-1].Text, "XYZ", "Rover B should not have heard the broadcast")
|
||||||
|
|
||||||
|
// Check if a logged it
|
||||||
|
rb, err = world.GetRover(a)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
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
|
||||||
|
assert.NoError(t, world.WarpRover(b, vector.Vector{X: ra.Range + 1, Y: 0}))
|
||||||
|
|
||||||
|
// Broadcast from a again
|
||||||
|
assert.NoError(t, world.RoverBroadcast(a, []byte{'H', 'J', 'K'}))
|
||||||
|
|
||||||
|
// Check if b heard it
|
||||||
|
ra, err = world.GetRover(b)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotContains(t, ra.Logs[len(ra.Logs)-1].Text, "HJK", "Rover B should have heard the broadcast")
|
||||||
|
|
||||||
|
// Check if a logged it
|
||||||
|
rb, err = world.GetRover(a)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Contains(t, rb.Logs[len(rb.Logs)-1].Text, "HJK", "Rover A should have logged it's broadcast")
|
||||||
|
}
|
||||||
|
|
|
@ -66,10 +66,15 @@ message Command {
|
||||||
// "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
|
// "repair" - Repairs the rover using an inventory object
|
||||||
// "recharge" - Waits a tick to add more charge to the rover
|
// "recharge" - Waits a tick to add more charge to the rover
|
||||||
|
// "broadcast" - Broadcasts a message to nearby rovers
|
||||||
string command = 1;
|
string command = 1;
|
||||||
|
|
||||||
// The bearing, example: NE
|
// A bearing, example: NE
|
||||||
string bearing = 2;
|
string bearing = 2;
|
||||||
|
|
||||||
|
// A simple message, must be composed of printable ASCII glyphs (32-126)
|
||||||
|
// maximum of three characters
|
||||||
|
bytes message = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CommandRequest {
|
message CommandRequest {
|
||||||
|
@ -135,7 +140,7 @@ message StatusResponse {
|
||||||
// Position of the rover in world coordinates
|
// Position of the rover in world coordinates
|
||||||
Vector position = 2;
|
Vector position = 2;
|
||||||
|
|
||||||
// The range of this rover's radar
|
// The range of this rover's radar and broadcasting
|
||||||
int32 range = 3;
|
int32 range = 3;
|
||||||
|
|
||||||
// The items in the rover inventory
|
// The items in the rover inventory
|
||||||
|
|
Loading…
Add table
Reference in a new issue