server/game.go

146 lines
3.2 KiB
Go
Raw Normal View History

2013-08-19 20:43:26 -07:00
package main
import (
2013-09-03 23:26:40 -07:00
"bitbucket.org/hackerbots/bot"
2013-08-19 20:43:26 -07:00
"log"
"sort"
"time"
)
type game struct {
2013-09-01 23:00:09 -07:00
id string
2013-09-01 22:04:34 -07:00
players map[*player]bool
2013-09-03 23:26:40 -07:00
projectiles map[*bot.Projectile]bool
splosions map[*bot.Splosion]bool
2013-09-01 22:04:34 -07:00
register chan *player
unregister chan *player
turn int
width, height float64
spectators map[*Spectator]bool
sregister chan *Spectator
sunregister chan *Spectator
kill chan bool
2013-08-19 20:43:26 -07:00
}
2013-09-01 23:00:09 -07:00
func NewGame(id string, width, height float64) *game {
2013-09-04 00:06:39 -07:00
g := &game{
2013-09-01 23:00:09 -07:00
id: id,
2013-08-25 23:10:02 -07:00
register: make(chan *player),
unregister: make(chan *player),
2013-09-03 23:26:40 -07:00
projectiles: make(map[*bot.Projectile]bool),
splosions: make(map[*bot.Splosion]bool),
2013-08-25 23:10:02 -07:00
players: make(map[*player]bool),
turn: 0,
2013-09-01 22:04:34 -07:00
width: width,
height: height,
2013-08-25 23:10:02 -07:00
spectators: make(map[*Spectator]bool),
sregister: make(chan *Spectator),
sunregister: make(chan *Spectator),
kill: make(chan bool, 128),
2013-08-25 23:10:02 -07:00
}
2013-09-04 00:06:39 -07:00
return g
}
func (g *game) run() {
started := false
2013-08-19 20:43:26 -07:00
for {
select {
2013-08-28 22:16:55 -07:00
case <-g.kill:
log.Printf("game %s: received kill signal, dying gracefully", g.id)
gameLock.Lock()
delete(games, g.id)
gameLock.Unlock()
2013-08-28 22:16:55 -07:00
return
2013-08-19 20:43:26 -07:00
case p := <-g.register:
g.players[p] = true
started = true
2013-08-19 20:43:26 -07:00
case p := <-g.unregister:
delete(g.players, p)
close(p.send)
2013-08-19 22:23:35 -07:00
case s := <-g.sregister:
g.spectators[s] = true
case s := <-g.sunregister:
delete(g.spectators, s)
close(s.send)
2013-08-19 20:43:26 -07:00
case <-time.Tick(time.Duration(*tick) * time.Millisecond):
if started && len(g.players) == 0 {
g.kill <- true
}
2013-08-19 20:43:26 -07:00
g.turn++
t0 := time.Now()
2013-09-03 23:26:40 -07:00
2013-08-19 20:43:26 -07:00
if *verbose {
log.Printf("\033[2JTurn: %v", g.turn)
log.Printf("Players: %v", len(g.players))
log.Printf("Projectiles: %v", len(g.projectiles))
log.Printf("Explosions: %v", len(g.splosions))
}
2013-09-03 23:26:40 -07:00
2013-09-04 00:07:47 -07:00
// TODO: making one of these every iteration seems wasteful
2013-09-03 23:26:40 -07:00
payload := bot.NewBoardstate(g.turn)
2013-08-19 20:43:26 -07:00
robots_remaining := 0
for p := range g.players {
if p.Robot.Health > 0 {
robots_remaining++
2013-09-04 00:07:47 -07:00
p.scan(g.players)
2013-08-19 20:43:26 -07:00
p.nudge()
2013-09-03 23:26:40 -07:00
// XXX: change to pointer, check for pointer as (0, 0) is valid target
2013-09-04 00:05:38 -07:00
if p.Robot.FireAt != nil {
proj := p.fire(g.projectiles)
2013-09-03 23:26:40 -07:00
if proj != nil {
g.projectiles[proj] = true
}
2013-08-19 20:43:26 -07:00
}
}
payload.Robots = append(payload.Robots, p.Robot)
}
2013-09-03 23:26:40 -07:00
sort.Sort(bot.RobotSorter{payload.Robots})
2013-08-19 20:43:26 -07:00
for p := range g.projectiles {
2013-09-03 23:26:40 -07:00
// XXX: p.nudge()
2013-08-19 20:43:26 -07:00
payload.Projectiles = append(payload.Projectiles, *p)
}
for s := range g.splosions {
2013-09-03 23:26:40 -07:00
// XXX: s.tick()
2013-08-19 20:43:26 -07:00
payload.Splosions = append(payload.Splosions, *s)
}
if robots_remaining <= 1 && len(g.players) > 1 {
for p := range g.players {
if p.Robot.Health > 0 {
log.Printf("Robot %v Wins", p.Robot.Id)
2013-08-28 23:46:12 -07:00
log.Printf("game over: %+v", g)
return
2013-08-19 20:43:26 -07:00
}
p.reset()
}
payload.Reset = true
} else {
payload.Reset = false
}
t1 := time.Now()
if *verbose {
log.Printf("Turn Processes %v\n", t1.Sub(t0))
}
for p := range g.players {
p.send <- payload
}
2013-08-19 22:23:35 -07:00
for s := range g.spectators {
s.send <- payload
}
2013-08-19 20:43:26 -07:00
t1 = time.Now()
if *verbose {
log.Printf("Sent Payload %v\n", t1.Sub(t0))
}
}
}
}