diff --git a/connection.go b/connection.go index 13e3592..c2b148a 100644 --- a/connection.go +++ b/connection.go @@ -84,10 +84,19 @@ func (c *Connection) Tick(frame int64) { func (c *Connection) RunCommand(name string, args ...string) { defer func() { if r := recover(); r != nil { - c.Printf("shit is *really* fucked up.") + c.Printf("shit is *really* fucked up.\n") log_error("recovered: %v", r) } }() + switch name { + case "commands": + commands := c.Commands() + for _, command := range commands { + c.Printf("%s\n", command.name) + } + return + } + cmd := c.GetCommand(name) if cmd == nil { c.Printf("No such command: %v\n", name) diff --git a/idle.go b/idle.go index c55802f..61caa4b 100644 --- a/idle.go +++ b/idle.go @@ -2,22 +2,41 @@ package main import ( "fmt" + "time" ) -var idleCommands = CommandSet{ - balCommand, - commandsCommand, - helpCommand, - playersCommand, -} - type IdleState struct { CommandSuite *System } func Idle(sys *System) ConnectionState { - return &IdleState{idleCommands, sys} + i := &IdleState{System: sys} + i.CommandSuite = CommandSet{ + balCommand, + commandsCommand, + helpCommand, + playersCommand, + Command{ + name: "goto", + help: "travel between star systems", + arity: 1, + handler: i.travelTo, + }, + Command{ + name: "nearby", + help: "list nearby star systems", + arity: 0, + handler: i.nearby, + }, + Command{ + name: "bomb", + help: "bomb another star system", + arity: 1, + handler: i.bomb, + }, + } + return i } func (i *IdleState) String() string { @@ -45,35 +64,40 @@ func (i *IdleState) travelTo(c *Connection, args ...string) { c.SetState(NewTravel(c, i.System, dest)) } -func (i *IdleState) GetCommand(name string) *Command { - return idleCommands.GetCommand(name) +func (i *IdleState) nearby(c *Connection, args ...string) { + neighbors, err := i.Nearby(25) + if err != nil { + log_error("unable to get neighbors: %v", err) + return + } + c.Printf("--------------------------------------------------------------------------------\n") + c.Printf("%-4s %-20s %s\n", "id", "name", "distance") + c.Printf("--------------------------------------------------------------------------------\n") + for _, neighbor := range neighbors { + other := index[neighbor.id] + c.Printf("%-4d %-20s %v\n", other.id, other.name, neighbor.distance) + } + c.Printf("--------------------------------------------------------------------------------\n") } -// func (i *IdleState) RunCommand(c *Connection, name string, args ...string) ConnectionState { -// switch name { -// case "goto": -// dest, err := GetSystem(args[0]) -// if err != nil { -// c.Printf("%v\n", err) -// break -// } -// return NewTravel(c, i.System, dest) -// case "nearby": -// neighbors, err := i.Nearby(25) -// if err != nil { -// log_error("unable to get neighbors: %v", err) -// break -// } -// c.Printf("--------------------------------------------------------------------------------\n") -// c.Printf("%-4s %-20s %s\n", "id", "name", "distance") -// c.Printf("--------------------------------------------------------------------------------\n") -// for _, neighbor := range neighbors { -// other := index[neighbor.id] -// c.Printf("%-4d %-20s %v\n", other.id, other.name, neighbor.distance) -// } -// c.Printf("--------------------------------------------------------------------------------\n") -// default: -// c.Printf("No such command: %v\n", name) -// } -// return i -// } +func (i *IdleState) bomb(c *Connection, args ...string) { + if c.bombs <= 0 { + c.Printf("Cannot send bomb: no bombs left! Build more bombs!\n") + return + } + if time.Since(c.lastBomb) < 5*time.Second { + c.Printf("Cannot send bomb: bombs are reloading\n") + return + } + + target, err := GetSystem(args[0]) + if err != nil { + c.Printf("Cannot send bomb: %v\n", err) + return + } + + c.bombs -= 1 + c.lastBomb = time.Now() + bomb := NewBomb(c, i.System, target) + currentGame.Register(bomb) +} diff --git a/main.go b/main.go index d5eb7cc..72b720c 100644 --- a/main.go +++ b/main.go @@ -65,6 +65,10 @@ func durToFrames(dur time.Duration) int64 { return int64(dur / options.frameLength) } +func framesToDur(frames int64) time.Duration { + return options.frameLength * time.Duration(frames) +} + func main() { flag.Parse() dbconnect() diff --git a/travel.go b/travel.go index 47325e6..b91ebe8 100644 --- a/travel.go +++ b/travel.go @@ -2,26 +2,52 @@ package main import ( "fmt" + "time" ) type TravelState struct { CommandSuite start *System dest *System - travelled float64 - dist float64 + travelled float64 // distance traveled so far in parsecs + dist float64 // distance between start and end in parsecs } func NewTravel(c *Connection, start, dest *System) ConnectionState { - return &TravelState{ + t := &TravelState{ start: start, dest: dest, dist: start.DistanceTo(dest), } + t.CommandSuite = CommandSet{ + helpCommand, + playersCommand, + balCommand, + Command{ + name: "progress", + help: "displays how far you are along your travel", + arity: 0, + handler: t.progress, + }, + Command{ + name: "eta", + help: "displays estimated time of arrival", + arity: 0, + handler: func(c *Connection, args ...string) { + c.Printf("Remaining: %v\n", t.remaining()) + c.Printf("Current time: %v\n", time.Now()) + c.Printf("ETA: %v\n", t.eta()) + }, + }, + } + return t } func (t *TravelState) Enter(c *Connection) { c.Printf("Leaving %v, bound for %v.\n", t.start, t.dest) + c.Printf("Trip duration: %v\n", t.tripTime()) + c.Printf("Current time: %v\n", time.Now()) + c.Printf("ETA: %v\n", t.eta()) } func (t *TravelState) Tick(c *Connection, frame int64) ConnectionState { @@ -39,3 +65,23 @@ func (t *TravelState) Exit(c *Connection) { func (t *TravelState) String() string { return fmt.Sprintf("Traveling from %v to %v", t.start, t.dest) } + +func (t *TravelState) progress(c *Connection, args ...string) { + c.Printf("%v\n", t.travelled/t.dist) +} + +func (t *TravelState) remaining() time.Duration { + remaining := t.dist - t.travelled + frames := remaining / (options.playerSpeed * options.lightSpeed) + return framesToDur(int64(frames)) +} + +func (t *TravelState) eta() time.Time { + // distance remaining in parsecs + return time.Now().Add(t.remaining()) +} + +func (t *TravelState) tripTime() time.Duration { + frames := t.dist / (options.playerSpeed * options.lightSpeed) + return framesToDur(int64(frames)) +}