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.
|
||||
type action struct {
|
||||
Action string `json:"action"`
|
||||
Param string `json:"param"`
|
||||
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
|
||||
// observers.
|
||||
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
|
||||
// definitely expired.
|
||||
ctx, stop := context.WithTimeoutCause(ctx, 4*time.Hour, errGameExpired)
|
||||
ctx, stop := context.WithTimeoutCause(ctx, 4*time.Hour, errMatchExpired)
|
||||
defer stop()
|
||||
var obs []person
|
||||
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
|
||||
p.conn.CloseRead(ctx)
|
||||
case a := <-actions:
|
||||
// TODO(zeph): transform the action into a game state change
|
||||
slog.DebugContext(ctx, "got action", "from", a.Player, "action", a)
|
||||
broadcast(ctx, g, dealer, chall, obs)
|
||||
slog.DebugContext(ctx, "got action", "from", a.Player, "action", a.Action)
|
||||
err := applyAction(g, a)
|
||||
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