initial commit, game init implemented
This commit is contained in:
commit
f0dc3716e8
35
game/game.go
Normal file
35
game/game.go
Normal file
@ -0,0 +1,35 @@
|
||||
package game
|
||||
|
||||
type Game struct {
|
||||
RNG RNG
|
||||
PP [2]Player
|
||||
Shells []bool
|
||||
Round int
|
||||
Turn int
|
||||
Damage int8
|
||||
|
||||
// Backing storage for shells.
|
||||
ShellArray [8]bool
|
||||
}
|
||||
|
||||
func NewGame() *Game {
|
||||
return &Game{RNG: NewRNG()}
|
||||
}
|
||||
|
||||
func (g *Game) StartRound() {
|
||||
items := g.RNG.Intn(4) + 1
|
||||
g.PP[0].StartRound(&g.RNG, items)
|
||||
g.PP[1].StartRound(&g.RNG, items)
|
||||
shells := g.RNG.Intn(6) + 2
|
||||
for i := 0; i < shells/2; i++ {
|
||||
g.ShellArray[i] = true
|
||||
}
|
||||
for i := shells / 2; i < shells; i++ {
|
||||
g.ShellArray[i] = false
|
||||
}
|
||||
g.Shells = g.ShellArray[:shells]
|
||||
ShuffleSlice(&g.RNG, g.Shells)
|
||||
g.Round++
|
||||
g.Turn = 0
|
||||
g.Damage = 1
|
||||
}
|
16
game/item.go
Normal file
16
game/item.go
Normal file
@ -0,0 +1,16 @@
|
||||
package game
|
||||
|
||||
type Item int8
|
||||
|
||||
const (
|
||||
ItemNone Item = iota
|
||||
ItemLens
|
||||
ItemCig
|
||||
ItemBeer
|
||||
ItemCuff
|
||||
ItemKnife
|
||||
)
|
||||
|
||||
func NewItem(rng *RNG) Item {
|
||||
return Item(rng.Intn(5)) + 1
|
||||
}
|
17
game/player.go
Normal file
17
game/player.go
Normal file
@ -0,0 +1,17 @@
|
||||
package game
|
||||
|
||||
type Player struct {
|
||||
HP int8
|
||||
Items [8]Item
|
||||
Skip bool
|
||||
Cuffed bool
|
||||
}
|
||||
|
||||
func (p *Player) StartRound(rng *RNG, items int) {
|
||||
p.HP = int8(rng.Intn(3) + 2)
|
||||
for i := 0; i < items; i++ {
|
||||
p.Items[i] = NewItem(rng)
|
||||
}
|
||||
p.Skip = false
|
||||
p.Cuffed = false
|
||||
}
|
65
game/rng.go
Normal file
65
game/rng.go
Normal file
@ -0,0 +1,65 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// RNG is a random number generator for shotgun.
|
||||
//
|
||||
// Currently xoshiro256**. Subject to change.
|
||||
type RNG struct {
|
||||
w, x, y, z uint64
|
||||
}
|
||||
|
||||
// NewRNG produces a new, uniquely seeded RNG.
|
||||
func NewRNG() RNG {
|
||||
r := RNG{}
|
||||
b := make([]byte, 8*4)
|
||||
// Loop to ensure the state is never all-zero, which is an invalid state
|
||||
// for xoshiro.
|
||||
for r.w == 0 && r.x == 0 && r.y == 0 && r.z == 0 {
|
||||
rand.Read(b)
|
||||
r.w = binary.LittleEndian.Uint64(b)
|
||||
r.x = binary.LittleEndian.Uint64(b[8:])
|
||||
r.y = binary.LittleEndian.Uint64(b[16:])
|
||||
r.z = binary.LittleEndian.Uint64(b[24:])
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Uint64 produces a 64-bit pseudo-random value.
|
||||
func (rng *RNG) Uint64() uint64 {
|
||||
w, x, y, z := rng.w, rng.x, rng.y, rng.z
|
||||
r := bits.RotateLeft64(x*5, 7) * 9
|
||||
t := x << 17
|
||||
y ^= w
|
||||
z ^= x
|
||||
x ^= y
|
||||
w ^= z
|
||||
y ^= t
|
||||
z = bits.RotateLeft64(z, 45)
|
||||
rng.w, rng.x, rng.y, rng.z = w, x, y, z
|
||||
return r
|
||||
}
|
||||
|
||||
// Intn produces an int in [0, n). Panics if n <= 0.
|
||||
func (rng *RNG) Intn(n int) int {
|
||||
if n <= 0 {
|
||||
panic("shotgun: rng.Intn max below zero")
|
||||
}
|
||||
bad := ^uint(0) - ^uint(0)%uint(n)
|
||||
x := uint(rng.Uint64())
|
||||
for x > bad {
|
||||
x = uint(rng.Uint64())
|
||||
}
|
||||
return int(x % uint(n))
|
||||
}
|
||||
|
||||
func ShuffleSlice[E any, S ~[]E](rng *RNG, s S) {
|
||||
for i := len(s) - 1; i > 0; i-- {
|
||||
j := rng.Intn(i + 1)
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user