package game import ( "battlecamp-go/board" "battlecamp-go/events" "battlecamp-go/player" "battlecamp-go/stomp" "log" "math/rand" "sync" "time" ) type Game struct { Id int64 `json:"id"` StartTime int64 `json:"startTime"` EndTime int64 `json:"endTime"` Board *board.Board `json:"board"` Players []*player.Player `json:"-"` mutex sync.Mutex Winner *player.Player `json:"winner,omitempty"` } func NewGame(width, height int) *Game { createTime := time.Now().Unix() game := &Game{ StartTime: createTime, Board: board.NewRemote(width, height), Players: make([]*player.Player, 0), } return game } func (g *Game) Join(p *player.Player) { g.mutex.Lock() g.placePlayer(p) g.Players = append(g.Players, p) g.mutex.Unlock() } func (g *Game) placePlayer(p *player.Player) { xRange := g.Board.Width / 5 yRange := g.Board.Height for { x := rand.Intn(xRange) y := rand.Intn(yRange) if g.isValidPlayerPos(x, y) { p.Pos.X = x p.Pos.Y = y return } } } func (g *Game) Move(p *player.Player, direction string) bool { if !(direction == "N" || direction == "W" || direction == "S" || direction == "E") { log.Printf("Illigal direction %v", direction) return false } newX := p.Pos.X newY := p.Pos.Y switch direction { case "N": newY-- case "W": newX-- case "S": newY++ case "E": newX++ } //TODO make thread safe if !g.isValidPlayerPos(newX, newY) { log.Printf("Illigal player pos oldX %v oldY %v newX %v newY %v dir %v ", p.Pos.X, p.Pos.Y, newX, newY, direction) return false } p.Pos.X = newX p.Pos.Y = newY // END TODO make tread safe up := events.PlayerUpdate{ GameId: g.Id, Players: g.Players, } stomp.SendJsonPlayerUpdate("update", up) if g.isWinner(p) { g.EndTime = time.Now().Unix() g.Winner = p ge := events.GameEnd{ Type: "GAME_END", GameId: g.Id, Payload: g.Winner.Id, } stomp.SendJson("game", ge) } return true } func (g *Game) isWinner(p *player.Player) bool { return g.Board.Finish.X == p.Pos.X && g.Board.Finish.Y == p.Pos.Y } func (g *Game) isValidPlayerPos(x, y int) bool { if x < 0 || y < 0 || x >= g.Board.Width || y >= g.Board.Height { return false } t := g.Board.Get(x, y) if t == board.Rock { return false } return g.getPlayerAt(x, y) == nil } func (g *Game) getPlayerAt(x, y int) *player.Player { for _, p := range g.Players { if p.Pos.X == x && p.Pos.Y == y { return p } } return nil } func (g *Game) GetPlayer(playerId string) *player.Player { for _, p := range g.Players { if p.Id == playerId { return p } } return nil }