Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

v0 source pure

Package penalty holds everything about a penalty kick that is pure computation: the constants a game is played with, ...

Overview

Package penalty holds everything about a penalty kick that is pure computation: the constants a game is played with, the ten parameters of a kick, how 32 bytes of entropy map onto them, the shootout rules, and SimulateShot.

It has no state and no realm dependencies, so every version of the game realm agrees on these types, and a client can run the same code to check a result. All quantities are integers: millimetres, mm/s, milliseconds, per-mille (0..1000) and milli-radii (thousandths of the ball's radius), so the outcome is identical on every node.

Constants 8

const ForwardMax, CentreShare, StarMaxSpd

1const (
2	ForwardMax  = 220 // deci-degrees
3	CentreShare = 60  // per-mille of the direction range
4	StarMaxSpd  = 1150
5)
source

Dive headings stay within ForwardMax of the line, except for the middle CentreShare of the direction range, which sweeps the headings in between.

const ChainAimInset, ChainAimMinY, ChainAimOverY, ChainPowerMin, ChainContact

1const (
2	ChainAimInset = 250 // mm inside each post
3	ChainAimMinY  = 300 // mm
4	ChainAimOverY = 200 // mm above the bar at most
5	ChainPowerMin = 450 // per-mille
6	ChainContact  = 350 // milli-radii
7)
source

How the computer takes its kicks: inside the frame, aimed a little high to allow for the drop, struck with at least ChainPowerMin.

const CurlPerMilliR, LiftPerMilliR, LaunchShare

1const (
2	CurlPerMilliR = 45 // tenths of a mm of sideways travel per milli-radius of side contact
3	LiftPerMilliR = 28 // tenths of a mm of lift per milli-radius below centre
4	LaunchShare   = 20 // tenths of a mm of that sideways travel visible in the launch direction
5)
source

const RegulationKicks

1const RegulationKicks = 5
source

RegulationKicks is how many kicks each side takes before sudden death.

Variables 2

var ErrConfigRange, ErrConfigOrder, ErrConfigShares, ErrConfigUnknown, ErrConfigSyntax

1var (
2	ErrConfigRange   = errors.New("penalty: config value out of range")
3	ErrConfigOrder   = errors.New("penalty: config range is inverted")
4	ErrConfigShares  = errors.New("penalty: starShare + readShare must not exceed 900")
5	ErrConfigUnknown = errors.New("penalty: unknown config key")
6	ErrConfigSyntax  = errors.New("penalty: config must be key=value pairs separated by commas")
7)
source

var ErrShotRange

1var ErrShotRange = errors.New("penalty: shot parameter out of range")
source

Functions 6

func MishitHex

1func MishitHex(m [24]byte) string
source

MishitHex prints a mishit seed as 48 hex characters.

func ParseMishitHex

1func ParseMishitHex(s string) ([24]byte, bool)
source

ParseMishitHex reads 48 hex characters.

func DefaultConfig

1func DefaultConfig() Config
source

DefaultConfig returns the constants the reference simulation is tuned for.

func ParseConfig

1func ParseConfig(s string) (Config, error)
source

ParseConfig applies "key=value,key=value" overrides to DefaultConfig and validates the result. An empty string gives the defaults. Keys are the lower-camel names String prints, e.g. "goalWidth=6400,reactionMax=150".

func DecodePlan

1func DecodePlan(p KeeperPlan, c Config) Plan
source

DecodePlan maps the four uint16 of a keeper plan onto a move:

Example
1direction  monotonic 0..65535 -> heading 0°..180°
2speed      lowest StarShare -> star jump, next ReadShare -> wait and read,
3           the rest -> dive at DiveMin..DiveMax
4jump       JumpMin..JumpMax
5reaction   ReactionMin..ReactionMax

For a read plan the direction and jump are unused: the keeper decides them from the ball.

func SimulateShot

1func SimulateShot(shot ShotParams, plan KeeperPlan, c Config) Result
source

SimulateShot decides a kick from its ten inputs: the taker's six (five choices plus the mishit seed) and the keeper's four, played with the game's constants. It is a pure function: the same inputs give the same Result on every node, so anyone can re-run it to check a recorded kick.

SUPERSEDED. This is the coarse integer model the realm used before the physics engine was ported (gno.land/p/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/penalty/physics/v0, which matches the browser game bit for bit and is what impl/v1 calls). It is kept so that kicks recorded under it can still be re-run.

Types 11

type Config

struct
 1type Config struct {
 2	GoalWidth  int64 // inside width, mm
 3	GoalHeight int64 // inside height, mm
 4
 5	KeeperScale int64 // keeper size relative to a ~1.85 m keeper, per-mille
 6	ReactionMin int64 // keeper reaction delay range, ms
 7	ReactionMax int64
 8	StarShare   int64 // share of the keeper's speed range that means "star jump", per-mille
 9	ReadShare   int64 // share that means "wait and read the shot", per-mille
10	DiveMin     int64 // committed dive speed range, mm/s
11	DiveMax     int64
12	JumpMin     int64 // keeper vertical launch speed range, mm/s (negative = collapse low)
13	JumpMax     int64
14
15	BallMinSpeed int64 // ball speed at 0% power, mm/s
16	BallMaxSpeed int64 // ball speed at 100% power, mm/s
17	FuzzBase     int64 // std-dev of the mishit at 0% power, milli-radii
18	FuzzPower    int64 // extra std-dev at 100% power, milli-radii
19	MaxContact   int64 // farthest contact offset a taker may choose, milli-radii
20}
source

Config is the set of keeper and ball constants a game is created with.

Methods on Config

func String

method on Config
1func (c Config) String() string
source

String prints the config in the form ParseConfig accepts.

func Validate

method on Config
1func (c Config) Validate() error
source

Validate checks every constant against its allowed range.

type KeeperPlan

struct
1type KeeperPlan struct {
2	Direction uint16
3	Speed     uint16
4	Jump      uint16
5	Reaction  uint16
6}
source

KeeperPlan is the keeper's commitment: four uint16 values that DecodePlan maps onto a dive using the game's Config.

Methods on KeeperPlan

func String

method on KeeperPlan
1func (p KeeperPlan) String() string
source

type Mode

ident
1type Mode uint8
source

Mode is what kind of move a keeper plan describes.

Methods on Mode

func String

method on Mode
1func (m Mode) String() string
source

type Outcome

ident
1type Outcome uint8
source

Outcome of a single kick.

Methods on Outcome

func Scored

method on Outcome
1func (o Outcome) Scored() bool
source

Scored reports whether the kick counts as a goal.

func String

method on Outcome
1func (o Outcome) String() string
source

type Plan

struct
1type Plan struct {
2	Mode     Mode
3	Heading  int64 // deci-degrees: 0 = along the line to the taker's right, 1800 = to the left, 900 = straight out
4	Speed    int64 // mm/s along the ground (0 for a read)
5	Jump     int64 // mm/s upwards (negative = collapse low)
6	Reaction int64 // ms after contact before moving
7}
source

Plan is a KeeperPlan decoded with a game's constants.

type Result

struct
1type Result struct {
2	Outcome   Outcome
3	X, Y      int64 // where the ball crosses (or would cross) the goal line, mm
4	ArrivalMS int64 // time from contact to the line
5	BallSpeed int64 // mm/s
6	MishitX   int64 // contact error the mishit seed added, milli-radii
7	MishitY   int64
8	Keeper    Mode
9}
source

Result is what SimulateShot reports.

type Seed

array
1type Seed [32]byte
source

Seed is the 32 bytes of entropy that complete a kick.

When the player shoots, the seed supplies the computer's keeper and the player's mishit:

Example
1bytes 0-7    keeper plan: four big-endian uint16 (direction, speed, jump, reaction)
2bytes 8-31   mishit seed (24 bytes)

When the player keeps, the seed supplies the computer's whole kick:

Example
1bytes 0-1    aim x       uint16 -> ±(GoalWidth/2 - ChainAimInset) mm
2bytes 2-3    aim y       uint16 -> ChainAimMinY .. GoalHeight + ChainAimOverY mm
3bytes 4-5    power       uint16 -> ChainPowerMin .. 1000 per-mille
4byte  6      contact x   int8   -> ±ChainContact milli-radii
5byte  7      contact y   int8   -> ±ChainContact milli-radii
6bytes 8-31   mishit seed (24 bytes)

So the layout is the same either way: the first eight bytes are "the computer's move", the last twenty-four are the mishit.

Methods on Seed

func ChainShot

method on Seed
1func (s Seed) ChainShot(c Config) ShotInput
source

ChainShot reads the computer's kick from bytes 0-7 (see Seed).

func Hex

method on Seed
1func (s Seed) Hex() string
source

Hex prints the seed as 64 hex characters.

func KeeperPlan

method on Seed
1func (s Seed) KeeperPlan() KeeperPlan
source

KeeperPlan reads the computer's keeper plan from bytes 0-7.

func Mishit

method on Seed
1func (s Seed) Mishit() [24]byte
source

Mishit returns bytes 8-31.

type Shootout

struct
1type Shootout struct {
2	PlayerKicks int
3	PlayerGoals int
4	ChainKicks  int
5	ChainGoals  int
6}
source

Shootout is the score of a penalty shootout in which the player always kicks first in each round:

  • each side takes RegulationKicks kicks, alternating;
  • it ends early as soon as one side cannot be caught with the kicks the other has left;
  • level after regulation, it goes to sudden death: rounds of one kick each, decided when one side scores and the other does not.

Methods on Shootout

func Next

method on Shootout
1func (s Shootout) Next() Side
source

Next returns who kicks next (SidePlayer at the start of every round).

func Record

method on Shootout
1func (s *Shootout) Record(side Side, scored bool)
source

Record adds a kick for side. It panics if side is out of turn or the shootout is already decided.

func Round

method on Shootout
1func (s Shootout) Round() int
source

Round is the 1-based number of the round in progress.

func SuddenDeath

method on Shootout
1func (s Shootout) SuddenDeath() bool
source

SuddenDeath reports whether regulation is over.

func Winner

method on Shootout
1func (s Shootout) Winner() Side
source

Winner returns the side that has won, or 0 while undecided.

type ShotInput

struct
1type ShotInput struct {
2	AimX     int64 // point on the goal plane the swing heads for, mm from the centre (+ = taker's right)
3	AimY     int64 // its height, mm
4	ContactX int64 // where the boot meets the ball, milli-radii from its centre (+ = right)
5	ContactY int64 // milli-radii (+ = above centre)
6	Power    int64 // per-mille
7}
source

ShotInput is what a taker chooses: the five numbers a player sends.

Methods on ShotInput

func String

method on ShotInput
1func (s ShotInput) String() string
source

func Validate

method on ShotInput
1func (s ShotInput) Validate(c Config) error
source

Validate checks a taker's choices against the game's constants.

func WithMishit

method on ShotInput
1func (s ShotInput) WithMishit(m [24]byte) ShotParams
source

WithMishit completes a taker's choices with a mishit seed.

type ShotParams

struct
1type ShotParams struct {
2	AimX     int64
3	AimY     int64
4	ContactX int64
5	ContactY int64
6	Power    int64
7	Mishit   [24]byte
8}
source

ShotParams is a complete kick: the taker's five choices plus the 24-byte mishit seed that decides how far the boot lands from the chosen contact. These six, with a keeper's four, are the ten inputs of SimulateShot.

Methods on ShotParams

func Input

method on ShotParams
1func (s ShotParams) Input() ShotInput
source

Input returns the taker's five choices.

type Side

ident
1type Side uint8
source

Side is who takes a kick.

Methods on Side

func Other

method on Side
1func (s Side) Other() Side
source

Other returns the opposing side.

func String

method on Side
1func (s Side) String() string
source

Dependencies

Imports 3

/p/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/penalty/v0

Imported by indexer

Source Files 7