145 lines
3.0 KiB
Go
145 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bitbucket.org/hackerbots/bot"
|
|
"log"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
type game struct {
|
|
id string
|
|
players map[*player]bool
|
|
projectiles map[*bot.Projectile]bool
|
|
splosions map[*bot.Splosion]bool
|
|
register chan *player
|
|
unregister chan *player
|
|
robot_id chan int
|
|
turn int
|
|
width, height float64
|
|
spectators map[*Spectator]bool
|
|
sregister chan *Spectator
|
|
sunregister chan *Spectator
|
|
kill chan bool
|
|
}
|
|
|
|
func NewGame(id string, width, height float64) *game {
|
|
g := &game{
|
|
id: id,
|
|
register: make(chan *player),
|
|
unregister: make(chan *player),
|
|
projectiles: make(map[*bot.Projectile]bool),
|
|
splosions: make(map[*bot.Splosion]bool),
|
|
players: make(map[*player]bool),
|
|
turn: 0,
|
|
width: width,
|
|
height: height,
|
|
spectators: make(map[*Spectator]bool),
|
|
sregister: make(chan *Spectator),
|
|
sunregister: make(chan *Spectator),
|
|
kill: make(chan bool),
|
|
}
|
|
|
|
g.robot_id = make(chan int)
|
|
go func() {
|
|
for i := 0; ; i++ {
|
|
g.robot_id <- i
|
|
}
|
|
}()
|
|
|
|
return g
|
|
|
|
}
|
|
|
|
func (g *game) run() {
|
|
for {
|
|
select {
|
|
case <-g.kill:
|
|
return
|
|
case p := <-g.register:
|
|
g.players[p] = true
|
|
case p := <-g.unregister:
|
|
delete(g.players, p)
|
|
close(p.send)
|
|
case s := <-g.sregister:
|
|
g.spectators[s] = true
|
|
case s := <-g.sunregister:
|
|
delete(g.spectators, s)
|
|
close(s.send)
|
|
case <-time.Tick(time.Duration(*tick) * time.Millisecond):
|
|
g.turn++
|
|
t0 := time.Now()
|
|
|
|
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))
|
|
}
|
|
|
|
payload := bot.NewBoardstate(g.turn)
|
|
|
|
robots_remaining := 0
|
|
|
|
for p := range g.players {
|
|
if p.Robot.Health > 0 {
|
|
robots_remaining++
|
|
p.scan()
|
|
p.nudge()
|
|
// XXX: change to pointer, check for pointer as (0, 0) is valid target
|
|
if p.Robot.FireAt != nil {
|
|
proj := p.fire(g.projectiles)
|
|
if proj != nil {
|
|
g.projectiles[proj] = true
|
|
}
|
|
}
|
|
}
|
|
payload.Robots = append(payload.Robots, p.Robot)
|
|
}
|
|
sort.Sort(bot.RobotSorter{payload.Robots})
|
|
|
|
for p := range g.projectiles {
|
|
// XXX: p.nudge()
|
|
payload.Projectiles = append(payload.Projectiles, *p)
|
|
}
|
|
|
|
for s := range g.splosions {
|
|
// XXX: s.tick()
|
|
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)
|
|
log.Printf("game over: %+v", g)
|
|
return
|
|
}
|
|
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
|
|
}
|
|
for s := range g.spectators {
|
|
s.send <- payload
|
|
}
|
|
|
|
t1 = time.Now()
|
|
if *verbose {
|
|
log.Printf("Sent Payload %v\n", t1.Sub(t0))
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|