This commit is contained in:
root
2026-09-19 20:21:47 +02:00
commit 0798933b05
62 changed files with 7658 additions and 0 deletions
+150
View File
@@ -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)
}