From 5f6ad5930302d34e52175b785af2e0eea3e48fa5 Mon Sep 17 00:00:00 2001 From: Stephen McQuay Date: Sun, 10 Nov 2013 23:30:23 -0800 Subject: [PATCH] spelled things more how I wanted to --- botserv.go | 11 ++++ main.go | 174 +++++++---------------------------------------------- robot.go | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+), 153 deletions(-) create mode 100644 robot.go diff --git a/botserv.go b/botserv.go index 2674a43..ab72cc0 100644 --- a/botserv.go +++ b/botserv.go @@ -9,6 +9,17 @@ type ClientConfig struct { Stats map[string]StatsRequest `json:"stats"` } +type BoardSize struct { + Width float32 `json:"width"` + Height float32 `json:"height"` +} + +type GameParam struct { + BoardSize BoardSize `json:"boardsize"` + name string + Type string `json:"type"` +} + type StatsRequest struct { Hp int `json:"hp"` Speed int `json:"speed"` diff --git a/main.go b/main.go index 341e0ef..6e050cd 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,7 @@ package main import ( - "bitbucket.org/hackerbots/vector" - "code.google.com/p/go.net/websocket" - "errors" "flag" - "fmt" "log" "math/rand" "time" @@ -18,168 +14,40 @@ var weaponRadius = flag.Int("wrad", 50, "weapon radius") var scannerRadius = flag.Int("srad", 50, "scanner radius") var fireRate = flag.Int("fire-rate", 50, "scanner radius") +// XXX: add TurnSpeed, WeaponDamage, WeaponSpeed + var server = flag.String("server", "hackerbots.us", "server hostname") var port = flag.Int("port", 8666, "server port") + var botname = flag.String("name", "gobot", "the name that other players will see") + var verbose = flag.Bool("verbose", false, "run verbosly") -type infos struct { - id string - width, height float32 -} - -func connect() (*websocket.Conn, error) { - origin := "http://localhost/" - url := fmt.Sprintf("ws://%s:%d/ws/", *server, *port) - return websocket.Dial(url, "", origin) -} - -func negociate(ws *websocket.Conn, gameid string) (i *infos, err error) { - log.Printf("trying to connect to game %s", gameid) - err = websocket.JSON.Send(ws, struct { - Id string `json:"id"` - }{ - gameid, - }) - if err != nil { - return nil, err - } - - var idreq struct { - Type string `json:"type"` - AssignedID string `json:"id"` - } - err = websocket.JSON.Receive(ws, &idreq) - if err != nil || idreq.Type == "failure" { - return nil, errors.New(fmt.Sprintf("failure: %+v", idreq)) - } - log.Printf("idreq: %+v", idreq) - - err = websocket.JSON.Send(ws, struct { - Type string `json:"type"` - Name string `json:"name"` - Useragent string `json:"useragent"` - }{ - Name: *botname, - Useragent: "gobot", - Type: "robot", - }) - if err != nil { - return nil, err - } - - type BoardSize struct { - Width float32 `json:"width"` - Height float32 `json:"height"` - } - var gameparam struct { - BoardSize BoardSize `json:"boardsize"` - - Type string `json:"type"` - } - err = websocket.JSON.Receive(ws, &gameparam) - if gameparam.Type != "gameparam" { - return nil, errors.New("didn't receive a good gameparam") - } - log.Printf("gameparam: %+v", gameparam) - - conf := ClientConfig{ - ID: gameid, - Stats: map[string]StatsRequest{ - *botname: StatsRequest{ - Hp: *hp, - Speed: *speed, - Acceleration: *acceleration, - WeaponRadius: *weaponRadius, - ScannerRadius: *scannerRadius, - TurnSpeed: 50, - FireRate: *fireRate, - WeaponDamage: 50, - WeaponSpeed: 50, - }, - }, - } - - err = websocket.JSON.Send(ws, conf) - - var handshake struct { - ID string `json:"id"` - Success bool `json:"success"` - Type string `json:"type"` - } - websocket.JSON.Receive(ws, &handshake) - if !handshake.Success { - return nil, errors.New("failed to validate correct stats request") - } - log.Printf("handshake: %+v", handshake) - return &infos{ - id: idreq.AssignedID, - width: gameparam.BoardSize.Width, - height: gameparam.BoardSize.Height, - }, err -} - func main() { rand.Seed(time.Now().UnixNano()) var err error - var gameid string + var gameName string flag.Parse() if flag.NArg() < 1 { - gameid = "debug" + gameName = "debug" } else { - gameid = flag.Arg(0) + gameName = flag.Arg(0) } - - ws, err := connect() + // XXX: add TurnSpeed, WeaponDamage, WeaponSpeed + r, err := NewRobot( + *server, + *port, + gameName, + *hp, + *speed, + *acceleration, + *weaponRadius, + *scannerRadius, + *fireRate, + ) if err != nil { log.Fatal(err) } - boardInfo, err := negociate(ws, gameid) - log.Printf("boardInfo: %+v", boardInfo) - if err != nil { - log.Fatal(err) - } - - // TODO: var target govector.Point2d - moveto := govector.Point2d{ - X: rand.Float32() * boardInfo.width, - Y: rand.Float32() * boardInfo.height, - } - log.Printf("moveto: %+v", moveto) - - var me Robot - - log.Printf("negociated well, starting loop") - for { - var boardstate Boardstate - err = websocket.JSON.Receive(ws, &boardstate) - // log.Printf("%#v", 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() * boardInfo.width, - Y: rand.Float32() * boardInfo.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(ws, instruction) - if err != nil { - log.Fatal(err) - } - } + log.Printf("%+v", r) + r.play() } diff --git a/robot.go b/robot.go new file mode 100644 index 0000000..9746bbf --- /dev/null +++ b/robot.go @@ -0,0 +1,167 @@ +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) + } + } +}