scan and broadcast both work without global index

master
Jordan Orelli 5 years ago
parent dbb2c86f5a
commit ce94d3cdd2

@ -33,10 +33,10 @@ func (b *Bomb) Dead() bool {
return b.done return b.done
} }
func (b *Bomb) Tick(frame int64) { func (b *Bomb) Tick(game *Game) {
b.fti -= 1 b.fti -= 1
if b.fti <= 0 { if b.fti <= 0 {
b.target.Bombed(b.profile, frame) b.target.Bombed(b.profile, game.frame)
b.done = true b.done = true
log_info("bomb went off on %v", b.target) log_info("bomb went off on %v", b.target)
} }

@ -9,8 +9,8 @@ type broadcast struct {
start time.Time start time.Time
origin *System origin *System
dist float64 dist float64
nextHitIndex int
message string message string
neighborhood Neighborhood
} }
func NewBroadcast(from *System, template string, args ...interface{}) *broadcast { func NewBroadcast(from *System, template string, args ...interface{}) *broadcast {
@ -21,20 +21,27 @@ func NewBroadcast(from *System, template string, args ...interface{}) *broadcast
} }
} }
func (b *broadcast) Tick(frame int64) { func (b *broadcast) Tick(game *Game) {
if b.neighborhood == nil {
log_info("setting up neighborhood for broadcast: %s", b.message)
b.neighborhood = game.galaxy.Neighborhood(b.origin)
log_info("nearest neighbor: %v", b.neighborhood[0])
}
b.dist += options.lightSpeed b.dist += options.lightSpeed
for ; b.nextHitIndex < len(b.origin.Distances()); b.nextHitIndex += 1 { for len(b.neighborhood) > 0 && b.neighborhood[0].distance <= b.dist {
candidate := b.origin.Distances()[b.nextHitIndex] s := game.galaxy.GetSystemByID(b.neighborhood[0].id)
if b.dist < candidate.dist { log_info("broadcast %s has reached %s from %s", b.message, s, b.origin)
break s.NotifyInhabitants("message received from system %v:\n\t%s\n", b.origin, b.message)
if len(b.neighborhood) > 1 {
b.neighborhood = b.neighborhood[1:]
} else {
b.neighborhood = nil
} }
candidate.s.NotifyInhabitants("message received from system %v:\n\t%s\n", b.origin, b.message)
} }
} }
func (b *broadcast) Dead() bool { func (b *broadcast) Dead() bool { return b.neighborhood == nil }
return b.dist > b.origin.Distances()[len(b.origin.Distances())-1].dist
}
func (b *broadcast) String() string { func (b *broadcast) String() string {
return fmt.Sprintf("[broadcast origin: %v message: %s]", b.origin, b.message) return fmt.Sprintf("[broadcast origin: %v message: %s]", b.origin, b.message)

@ -212,15 +212,15 @@ func BroadcastCommand(sys *System) Command {
func NearbyCommand(sys *System) Command { func NearbyCommand(sys *System) Command {
handler := func(c *Connection, args ...string) { handler := func(c *Connection, args ...string) {
neighbors := c.game.galaxy.Neighborhood(sys) neighbors := c.game.galaxy.Neighborhood(sys)
c.Printf("--------------------------------------------------------------------------------\n") c.Line()
c.Printf("%-4s %-20s %-12s %s\n", "id", "name", "distance", "trip time") c.Printf("%-4s %-20s %-12s %s\n", "id", "name", "distance", "trip time")
c.Printf("--------------------------------------------------------------------------------\n") c.Line()
for _, neighbor := range neighbors[:25] { for _, neighbor := range neighbors[:25] {
other := index[neighbor.id] other := c.game.galaxy.GetSystemByID(neighbor.id)
dur := NewTravel(c, sys, other).(*TravelState).tripTime() dur := NewTravel(c, sys, other).(*TravelState).tripTime()
c.Printf("%-4d %-20s %-12.6v %v\n", other.id, other.name, neighbor.distance, dur) c.Printf("%-4d %-20s %-12.6vpc %v\n", other.id, other.name, neighbor.distance, dur)
} }
c.Printf("--------------------------------------------------------------------------------\n") c.Line()
} }
return Command{ return Command{
name: "nearby", name: "nearby",

@ -40,14 +40,14 @@ func (c *Connection) Dead() bool {
return false return false
} }
func (c *Connection) Tick(frame int64) { func (c *Connection) Tick(game *Game) {
if c.ConnectionState == nil { if c.ConnectionState == nil {
log_error("connected client has nil state.") log_error("connected client has nil state.")
c.Printf("somehow you have a nil state. I don't know what to do so I'm going to kick you off.") c.Printf("somehow you have a nil state. I don't know what to do so I'm going to kick you off.")
c.Close() c.Close()
return return
} }
c.SetState(c.ConnectionState.Tick(c, frame)) c.SetState(c.ConnectionState.Tick(c, game.frame))
} }
func (c *Connection) RunCommand(name string, args ...string) { func (c *Connection) RunCommand(name string, args ...string) {
@ -221,11 +221,3 @@ func (c *Connection) Win(method string) {
func (c *Connection) Die(frame int64) { func (c *Connection) Die(frame int64) {
c.SetState(NewDeadState(frame)) c.SetState(NewDeadState(frame))
} }
func SpawnRandomly() ConnectionState {
sys, err := randomSystem()
if err != nil {
return NewErrorState(fmt.Errorf("unable to create idle state: %v", err))
}
return Idle(sys)
}

@ -17,7 +17,7 @@ func (d *DeadState) Enter(c *Connection) {
func (d *DeadState) Tick(c *Connection, frame int64) ConnectionState { func (d *DeadState) Tick(c *Connection, frame int64) ConnectionState {
if frame-d.start > options.respawnFrames { if frame-d.start > options.respawnFrames {
return SpawnRandomly() return c.game.SpawnPlayer()
} }
return d return d
} }

@ -70,8 +70,16 @@ func (g *Galaxy) SystemID(name string) int { return g.names[name] }
func (g *Galaxy) Neighborhood(sys *System) Neighborhood { func (g *Galaxy) Neighborhood(sys *System) Neighborhood {
neighbors := make(Neighborhood, 0, len(g.systems)) neighbors := make(Neighborhood, 0, len(g.systems))
for id, sys2 := range g.systems { for id, sys2 := range g.systems {
if id == sys.id {
continue
}
neighbors = append(neighbors, Neighbor{id: id, distance: sys.DistanceTo(sys2)}) neighbors = append(neighbors, Neighbor{id: id, distance: sys.DistanceTo(sys2)})
} }
sort.Sort(neighbors) sort.Sort(neighbors)
return neighbors return neighbors
} }
func (g *Galaxy) randomSystem() *System {
id := rand.Intn(len(g.systems))
return g.GetSystemByID(id)
}

@ -136,7 +136,7 @@ func (g *Game) Register(elem GameElement) {
func (g *Game) tick() { func (g *Game) tick() {
g.frame += 1 g.frame += 1
for elem := range g.elems { for elem := range g.elems {
elem.Tick(g.frame) elem.Tick(g)
} }
for elem := range g.elems { for elem := range g.elems {
if elem.Dead() { if elem.Dead() {
@ -146,7 +146,11 @@ func (g *Game) tick() {
} }
} }
func (g *Game) SpawnPlayer() ConnectionState {
return Idle(g.galaxy.randomSystem())
}
type GameElement interface { type GameElement interface {
Tick(frame int64) Tick(*Game)
Dead() bool Dead() bool
} }

@ -104,7 +104,7 @@ func (i *IdleState) scan(c *Connection, args ...string) {
return return
} }
c.Printf("Scanning the galaxy for signs of life...\n") c.Printf("Scanning the galaxy for signs of life...\n")
c.game.Register(NewScan(i.System)) c.game.Register(NewScan(i.System, c.game.galaxy.Neighborhood(i.System)))
} }
// "make" is already a keyword // "make" is already a keyword

@ -114,7 +114,7 @@ var newGameCommand = Command{
c.Printf("Now playing in game: %s\n\n", game.id) c.Printf("Now playing in game: %s\n\n", game.id)
c.Line() c.Line()
c.game.Join(c) c.game.Join(c)
c.SetState(SpawnRandomly()) c.SetState(game.SpawnPlayer())
}, },
debug: false, debug: false,
} }
@ -135,9 +135,10 @@ Usage: join [game-code]`, " \n\t"))
return return
} }
id := args[0] id := args[0]
c.game = gm.Get(id) game := gm.Get(id)
c.game = game
log_info("%s Joining game: %s", c.profile.name, c.game.id) log_info("%s Joining game: %s", c.profile.name, c.game.id)
c.SetState(SpawnRandomly()) c.SetState(game.SpawnPlayer())
c.game.Join(c) c.game.Join(c)
}, },
debug: false, debug: false,

@ -18,7 +18,7 @@ var options struct {
frameLength time.Duration frameLength time.Duration
colonyCost int colonyCost int
frameRate int frameRate int
lightSpeed float64 lightSpeed float64 // the distance that light travels in one tick
makeBombTime time.Duration makeBombTime time.Duration
makeColonyTime time.Duration makeColonyTime time.Duration
makeShieldTime time.Duration makeShieldTime time.Duration

@ -12,6 +12,7 @@ type scan struct {
nextHitIndex int nextHitIndex int
nextEchoIndex int nextEchoIndex int
results []scanResult results []scanResult
neighborhood Neighborhood
} }
type scanResult struct { type scanResult struct {
@ -38,17 +39,18 @@ func (r *scanResult) playerNames() []string {
return names return names
} }
func NewScan(origin *System) *scan { func NewScan(origin *System, n Neighborhood) *scan {
return &scan{ return &scan{
origin: origin, origin: origin,
start: time.Now(), start: time.Now(),
results: make([]scanResult, 0, len(origin.Distances())), results: make([]scanResult, 0, len(origin.Distances())),
neighborhood: n,
} }
} }
func (s *scan) Tick(frame int64) { func (s *scan) Tick(game *Game) {
s.dist += options.lightSpeed s.dist += options.lightSpeed
s.hits() s.hits(game)
s.echos() s.echos()
} }
@ -60,14 +62,17 @@ func (s *scan) String() string {
return fmt.Sprintf("[scan origin: %s start_time: %v]", s.origin.name, s.start) return fmt.Sprintf("[scan origin: %s start_time: %v]", s.origin.name, s.start)
} }
func (s *scan) hits() { func (s *scan) hits(game *Game) {
for ; s.nextHitIndex < len(s.origin.Distances()); s.nextHitIndex += 1 { for len(s.neighborhood) > 0 && s.neighborhood[0].distance <= s.dist {
candidate := s.origin.Distances()[s.nextHitIndex] sys := game.galaxy.GetSystemByID(s.neighborhood[0].id)
if s.dist < candidate.dist { s.results = append(s.results, s.hitSystem(sys, s.neighborhood[0].distance))
break log_info("scan hit %v. Traveled %v in %v", sys.name, s.neighborhood[0].distance, time.Since(s.start))
if len(s.neighborhood) > 1 {
s.neighborhood = s.neighborhood[1:]
} else {
s.neighborhood = nil
} }
s.results = append(s.results, s.hitSystem(candidate.s, candidate.dist))
log_info("scan hit %v. Traveled %v in %v", candidate.s.name, candidate.dist, time.Since(s.start))
} }
} }

@ -54,7 +54,7 @@ type Shield struct {
energy float64 energy float64
} }
func (s *Shield) Tick(frame int64) { func (s *Shield) Tick() {
if s.energy < 1000 { if s.energy < 1000 {
s.energy += (1000 - s.energy) * 0.0005 s.energy += (1000 - s.energy) * 0.0005
} }

@ -25,13 +25,13 @@ type System struct {
money int64 money int64
} }
func (s *System) Tick(frame int64) { func (s *System) Tick(game *Game) {
if s.colonizedBy != nil && s.money > 0 { if s.colonizedBy != nil && s.money > 0 {
s.colonizedBy.Deposit(1) s.colonizedBy.Deposit(1)
s.money -= 1 s.money -= 1
} }
if s.Shield != nil { if s.Shield != nil {
s.Shield.Tick(frame) s.Shield.Tick()
} }
} }
@ -45,7 +45,6 @@ func (s *System) Reset() {
} }
func (s *System) Arrive(conn *Connection) { func (s *System) Arrive(conn *Connection) {
// conn.SetSystem(s)
if s.players[conn] { if s.players[conn] {
return return
} }
@ -125,11 +124,11 @@ func (s *System) Distances() []Ray {
if s.distances == nil { if s.distances == nil {
s.distances = make([]Ray, 0, 551) s.distances = make([]Ray, 0, 551)
rows, err := db.Query(` rows, err := db.Query(`
select edges.id_2, edges.distance select edges.id_2, edges.distance
from edges from edges
where edges.id_1 = ? where edges.id_1 = ?
order by distance order by distance
;`, s.id) ;`, s.id)
if err != nil { if err != nil {
log_error("unable to query for system distances: %v", err) log_error("unable to query for system distances: %v", err)
return nil return nil
@ -247,13 +246,3 @@ func indexSystems() map[int]*System {
} }
return index return index
} }
func randomSystem() (*System, error) {
n := len(index)
if n == 0 {
return nil, fmt.Errorf("no planets are known to exist")
}
pick := rand.Intn(n)
sys := index[pick]
return sys, nil
}

Loading…
Cancel
Save