adapter.gno
3.09 Kb · 90 lines
1package physics
2
3import "gno.land/p/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/penalty/v0"
4
5// ParamsOf converts a game's constants from the realm's integer units (mm,
6// mm/s, ms, per-mille, milli-radii) to the engine's. The defaults convert to
7// DefaultParams exactly: each division is correctly rounded, so 2424/1000 is
8// the same double as the browser's literal 2.424.
9func ParamsOf(c penalty.Config) Params {
10 return Params{
11 GoalHalfWidth: float64(c.GoalWidth) / 2000,
12 GoalHeight: float64(c.GoalHeight) / 1000,
13 KeeperScale: float64(c.KeeperScale) / 1000,
14 ReactionMin: float64(c.ReactionMin) / 1000,
15 ReactionMax: float64(c.ReactionMax) / 1000,
16 StarShare: float64(c.StarShare) / 1000,
17 ReadShare: float64(c.ReadShare) / 1000,
18 DiveMin: float64(c.DiveMin) / 1000,
19 DiveMax: float64(c.DiveMax) / 1000,
20 JumpMin: float64(c.JumpMin) / 1000,
21 JumpMax: float64(c.JumpMax) / 1000,
22 BallMinSpeed: float64(c.BallMinSpeed) / 1000,
23 BallMaxSpeed: float64(c.BallMaxSpeed) / 1000,
24 FuzzBase: float64(c.FuzzBase) / 1000,
25 FuzzPower: float64(c.FuzzPower) / 1000,
26 MaxContact: float64(c.MaxContact) / 1000,
27 }
28}
29
30// ShotOf converts the taker's ten-input half (integer units plus the mishit
31// seed) to the engine's units, as the web game does: each value / 1000.
32func ShotOf(s penalty.ShotParams) Shot {
33 return Shot{
34 AimX: float64(s.AimX) / 1000,
35 AimY: float64(s.AimY) / 1000,
36 ContactX: float64(s.ContactX) / 1000,
37 ContactY: float64(s.ContactY) / 1000,
38 Power: float64(s.Power) / 1000,
39 Mishit: s.Mishit,
40 HasMishit: true,
41 }
42}
43
44// SimulateShot is the realm's outcome function on this engine: the taker's
45// six inputs and the keeper's four, under a game's constants.
46func SimulateShot(shot penalty.ShotParams, plan penalty.KeeperPlan, cfg penalty.Config) penalty.Result {
47 prm := ParamsOf(cfg)
48 pl := DecodePlan([4]uint16{plan.Direction, plan.Speed, plan.Jump, plan.Reaction}, prm)
49 r := Simulate(ShotOf(shot), pl, prm, Options{})
50 return ResultOf(r, pl)
51}
52
53// ResultOf summarises a decided kick in the realm's integer units.
54func ResultOf(r Result, pl Plan) penalty.Result {
55 out := penalty.Result{
56 BallSpeed: int64(jsRound(r.Launch.Speed * 1000)),
57 MishitX: int64(jsRound(r.Launch.FuzzX * 1000)),
58 MishitY: int64(jsRound(r.Launch.FuzzY * 1000)),
59 }
60 switch r.Outcome {
61 case Goal:
62 out.Outcome = penalty.OutcomeGoal
63 case Save:
64 out.Outcome = penalty.OutcomeSave
65 case Miss:
66 out.Outcome = penalty.OutcomeMiss
67 case Post:
68 out.Outcome = penalty.OutcomePost
69 }
70 switch pl.Mode {
71 case ModeStar:
72 out.Keeper = penalty.ModeStar
73 case ModeRead:
74 out.Keeper = penalty.ModeRead
75 default:
76 out.Keeper = penalty.ModeDive
77 }
78 // Where the ball reached the goal line, or failing that where it was
79 // when the kick was decided (kept out before the line).
80 if r.LineCross {
81 out.X = int64(jsRound(r.LineX * 1000))
82 out.Y = int64(jsRound(r.LineY * 1000))
83 out.ArrivalMS = int64(jsRound(r.LineT * 1000))
84 } else {
85 out.X = int64(jsRound(r.EndX * 1000))
86 out.Y = int64(jsRound(r.EndY * 1000))
87 out.ArrivalMS = int64(jsRound(r.DecidedAt * 1000))
88 }
89 return out
90}