package sim import ( "crypto/sha256" "encoding/binary" "sort" ) // Hash returns a digest of the complete simulation state. Two runs from the // same seed and inputs must produce identical hashes. func (s *State) Hash() [32]byte { h := sha256.New() w := func(vs ...int64) { var b [8]byte for _, v := range vs { binary.LittleEndian.PutUint64(b[:], uint64(v)) h.Write(b[:]) } } w(s.Day, int64(len(s.Asteroids))) for i := range s.Asteroids { a := &s.Asteroids[i] w(a.ID) for _, o := range a.Ore { w(o) } } w(int64(len(s.Ships))) for _, sh := range s.Ships { alive := int64(0) if sh.Alive { alive = 1 } w(sh.ID, sh.Owner, alive, int64(sh.Pos.X), int64(sh.Pos.Y), int64(sh.Pos.Z), int64(sh.Vel.X), int64(sh.Vel.Y), int64(sh.Vel.Z), int64(sh.Fuel), sh.Earned, int64(sh.Throttle), int64(sh.Azimuth), int64(sh.Pitch), sh.Target) for _, c := range sh.Cargo { w(c) } h.Write(sh.CPU.MarshalState()) } owners := make([]int64, 0, len(s.Credits)) for o := range s.Credits { owners = append(owners, o) } sort.Slice(owners, func(i, j int) bool { return owners[i] < owners[j] }) for _, o := range owners { w(o, s.Credits[o]) } for _, v := range s.Market.Supply { w(v) } var out [32]byte copy(out[:], h.Sum(nil)) return out }