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.

params.gno

2.99 Kb · 87 lines
 1package penalty
 2
 3import (
 4	"errors"
 5	"strconv"
 6)
 7
 8const (
 9	BallRadius = 110   // mm
10	PostRadius = 60    // mm
11	Distance   = 11000 // penalty spot to goal line, mm
12	Gravity    = 9810  // mm/s²
13
14	AimMaxX = 6000 // the aim point must lie within ±6 m of the goal centre
15	AimMaxY = 4000 // and between the grass and 4 m up
16)
17
18// ShotInput is what a taker chooses: the five numbers a player sends.
19type ShotInput struct {
20	AimX     int64 // point on the goal plane the swing heads for, mm from the centre (+ = taker's right)
21	AimY     int64 // its height, mm
22	ContactX int64 // where the boot meets the ball, milli-radii from its centre (+ = right)
23	ContactY int64 // milli-radii (+ = above centre)
24	Power    int64 // per-mille
25}
26
27// ShotParams is a complete kick: the taker's five choices plus the 24-byte
28// mishit seed that decides how far the boot lands from the chosen contact.
29// These six, with a keeper's four, are the ten inputs of SimulateShot.
30type ShotParams struct {
31	AimX     int64
32	AimY     int64
33	ContactX int64
34	ContactY int64
35	Power    int64
36	Mishit   [24]byte
37}
38
39// KeeperPlan is the keeper's commitment: four uint16 values that DecodePlan
40// maps onto a dive using the game's Config.
41type KeeperPlan struct {
42	Direction uint16
43	Speed     uint16
44	Jump      uint16
45	Reaction  uint16
46}
47
48var ErrShotRange = errors.New("penalty: shot parameter out of range")
49
50// Validate checks a taker's choices against the game's constants.
51func (s ShotInput) Validate(c Config) error {
52	if s.AimX < -AimMaxX || s.AimX > AimMaxX {
53		return errors.New(ErrShotRange.Error() + ": aimX must be within ±" + strconv.Itoa(AimMaxX) + " mm")
54	}
55	if s.AimY < 0 || s.AimY > AimMaxY {
56		return errors.New(ErrShotRange.Error() + ": aimY must be within 0.." + strconv.Itoa(AimMaxY) + " mm")
57	}
58	if s.ContactX*s.ContactX+s.ContactY*s.ContactY > c.MaxContact*c.MaxContact {
59		return errors.New(ErrShotRange.Error() + ": contact offset must be within " +
60			strconv.FormatInt(c.MaxContact, 10) + " milli-radii of the centre")
61	}
62	if s.Power < 0 || s.Power > 1000 {
63		return errors.New(ErrShotRange.Error() + ": power must be within 0..1000")
64	}
65	return nil
66}
67
68// WithMishit completes a taker's choices with a mishit seed.
69func (s ShotInput) WithMishit(m [24]byte) ShotParams {
70	return ShotParams{AimX: s.AimX, AimY: s.AimY, ContactX: s.ContactX, ContactY: s.ContactY, Power: s.Power, Mishit: m}
71}
72
73// Input returns the taker's five choices.
74func (s ShotParams) Input() ShotInput {
75	return ShotInput{AimX: s.AimX, AimY: s.AimY, ContactX: s.ContactX, ContactY: s.ContactY, Power: s.Power}
76}
77
78func (s ShotInput) String() string {
79	return "aim=(" + strconv.FormatInt(s.AimX, 10) + "," + strconv.FormatInt(s.AimY, 10) + ")mm contact=(" +
80		strconv.FormatInt(s.ContactX, 10) + "," + strconv.FormatInt(s.ContactY, 10) + ")mR power=" +
81		strconv.FormatInt(s.Power, 10) + "‰"
82}
83
84func (p KeeperPlan) String() string {
85	return "plan=(" + strconv.Itoa(int(p.Direction)) + "," + strconv.Itoa(int(p.Speed)) + "," +
86		strconv.Itoa(int(p.Jump)) + "," + strconv.Itoa(int(p.Reaction)) + ")"
87}