second commit, too busy flowing to isolate work
This commit is contained in:
parent
f0dc3716e8
commit
e173225b6e
52
game/game.go
52
game/game.go
@ -4,22 +4,34 @@ type Game struct {
|
|||||||
RNG RNG
|
RNG RNG
|
||||||
PP [2]Player
|
PP [2]Player
|
||||||
Shells []bool
|
Shells []bool
|
||||||
Round int
|
HP int8
|
||||||
Turn int
|
Round uint
|
||||||
|
Group uint
|
||||||
|
Turn uint
|
||||||
Damage int8
|
Damage int8
|
||||||
|
Reveal bool
|
||||||
|
|
||||||
// Backing storage for shells.
|
// Backing storage for shells.
|
||||||
ShellArray [8]bool
|
ShellArray [8]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGame() *Game {
|
func NewGame() *Game {
|
||||||
return &Game{RNG: NewRNG()}
|
return &Game{
|
||||||
|
RNG: NewRNG(),
|
||||||
|
Damage: 1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) StartRound() {
|
func (g *Game) StartRound() {
|
||||||
|
g.PP[0].StartRound()
|
||||||
|
g.PP[1].StartRound()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) StartGroup() {
|
||||||
items := g.RNG.Intn(4) + 1
|
items := g.RNG.Intn(4) + 1
|
||||||
g.PP[0].StartRound(&g.RNG, items)
|
g.HP = int8(g.RNG.Intn(3) + 2)
|
||||||
g.PP[1].StartRound(&g.RNG, items)
|
g.PP[0].StartGroup(&g.RNG, g.HP, items)
|
||||||
|
g.PP[1].StartGroup(&g.RNG, g.HP, items)
|
||||||
shells := g.RNG.Intn(6) + 2
|
shells := g.RNG.Intn(6) + 2
|
||||||
for i := 0; i < shells/2; i++ {
|
for i := 0; i < shells/2; i++ {
|
||||||
g.ShellArray[i] = true
|
g.ShellArray[i] = true
|
||||||
@ -29,7 +41,31 @@ func (g *Game) StartRound() {
|
|||||||
}
|
}
|
||||||
g.Shells = g.ShellArray[:shells]
|
g.Shells = g.ShellArray[:shells]
|
||||||
ShuffleSlice(&g.RNG, g.Shells)
|
ShuffleSlice(&g.RNG, g.Shells)
|
||||||
g.Round++
|
g.Group++
|
||||||
g.Turn = 0
|
}
|
||||||
g.Damage = 1
|
|
||||||
|
// CurrentPlayer gets the index of the current player, either 0 or 1.
|
||||||
|
func (g *Game) CurrentPlayer() uint {
|
||||||
|
return g.Turn % 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opponent returns the player who is not the current player.
|
||||||
|
func (g *Game) Opponent() *Player {
|
||||||
|
return &g.PP[1^g.CurrentPlayer()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply uses an item by index for the current player.
|
||||||
|
func (g *Game) Apply(item int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// PopShell removes a shell from the shotgun.
|
||||||
|
// This may cause the shotgun to be empty, but does not start the next group
|
||||||
|
// if so.
|
||||||
|
func (g *Game) PopShell() {
|
||||||
|
g.Shells = g.Shells[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns whether the shotgun is empty.
|
||||||
|
func (g *Game) Empty() bool {
|
||||||
|
return len(g.Shells) == 0
|
||||||
}
|
}
|
||||||
|
41
game/item.go
41
game/item.go
@ -14,3 +14,44 @@ const (
|
|||||||
func NewItem(rng *RNG) Item {
|
func NewItem(rng *RNG) Item {
|
||||||
return Item(rng.Intn(5)) + 1
|
return Item(rng.Intn(5)) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i Item) Apply(g *Game) bool {
|
||||||
|
switch i {
|
||||||
|
case ItemNone:
|
||||||
|
return false
|
||||||
|
case ItemLens:
|
||||||
|
if g.Reveal {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
g.Reveal = true
|
||||||
|
return true
|
||||||
|
case ItemCig:
|
||||||
|
cur := &g.PP[g.CurrentPlayer()]
|
||||||
|
if cur.HP < g.HP {
|
||||||
|
cur.HP++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
case ItemBeer:
|
||||||
|
g.PopShell()
|
||||||
|
if g.Empty() {
|
||||||
|
g.StartGroup()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
case ItemCuff:
|
||||||
|
opp := g.Opponent()
|
||||||
|
if opp.Cuffs != Uncuffed {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
opp.Cuffs = Cuffed
|
||||||
|
return true
|
||||||
|
case ItemKnife:
|
||||||
|
if g.Damage != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
g.Damage = 2
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
panic("shotgun: unknown item")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,17 +1,38 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
|
import "slices"
|
||||||
|
|
||||||
|
// PlayerID is a unique ID for a player.
|
||||||
|
// May just be IPv6 (or IPv4-in-6) of their connection, or a UUID.
|
||||||
|
type PlayerID [16]byte
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
HP int8
|
ID PlayerID
|
||||||
Items [8]Item
|
HP int8
|
||||||
Skip bool
|
Items [8]Item
|
||||||
Cuffed bool
|
Cuffs CuffState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) StartRound(rng *RNG, items int) {
|
func (p *Player) StartRound() {
|
||||||
p.HP = int8(rng.Intn(3) + 2)
|
clear(p.Items[:])
|
||||||
for i := 0; i < items; i++ {
|
|
||||||
p.Items[i] = NewItem(rng)
|
|
||||||
}
|
|
||||||
p.Skip = false
|
|
||||||
p.Cuffed = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Player) StartGroup(rng *RNG, hp int8, items int) {
|
||||||
|
p.HP = hp
|
||||||
|
for i := 0; i < items; i++ {
|
||||||
|
k := slices.Index(p.Items[:], ItemNone)
|
||||||
|
if k < 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p.Items[k] = NewItem(rng)
|
||||||
|
}
|
||||||
|
p.Cuffs = Uncuffed // TODO(zeph): or is this startround?
|
||||||
|
}
|
||||||
|
|
||||||
|
type CuffState uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
Uncuffed CuffState = iota
|
||||||
|
Cuffed
|
||||||
|
CuffedSkip
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user