init
This commit is contained in:
+150
@@ -0,0 +1,150 @@
|
||||
// Package sim is the deterministic core: given a State, the day's inputs and
|
||||
// a Config it advances the world by one day. It performs no I/O.
|
||||
package sim
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"wh/config"
|
||||
"wh/fixed"
|
||||
"wh/market"
|
||||
"wh/vm"
|
||||
"wh/world"
|
||||
)
|
||||
|
||||
// Hull describes the physical properties of a ship design.
|
||||
type Hull struct {
|
||||
DryMass int64 // kg
|
||||
FuelCap int64 // kg
|
||||
CargoCap int64 // kg
|
||||
Thrust int64 // newtons at full throttle
|
||||
ExhaustVel int64 // m/s
|
||||
MineRate int64 // kg mined per tick
|
||||
}
|
||||
|
||||
// CommandShip is the only hull for now.
|
||||
var CommandShip = Hull{
|
||||
DryMass: 8000,
|
||||
FuelCap: 4000,
|
||||
CargoCap: 6000,
|
||||
Thrust: 6000,
|
||||
ExhaustVel: 30000,
|
||||
MineRate: 10,
|
||||
}
|
||||
|
||||
// Docking / mining limits.
|
||||
const (
|
||||
MineRangeKm = 5 // max distance to an asteroid for mining
|
||||
DockRangeKm = 20 // max distance to the station for selling
|
||||
MaxRelSpeedM = 100 // max relative speed (m/s) for mining or docking
|
||||
StarRadiusKm = 200_000
|
||||
)
|
||||
|
||||
type Ship struct {
|
||||
ID int64
|
||||
Owner int64
|
||||
Hull Hull
|
||||
Pos fixed.Vec
|
||||
Vel fixed.Vec
|
||||
Fuel fixed.F
|
||||
Cargo [world.NumOre]int64
|
||||
CPU *vm.CPU
|
||||
Alive bool
|
||||
Earned int64 // credits earned so far
|
||||
|
||||
// Peripheral state.
|
||||
Throttle int32
|
||||
Azimuth int32
|
||||
Pitch int32
|
||||
Target int64
|
||||
Mining bool
|
||||
UplinkNew bool
|
||||
UplinkLen int32
|
||||
MathX int32
|
||||
MathY int32
|
||||
MathZ int32
|
||||
}
|
||||
|
||||
func (s *Ship) CargoTotal() int64 {
|
||||
var t int64
|
||||
for _, v := range s.Cargo {
|
||||
t += v
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (s *Ship) Mass() fixed.F {
|
||||
return fixed.FromInt(s.Hull.DryMass+s.CargoTotal()) + s.Fuel
|
||||
}
|
||||
|
||||
// State is everything that persists between daily runs.
|
||||
type State struct {
|
||||
Day int64
|
||||
Asteroids []world.Asteroid // sorted by ID
|
||||
Station world.Station
|
||||
Ships []*Ship // sorted by ID
|
||||
Credits map[int64]int64
|
||||
Market market.Market
|
||||
}
|
||||
|
||||
// NewState builds the initial world from the config seed.
|
||||
func NewState(cfg config.Config) *State {
|
||||
asts, st := world.Generate(cfg)
|
||||
return &State{
|
||||
Asteroids: asts,
|
||||
Station: st,
|
||||
Credits: map[int64]int64{},
|
||||
Market: market.New(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) asteroid(id int64) *world.Asteroid {
|
||||
// Asteroids are numbered 1..N in slice order.
|
||||
if id >= 1 && id <= int64(len(s.Asteroids)) {
|
||||
return &s.Asteroids[id-1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Launch describes a ship entering the belt at the start of a day.
|
||||
type Launch struct {
|
||||
ShipID int64
|
||||
Owner int64
|
||||
Program []byte
|
||||
}
|
||||
|
||||
// Uplink is a message delivered to a ship's comm buffer at the start of a day.
|
||||
type Uplink struct {
|
||||
ShipID int64
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// DayInput is everything external the simulation consumes for one day.
|
||||
type DayInput struct {
|
||||
Launches []Launch // processed in slice order (must be deterministic)
|
||||
Uplinks []Uplink
|
||||
}
|
||||
|
||||
// Downlink is the content of a ship's transmit buffer at the end of the day.
|
||||
type Downlink struct {
|
||||
ShipID int64
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
Tick int
|
||||
ShipID int64
|
||||
Kind string
|
||||
Detail string
|
||||
}
|
||||
|
||||
type DayResult struct {
|
||||
Day int64
|
||||
Downlinks []Downlink
|
||||
Events []Event
|
||||
Hash [32]byte
|
||||
}
|
||||
|
||||
func (e Event) String() string {
|
||||
return fmt.Sprintf("t%04d ship %d %s %s", e.Tick, e.ShipID, e.Kind, e.Detail)
|
||||
}
|
||||
Reference in New Issue
Block a user