2020-07-25 17:37:41 -07:00
|
|
|
package rules
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
)
|
|
|
|
|
|
2022-04-19 15:52:57 -07:00
|
|
|
var royaleRulesetStages = []string{
|
2022-06-01 15:21:27 -07:00
|
|
|
StageGameOverStandard,
|
2022-04-19 15:52:57 -07:00
|
|
|
StageMovementStandard,
|
|
|
|
|
StageStarvationStandard,
|
|
|
|
|
StageHazardDamageStandard,
|
|
|
|
|
StageFeedSnakesStandard,
|
|
|
|
|
StageEliminationStandard,
|
|
|
|
|
StageSpawnHazardsShrinkMap,
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-25 17:37:41 -07:00
|
|
|
type RoyaleRuleset struct {
|
|
|
|
|
StandardRuleset
|
|
|
|
|
|
2022-05-25 11:17:41 -07:00
|
|
|
ShrinkEveryNTurns int
|
2020-07-25 17:37:41 -07:00
|
|
|
}
|
|
|
|
|
|
2022-03-16 16:58:05 -07:00
|
|
|
func (r *RoyaleRuleset) Name() string { return GameTypeRoyale }
|
2021-07-02 20:09:55 -07:00
|
|
|
|
2022-04-19 15:52:57 -07:00
|
|
|
func (r RoyaleRuleset) Execute(bs *BoardState, s Settings, sm []SnakeMove) (bool, *BoardState, error) {
|
|
|
|
|
return NewPipeline(royaleRulesetStages...).Execute(bs, s, sm)
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-25 17:37:41 -07:00
|
|
|
func (r *RoyaleRuleset) CreateNextBoardState(prevState *BoardState, moves []SnakeMove) (*BoardState, error) {
|
2021-08-17 16:47:06 -07:00
|
|
|
if r.StandardRuleset.HazardDamagePerTurn < 1 {
|
|
|
|
|
return nil, errors.New("royale damage per turn must be greater than zero")
|
2020-07-25 17:37:41 -07:00
|
|
|
}
|
2022-04-19 15:52:57 -07:00
|
|
|
_, nextState, err := r.Execute(prevState, r.Settings(), moves)
|
|
|
|
|
return nextState, err
|
2022-03-16 16:58:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func PopulateHazardsRoyale(b *BoardState, settings Settings, moves []SnakeMove) (bool, error) {
|
2022-04-19 15:52:57 -07:00
|
|
|
if IsInitialization(b, settings, moves) {
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|
2021-08-17 16:47:06 -07:00
|
|
|
b.Hazards = []Point{}
|
2020-07-25 17:37:41 -07:00
|
|
|
|
2022-03-16 16:58:05 -07:00
|
|
|
// Royale uses the current turn to generate hazards, not the previous turn that's in the board state
|
|
|
|
|
turn := b.Turn + 1
|
|
|
|
|
|
|
|
|
|
if settings.RoyaleSettings.ShrinkEveryNTurns < 1 {
|
|
|
|
|
return false, errors.New("royale game can't shrink more frequently than every turn")
|
2020-07-25 17:37:41 -07:00
|
|
|
}
|
|
|
|
|
|
2022-03-16 16:58:05 -07:00
|
|
|
if turn < settings.RoyaleSettings.ShrinkEveryNTurns {
|
|
|
|
|
return false, nil
|
2020-07-25 17:37:41 -07:00
|
|
|
}
|
|
|
|
|
|
2022-05-25 11:24:27 -07:00
|
|
|
randGenerator := settings.GetRand(0)
|
2020-07-29 10:24:38 -07:00
|
|
|
|
2022-03-16 16:58:05 -07:00
|
|
|
numShrinks := turn / settings.RoyaleSettings.ShrinkEveryNTurns
|
2022-05-25 11:17:41 -07:00
|
|
|
minX, maxX := 0, b.Width-1
|
|
|
|
|
minY, maxY := 0, b.Height-1
|
|
|
|
|
for i := 0; i < numShrinks; i++ {
|
2020-07-29 10:24:38 -07:00
|
|
|
switch randGenerator.Intn(4) {
|
|
|
|
|
case 0:
|
|
|
|
|
minX += 1
|
|
|
|
|
case 1:
|
|
|
|
|
maxX -= 1
|
|
|
|
|
case 2:
|
|
|
|
|
minY += 1
|
|
|
|
|
case 3:
|
|
|
|
|
maxY -= 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-25 11:17:41 -07:00
|
|
|
for x := 0; x < b.Width; x++ {
|
|
|
|
|
for y := 0; y < b.Height; y++ {
|
2020-07-25 17:37:41 -07:00
|
|
|
if x < minX || x > maxX || y < minY || y > maxY {
|
2021-08-17 16:47:06 -07:00
|
|
|
b.Hazards = append(b.Hazards, Point{x, y})
|
2020-07-25 17:37:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 16:58:05 -07:00
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-19 15:52:57 -07:00
|
|
|
func (r *RoyaleRuleset) IsGameOver(b *BoardState) (bool, error) {
|
|
|
|
|
return GameOverStandard(b, r.Settings(), nil)
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 16:58:05 -07:00
|
|
|
func (r RoyaleRuleset) Settings() Settings {
|
|
|
|
|
s := r.StandardRuleset.Settings()
|
|
|
|
|
s.RoyaleSettings = RoyaleSettings{
|
|
|
|
|
ShrinkEveryNTurns: r.ShrinkEveryNTurns,
|
|
|
|
|
}
|
|
|
|
|
return s
|
|
|
|
|
}
|