apply game actions from connections
This commit is contained in:
parent
6077316a0d
commit
1099e0b618
76
game.go
76
game.go
@ -16,16 +16,48 @@ import (
|
|||||||
// An action is a request to change the game state.
|
// An action is a request to change the game state.
|
||||||
type action struct {
|
type action struct {
|
||||||
Action string `json:"action"`
|
Action string `json:"action"`
|
||||||
Param string `json:"param"`
|
|
||||||
Player player.ID `json:"-"`
|
Player player.ID `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyAction(g *game.Match, a action) error {
|
||||||
|
switch a.Action {
|
||||||
|
case "quit":
|
||||||
|
return g.Concede(a.Player)
|
||||||
|
case "across", "self":
|
||||||
|
if err := g.Shoot(a.Player, a.Action == "self"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if g.RoundWinner() != nil {
|
||||||
|
return errRoundEnded
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case "0":
|
||||||
|
return g.Apply(a.Player, 0)
|
||||||
|
case "1":
|
||||||
|
return g.Apply(a.Player, 1)
|
||||||
|
case "2":
|
||||||
|
return g.Apply(a.Player, 2)
|
||||||
|
case "3":
|
||||||
|
return g.Apply(a.Player, 3)
|
||||||
|
case "4":
|
||||||
|
return g.Apply(a.Player, 4)
|
||||||
|
case "5":
|
||||||
|
return g.Apply(a.Player, 5)
|
||||||
|
case "6":
|
||||||
|
return g.Apply(a.Player, 6)
|
||||||
|
case "7":
|
||||||
|
return g.Apply(a.Player, 7)
|
||||||
|
default:
|
||||||
|
return errWeirdAction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// gameActor is an actor that updates a game's state and relays changes to all
|
// gameActor is an actor that updates a game's state and relays changes to all
|
||||||
// observers.
|
// observers.
|
||||||
func gameActor(ctx context.Context, g *game.Match, dealer, chall person, join <-chan person) {
|
func gameActor(ctx context.Context, g *game.Match, dealer, chall person, join <-chan person) {
|
||||||
// Games should generally be on the order of minutes. A four hour game is
|
// Games should generally be on the order of minutes. A four hour game is
|
||||||
// definitely expired.
|
// definitely expired.
|
||||||
ctx, stop := context.WithTimeoutCause(ctx, 4*time.Hour, errGameExpired)
|
ctx, stop := context.WithTimeoutCause(ctx, 4*time.Hour, errMatchExpired)
|
||||||
defer stop()
|
defer stop()
|
||||||
var obs []person
|
var obs []person
|
||||||
actions := make(chan action, 2)
|
actions := make(chan action, 2)
|
||||||
@ -51,9 +83,27 @@ func gameActor(ctx context.Context, g *game.Match, dealer, chall person, join <-
|
|||||||
// observer when they disconnect
|
// observer when they disconnect
|
||||||
p.conn.CloseRead(ctx)
|
p.conn.CloseRead(ctx)
|
||||||
case a := <-actions:
|
case a := <-actions:
|
||||||
// TODO(zeph): transform the action into a game state change
|
slog.DebugContext(ctx, "got action", "from", a.Player, "action", a.Action)
|
||||||
slog.DebugContext(ctx, "got action", "from", a.Player, "action", a)
|
err := applyAction(g, a)
|
||||||
broadcast(ctx, g, dealer, chall, obs)
|
switch err {
|
||||||
|
case nil:
|
||||||
|
broadcast(ctx, g, dealer, chall, obs)
|
||||||
|
case errRoundEnded:
|
||||||
|
broadcast(ctx, g, dealer, chall, obs)
|
||||||
|
if g.MatchWinner() != nil {
|
||||||
|
gameOver(ctx, dealer, chall, obs)
|
||||||
|
// TODO(zeph): server needs to know the players are gone
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.NextRound()
|
||||||
|
broadcast(ctx, g, dealer, chall, obs)
|
||||||
|
// TODO(zeph): broadcast shell counts?
|
||||||
|
case game.ErrWrongTurn: // do nothing
|
||||||
|
case errWeirdAction:
|
||||||
|
slog.WarnContext(ctx, "nonsense action", "from", a.Player, "action", a.Action)
|
||||||
|
default:
|
||||||
|
slog.ErrorContext(ctx, "action caused a mystery error", "from", a.Player, "action", a.Action, "err", err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,4 +148,18 @@ func broadcast(ctx context.Context, g *game.Match, dealer, chall person, obs []p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var errGameExpired = errors.New("there is a time limit on games please")
|
func gameOver(ctx context.Context, dealer, chall person, obs []person) {
|
||||||
|
// TODO(zeph): need to communicate to the server that these have gone away
|
||||||
|
go dealer.conn.Close(websocket.StatusNormalClosure, "match ended")
|
||||||
|
go chall.conn.Close(websocket.StatusNormalClosure, "match ended")
|
||||||
|
for _, p := range obs {
|
||||||
|
c := p.conn
|
||||||
|
go c.Close(websocket.StatusNormalClosure, "match ended")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errRoundEnded = errors.New("someone h*ckin died")
|
||||||
|
errWeirdAction = errors.New("unknown action")
|
||||||
|
errMatchExpired = errors.New("there is a time limit on matches please")
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user