Created
August 18, 2014 00:32
-
-
Save 0xcaff/3c0402d7f452868697b6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"net/http" | |
"net/url" | |
"fmt" | |
"io" | |
"regexp" | |
"strconv" | |
"strings" | |
"github.com/oleiade/lane" | |
) | |
var ( | |
server = "http://vindinium.org/api/training" | |
key = "ec4rl6yd" | |
MineRe = regexp.MustCompile(`\$([\d-]{1})`) | |
) | |
type Point struct { | |
X, Y int | |
} | |
func Add(a, b Point) Point { | |
return Point{X: a.X + b.X, Y: a.Y + b.Y} | |
} | |
func (p *Point) String() string { | |
return "(" + strconv.Itoa(p.X) + "," + strconv.Itoa(p.Y) + ")" | |
} | |
var ( | |
North = Point{X: 0, Y: 1} | |
South = Point{X: 0, Y: -1} | |
East = Point{X: 1, Y: 0} | |
West = Point{X: -1, Y: 1} | |
Directions = []Point{ | |
North, | |
East, | |
South, | |
West, | |
} | |
) | |
type Hero struct { | |
ID uint | |
Name string | |
User string `json:"userId"` | |
ELO uint | |
Position Point `json:"pos"` | |
Life uint | |
Gold uint | |
Mines []Point | |
Spawn Point `json:"spawnPos"` | |
Crashed bool | |
} | |
type Board struct { | |
Size int | |
RawTiles json.RawMessage `json:"tiles"` | |
Tiles [][]string | |
Finished bool | |
Taverns []Point | |
Mines []Location | |
} | |
func (b *Board) String() string { | |
var s []string | |
for l := range b.Tiles { | |
s = append(s, fmt.Sprintf("%2d", l)+"| "+strings.Join(b.Tiles[l], " ")) | |
} | |
t := strings.Join(s, "\n") | |
var ns []string | |
for i := 0; i < b.Size; i++ { | |
ns = append(ns, fmt.Sprintf("%2d", i)) | |
} | |
nums := strings.Join(ns, "|") | |
return fmt.Sprintf(" | %s\n%s", nums, t) | |
} | |
type Location struct { | |
Owner *Hero | |
Point Point | |
} | |
type Game struct { | |
ID string | |
Turn uint | |
MaxTurns uint | |
Finished bool | |
Heroes []Hero | |
Board Board | |
} | |
type State struct { | |
Game Game | |
Me Hero `json:"hero"` | |
Token string | |
View string | |
Play string | |
} | |
func Decode(resp io.Reader) State { | |
var d State | |
json.NewDecoder(resp).Decode(&d) | |
var t string | |
json.Unmarshal(d.Game.Board.RawTiles, &t) | |
var b [][]string | |
lines := Split(t, int(d.Game.Board.Size)*2) | |
for line := range lines { | |
b = append(b, Split(lines[line], 2)) | |
} | |
d.Game.Board.Tiles = b | |
board := &d.Game.Board | |
for i := range board.Tiles { | |
for j := range board.Tiles[i] { | |
switch { | |
case board.Tiles[i][j] == "##" || board.Tiles[i][j] == " ": | |
continue | |
case board.Tiles[i][j] == "[]": | |
board.Taverns = append(board.Taverns, Point{X: i, Y: j}) | |
case MineRe.MatchString(board.Tiles[i][j]): | |
m := MineRe.FindStringSubmatch(board.Tiles[i][j]) | |
var o *Hero | |
if m[1] != "-" { | |
for h := range d.Game.Heroes { | |
if m[1] == strconv.Itoa(int(d.Game.Heroes[h].ID)) { | |
o = &d.Game.Heroes[h] | |
break | |
} | |
} | |
} | |
board.Mines = append(board.Mines, Location{Owner: o, Point: Point{X: i, Y: j}}) | |
} | |
} | |
} | |
return d | |
} | |
func main() { | |
resp, err := http.PostForm(server, url.Values{"key": {key}}) | |
if err != nil { | |
panic(fmt.Errorf("Failed to get response from server %v", err)) | |
} | |
d := Decode(resp.Body) | |
for d.Game.Finished { | |
break | |
} | |
fmt.Println(d.Game.Board.String()) | |
fmt.Println(MoveTo(d.Me.Position, d.Game.Board.Taverns[0], d.Game.Board)) | |
} | |
// Split splits s into strings e long. The remaindar, if any, is the last | |
// element. | |
func Split(s string, e int) []string { | |
var res []string | |
for i := 0; i < len(s); i += e { | |
var li int | |
if i <= 0 { | |
continue | |
} else { | |
li = i - e | |
} | |
res = append(res, s[li:i]) | |
} | |
return res | |
} | |
func MoveTo(from, to Point, board Board) []Point { | |
cf := make(map[Point]*Point) | |
cf[from] = nil | |
frontier := lane.NewQueue() | |
frontier.Enqueue(from) | |
for !frontier.Empty() { | |
p := frontier.Dequeue().(Point) | |
if p == to { | |
break | |
} | |
for d := range Directions { | |
np := Add(Directions[d], p) | |
if _, ok := cf[np]; ok || np.X < 0 || np.Y < 0 || | |
np.Y > len(board.Tiles[0])-1 || np.X > len(board.Tiles)-1 { | |
continue | |
} | |
// TODO: Merge these if statements | |
// TODO: Make this consider players | |
if t := board.Tiles[np.X][np.Y]; t != "##" { | |
frontier.Enqueue(np) | |
cf[np] = &p | |
} | |
} | |
} | |
path := []Point{ | |
to, | |
} | |
p := to | |
for p != from { | |
p = *cf[p] | |
path = append(path, p) | |
} | |
return path | |
} | |
// TODO: Fix variable names |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment