-/* Filling the state table is a set of nested for loops NumDimensions deep.
- * We split this into two procedures: 1 and 2. #1 is the outer, slowest-
- * changing indexes. #1 fires off many calls to #2 that run in parallel.
- * The order of the nesting of the dimensions, the order of iteration within
- * each dimension, and where the 1 / 2 split is placed are carefully chosen
- * to make this arrangement safe.
- *
- * Outermost two layers: Go from high-energy states (lots of fuel, edens) to
- * low-energy state. These must be processed sequentially and in this order
- * because you travel through high-energy states to get to the low-energy
- * states.
- *
- * Third layer: Planet. This is a good layer to parallelize on. There's
- * high enough cardinality that we don't have to mess with parallelizing
- * multiple layers for good utilization (on 2011 machines). Each thread
- * works on one planet's states and need not synchronize with peer threads.
- */
-func FillStateTable1(data planet_data, dims []int, table []State) {
- barrier := make(chan bool, len(data.Planets))
- eden_capacity := data.Commodities["Eden Warp Units"].Limit
- work_units := (float64(*fuel) + 1) * (float64(eden_capacity) + 1)
- work_done := 0.0
- for fuel_remaining := *fuel; fuel_remaining >= 0; fuel_remaining-- {
- /* Make an Eden-buying pass (Eden vendors' energy gradient
- * along the Edens dimension runs backwards) */
- for edens_remaining := 0; edens_remaining <= eden_capacity; edens_remaining++ {
- for planet := range data.Planets {
- if _, available := data.Planets[planet].RelativePrices["Eden Warp Units"]; available {
- addr := make([]int, len(dims))
- addr[Edens] = edens_remaining
- addr[Fuel] = fuel_remaining
- addr[Location] = data.p2i[planet]
- FillStateTable2(data, dims, table, addr, nil)
- }
- }
- }
- for edens_remaining := eden_capacity; edens_remaining >= 0; edens_remaining-- {
- /* Do the brunt of the work */
- for planet := range data.Planets {
- addr := make([]int, len(dims))
- addr[Edens] = edens_remaining
- addr[Fuel] = fuel_remaining
- addr[Location] = data.p2i[planet]
- go FillStateTable2(data, dims, table, addr, barrier)
- }
- for _ = range data.Planets {
- <-barrier
- }
- work_done++
- print(fmt.Sprintf("\r%3.0f%%", 100*work_done/work_units))
- }