client/robot.go

168 lines
3.4 KiB
Go

package main
import (
"bitbucket.org/hackerbots/vector"
"code.google.com/p/go.net/websocket"
"errors"
"fmt"
"log"
"math/rand"
)
func connect() (*websocket.Conn, error) {
origin := "http://localhost/"
url := fmt.Sprintf("ws://%s:%d/ws/", *server, *port)
return websocket.Dial(url, "", origin)
}
type robot struct {
ws *websocket.Conn
game GameParam
playerId string
}
func NewRobot(
server string,
port int,
gameName string,
hp,
speed,
acceleration,
weaponRadius,
scannerRadius,
fireRate int) (*robot, error) {
ws, err := connect()
if err != nil {
return nil, errors.New(fmt.Sprintf("connection failure: %s", err))
}
r := &robot{
ws: ws,
}
// XXX: update with missing fields
statsReq := StatsRequest{
Hp: hp,
Speed: speed,
Acceleration: acceleration,
WeaponRadius: weaponRadius,
ScannerRadius: scannerRadius,
TurnSpeed: 50,
FireRate: fireRate,
WeaponDamage: 50,
WeaponSpeed: 50,
}
err = r.negociate(statsReq, gameName)
return r, nil
}
func (r *robot) negociate(req StatsRequest, gameName string) (err error) {
log.Printf("trying to connect to game '%s'", gameName)
err = websocket.JSON.Send(r.ws, struct {
Id string `json:"id"`
}{
gameName,
})
if err != nil {
return err
}
var idreq struct {
Type string `json:"type"`
PlayerId string `json:"id"`
}
err = websocket.JSON.Receive(r.ws, &idreq)
if err != nil || idreq.Type == "failure" {
return errors.New(fmt.Sprintf("failure: %+v", idreq))
}
log.Printf("idreq: %+v", idreq)
err = websocket.JSON.Send(r.ws, struct {
Type string `json:"type"`
Name string `json:"name"`
Useragent string `json:"useragent"`
}{
Name: *botname,
Useragent: "gobot",
Type: "robot",
})
if err != nil {
return err
}
err = websocket.JSON.Receive(r.ws, &r.game)
if r.game.Type != "gameparam" {
return errors.New("didn't receive a good gameparam")
}
r.game.name = gameName
log.Printf("game parameters: %+v", r.game)
conf := ClientConfig{
ID: gameName,
Stats: map[string]StatsRequest{
*botname: req,
},
}
err = websocket.JSON.Send(r.ws, conf)
var handshake struct {
Id string `json:"id"`
Success bool `json:"success"`
Type string `json:"type"`
}
websocket.JSON.Receive(r.ws, &handshake)
if !handshake.Success {
return errors.New("failed to validate correct stats request")
}
r.playerId = handshake.Id
log.Printf("handshake: %+v", handshake)
return nil
}
func (r *robot) play() {
var err error
// TODO: var target govector.Point2d
moveto := govector.Point2d{
X: rand.Float32() * r.game.BoardSize.Width,
Y: rand.Float32() * r.game.BoardSize.Height,
}
log.Printf("moveto: %+v", moveto)
var me Robot
log.Printf("%s: starting loop", r.playerId)
for {
var boardstate Boardstate
err = websocket.JSON.Receive(r.ws, &boardstate)
if *verbose {
log.Printf("%+v", boardstate)
}
if err != nil {
log.Fatal("Connection lost")
}
me = boardstate.MyRobots[0]
if govector.Distance(me.Position, moveto) < 3.0 {
log.Printf("old: %+v: %+v", me.Position, moveto)
moveto = govector.Point2d{
X: rand.Float32() * r.game.BoardSize.Width,
Y: rand.Float32() * r.game.BoardSize.Height,
}
log.Printf("new: %+v: %+v", me.Position, moveto)
}
// TODO: send instructions
instruction := map[string]Instruction{
me.Id: {
MoveTo: &moveto,
FireAt: &moveto,
},
}
err = websocket.JSON.Send(r.ws, instruction)
if err != nil {
log.Fatal(err)
}
}
}