From 444896f3646cf7264add6394b5fdbb801d050d12 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Tue, 11 Nov 2014 19:00:32 -0500 Subject: [PATCH] added new scan implementation --- commands.go | 3 +++ game.go | 40 ++++++++++++++++++++++++++++++++++++++++ main.go | 3 +++ scan.go | 30 ++++++++++++++++++++++++++++++ system.go | 41 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 scan.go diff --git a/commands.go b/commands.go index 86ecec3..e12987e 100644 --- a/commands.go +++ b/commands.go @@ -120,6 +120,9 @@ var scanCommand = &Command{ fmt.Fprintf(conn, "scanners are still recharging. Can scan again in %v\n", conn.NextScan()) return } + s := &scan{start: time.Now(), origin: conn.System()} + currentGame.Register(s) + conn.RecordScan() system := conn.System() log_info("scan sent from %s", system.name) diff --git a/game.go b/game.go index e88564a..60f63dc 100644 --- a/game.go +++ b/game.go @@ -12,6 +12,8 @@ type Game struct { winner string winMethod string connections map[*Connection]bool + frame int64 + elems map[GameElement]bool } func gamesTable() { @@ -32,6 +34,7 @@ func NewGame() *Game { id: NewId(), start: time.Now(), connections: make(map[*Connection]bool, 32), + elems: make(map[GameElement]bool, 32), } if err := game.Create(); err != nil { log_error("unable to create game: %v", err) @@ -96,3 +99,40 @@ func (g *Game) Reset() { *g = *fresh g.connections = connections } + +func (g *Game) Run() { + ticker := time.Tick(time.Second / time.Duration(frameRate)) + for { + select { + case <-ticker: + g.tick() + } + } +} + +func (g *Game) Register(elem GameElement) { + g.elems[elem] = true +} + +func (g *Game) tick() { + g.frame += 1 + for elem := range g.elems { + if elem.Dead() { + delete(g.elems, elem) + } + } + for elem := range g.elems { + elem.Tick(g.frame) + } +} + +type GameElement interface { + Tick(frame int64) + Dead() Mortality +} + +type Mortality bool + +func (m Mortality) Dead() Mortality { + return m +} diff --git a/main.go b/main.go index b3fcd05..e9e544d 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,8 @@ var ( info_log *log.Logger error_log *log.Logger currentGame *Game + frameRate = 100 // frames/second + lightSpeed = 0.01 // parsecs/frame ) func log_error(template string, args ...interface{}) { @@ -90,6 +92,7 @@ func main() { go RunQueue() currentGame = NewGame() + go currentGame.Run() for { conn, err := listener.Accept() diff --git a/scan.go b/scan.go new file mode 100644 index 0000000..e5efd60 --- /dev/null +++ b/scan.go @@ -0,0 +1,30 @@ +package main + +import ( + "time" +) + +type scan struct { + Mortality + start time.Time + origin *System + dist float64 + nextHitIndex int +} + +func (s *scan) Tick(frame int64) { + s.dist += lightSpeed + for { + candidate := s.origin.Distances()[s.nextHitIndex] + if s.dist < candidate.dist { + break + } + log_info("scan hit %v. Traveled %v in %v", candidate.s.name, candidate.dist, time.Since(s.start)) + s.nextHitIndex += 1 + if s.nextHitIndex >= len(s.origin.Distances()) { + s.Mortality = true + log_info("scan complete") + break + } + } +} diff --git a/system.go b/system.go index 1f1c7b1..a217e56 100644 --- a/system.go +++ b/system.go @@ -22,6 +22,7 @@ type System struct { players map[*Connection]bool miningRate float64 colonizedBy *Connection + distances []Ray } func (s *System) Arrive(conn *Connection) { @@ -87,6 +88,42 @@ func (s *System) TravelTimeTo(other *System) time.Duration { return time.Duration(int64(s.DistanceTo(other) * 125000000)) } +type Ray struct { + s *System + dist float64 // distance in parsecs +} + +func (s *System) Distances() []Ray { + if s.distances == nil { + s.distances = make([]Ray, 0, 551) + rows, err := db.Query(` + select edges.id_2, edges.distance + from edges + where edges.id_1 = ? + order by distance + ;`, s.id) + if err != nil { + log_error("unable to query for system distances: %v", err) + return nil + } + for rows.Next() { + var ( + r Ray + id int + dist float64 + ) + if err := rows.Scan(&id, &dist); err != nil { + log_error("unable to unpack Ray from sql result: %v", err) + continue + } + r.s = index[id] + r.dist = dist + s.distances = append(s.distances, r) + } + } + return s.distances +} + func (s *System) Bombed(bomber *Connection) { s.EachConn(func(conn *Connection) { conn.Die() @@ -230,7 +267,7 @@ func scanSystem(id int, reply int) { system := index[id] source := index[reply] delay := system.LightTimeTo(source) - log_info("scan hit %s from %s after traveling for %v", system.name, source.name, delay) + // log_info("scan hit %s from %s after traveling for %v", system.name, source.name, delay) system.EachConn(func(conn *Connection) { fmt.Fprintf(conn, "scan detected from %s\n", source.name) @@ -248,7 +285,7 @@ func deliverReply(id int, echo int, results *scanResults) { system := index[id] source := index[echo] delay := system.LightTimeTo(source) - log_info("echo received at %s reflected from %s after traveling for %v", system.name, source.name, delay) + // log_info("echo received at %s reflected from %s after traveling for %v", system.name, source.name, delay) system.EachConn(func(conn *Connection) { if results.negative() { return