Skip to content

Instantly share code, notes, and snippets.

@0xcaff
Created August 18, 2014 00:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save 0xcaff/3c0402d7f452868697b6 to your computer and use it in GitHub Desktop.
Save 0xcaff/3c0402d7f452868697b6 to your computer and use it in GitHub Desktop.
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