]> git.scottworley.com Git - planeteer/blobdiff - planeteer.go
Implement Eden buying
[planeteer] / planeteer.go
index 1de46879faaad85b3d4a64c93af0cc0212ee61d2..40d19dd700c6b9dc4187ed32869c35555f220216 100644 (file)
@@ -32,7 +32,7 @@ var start = flag.String("start", "",
 var flight_plan_string = flag.String("flight_plan", "",
        "Your hidey-holes for the day, comma-separated.")
 
-var end = flag.String("end", "",
+var end_string = flag.String("end", "",
        "A comma-separated list of acceptable ending planets.")
 
 var planet_data_file = flag.String("planet_data_file", "planet-data",
@@ -60,18 +60,29 @@ var visit_string = flag.String("visit", "",
 
 func visit() []string {
        if *visit_string == "" {
-               return []string{}
+               return nil
        }
        return strings.Split(*visit_string, ",")
 }
 
 func flight_plan() []string {
        if *flight_plan_string == "" {
-               return []string{}
+               return nil
        }
        return strings.Split(*flight_plan_string, ",")
 }
 
+func end() map[string]bool {
+       if *end_string == "" {
+               return nil
+       }
+       m := make(map[string]bool)
+       for _, p := range strings.Split(*end_string, ",") {
+               m[p] = true
+       }
+       return m
+}
+
 type Commodity struct {
        BasePrice int
        CanSell   bool
@@ -267,7 +278,9 @@ func FillCellByArriving(data planet_data, dims []int, table []State, addr []int)
        if addr[Fuel]+2 < dims[Fuel] {
                other[Fuel] = addr[Fuel] + 2
                for other[Location] = 0; other[Location] < dims[Location]; other[Location]++ {
-                       UpdateCell(table, my_index, EncodeIndex(dims, other), 0)
+                       if data.Planets[data.i2p[addr[Location]]].BeaconOn {
+                               UpdateCell(table, my_index, EncodeIndex(dims, other), 0)
+                       }
                }
                other[Location] = addr[Location]
                other[Fuel] = addr[Fuel]
@@ -276,23 +289,28 @@ func FillCellByArriving(data planet_data, dims []int, table []State, addr []int)
        /* Travel here via a hidey hole */
        if addr[Fuel]+1 < dims[Fuel] {
                hole_index := (dims[Fuel] - 1) - (addr[Fuel] + 1)
-               if hole_index < len(flight_plan()) {
+               if hole_index < len(flight_plan()) && addr[Location] == data.p2i[flight_plan()[hole_index]] {
                        other[Fuel] = addr[Fuel] + 1
-                       other[Location] = data.p2i[flight_plan()[hole_index]]
-                       UpdateCell(table, my_index, EncodeIndex(dims, other), 0)
+                       for other[Location] = 0; other[Location] < dims[Location]; other[Location]++ {
+                               UpdateCell(table, my_index, EncodeIndex(dims, other), 0)
+                       }
                        other[Location] = addr[Location]
                        other[Fuel] = addr[Fuel]
                }
        }
 
        /* Travel here via Eden Warp Unit */
-       for other[Edens] = addr[Edens] + 1; other[Edens] < dims[Edens]; other[Edens]++ {
-               for other[Location] = 0; other[Location] < dims[Location]; other[Location]++ {
-                       UpdateCell(table, my_index, EncodeIndex(dims, other), 0)
+       if addr[Edens]+1 < dims[Edens] {
+               _, available := data.Planets[data.i2p[addr[Location]]].RelativePrices["Eden Warp Units"]
+               if !available {
+                       other[Edens] = addr[Edens] + 1
+                       for other[Location] = 0; other[Location] < dims[Location]; other[Location]++ {
+                               UpdateCell(table, my_index, EncodeIndex(dims, other), 0)
+                       }
+                       other[Location] = addr[Location]
+                       other[Edens] = addr[Edens]
                }
        }
-       other[Location] = addr[Location]
-       other[Edens] = addr[Edens]
 }
 
 func FillCellBySelling(data planet_data, dims []int, table []State, addr []int) {
@@ -354,21 +372,26 @@ func FillCellByBuying(data planet_data, dims []int, table []State, addr []int) {
        quantity := *hold - (addr[UnusedCargo] + addr[Cloaks] + addr[Edens])
        total_price := quantity * absolute_price
        other[Hold] = 0
+       other[UnusedCargo] = 0
        UpdateCell(table, my_index, EncodeIndex(dims, other), -total_price)
+       other[UnusedCargo] = addr[UnusedCargo]
+       other[Hold] = addr[Hold]
 }
 
 func FillCellByMisc(data planet_data, dims []int, table []State, addr []int) {
        my_index := EncodeIndex(dims, addr)
        other := make([]int, NumDimensions)
        copy(other, addr)
-       /* Buy Eden warp units */
+
        /* Buy a Device of Cloaking */
        if addr[Cloaks] == 1 && addr[UnusedCargo] < dims[UnusedCargo]-1 {
                relative_price, available := data.Planets[data.i2p[addr[Location]]].RelativePrices["Device Of Cloakings"]
                if available {
                        absolute_price := int(float64(data.Commodities["Device Of Cloakings"].BasePrice) * float64(relative_price) / 100.0)
                        other[Cloaks] = 0
-                       other[UnusedCargo] = addr[UnusedCargo] + 1
+                       if other[Hold] != 0 {
+                               other[UnusedCargo] = addr[UnusedCargo] + 1
+                       }
                        UpdateCell(table, my_index, EncodeIndex(dims, other), -absolute_price)
                        other[UnusedCargo] = addr[UnusedCargo]
                        other[Cloaks] = addr[Cloaks]
@@ -380,6 +403,32 @@ func FillCellByMisc(data planet_data, dims []int, table []State, addr []int) {
        /* Visit this planet */
 }
 
+func FillCellByBuyingEdens(data planet_data, dims []int, table []State, addr []int) {
+       my_index := EncodeIndex(dims, addr)
+       other := make([]int, NumDimensions)
+       copy(other, addr)
+
+       /* Buy Eden warp units */
+       eden_limit := data.Commodities["Eden Warp Units"].Limit
+       if addr[Edens] > 0 && addr[Edens] <= eden_limit {
+               relative_price, available := data.Planets[data.i2p[addr[Location]]].RelativePrices["Eden Warp Units"]
+               if available {
+                       absolute_price := int(float64(data.Commodities["Eden Warp Units"].BasePrice) * float64(relative_price) / 100.0)
+                       for quantity := addr[Edens]; quantity > 0; quantity-- {
+                               other[Edens] = addr[Edens] - quantity
+                               if addr[Hold] != 0 {
+                                       other[UnusedCargo] = addr[UnusedCargo] + quantity
+                               }
+                               if other[UnusedCargo] < dims[UnusedCargo] {
+                                       UpdateCell(table, my_index, EncodeIndex(dims, other), -absolute_price * quantity)
+                               }
+                       }
+                       other[Edens] = addr[Edens]
+                       other[UnusedCargo] = addr[UnusedCargo]
+               }
+       }
+}
+
 func FillStateTable2Iteration(data planet_data, dims []int, table []State,
 addr []int, f func(planet_data, []int, []State, []int)) {
        /* TODO: Justify the safety of the combination of this dimension
@@ -400,11 +449,7 @@ addr []int, f func(planet_data, []int, []State, []int)) {
 }
 
 func FillStateTable2(data planet_data, dims []int, table []State,
-fuel_remaining, edens_remaining int, planet string, barrier chan<- bool) {
-       addr := make([]int, len(dims))
-       addr[Edens] = edens_remaining
-       addr[Fuel] = fuel_remaining
-       addr[Location] = data.p2i[planet]
+addr []int, barrier chan<- bool) {
        FillStateTable2Iteration(data, dims, table, addr, FillCellByArriving)
        FillStateTable2Iteration(data, dims, table, addr, FillCellBySelling)
        FillStateTable2Iteration(data, dims, table, addr, FillCellByBuying)
@@ -436,9 +481,13 @@ func FillStateTable1(data planet_data, dims []int, table []State) {
        work_done := 0.0
        for fuel_remaining := *fuel; fuel_remaining >= 0; fuel_remaining-- {
                for edens_remaining := eden_capacity; edens_remaining >= 0; edens_remaining-- {
+                       /* Do the brunt of the work */
                        for planet := range data.Planets {
-                               go FillStateTable2(data, dims, table, fuel_remaining,
-                                       edens_remaining, planet, barrier)
+                               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
@@ -446,6 +495,15 @@ func FillStateTable1(data planet_data, dims []int, table []State) {
                        work_done++
                        print(fmt.Sprintf("\r%3.0f%%", 100*work_done/work_units))
                }
+               /* Make an Eden-buying pass (uphill) */
+               addr := make([]int, len(dims))
+               addr[Fuel] = fuel_remaining
+               for addr[Edens] = 0; addr[Edens] <= eden_capacity; addr[Edens]++ {
+                       for planet := range data.Planets {
+                               addr[Location] = data.p2i[planet]
+                               FillStateTable2Iteration(data, dims, table, addr, FillCellByBuyingEdens)
+                       }
+               }
        }
        print("\n")
 }
@@ -461,10 +519,12 @@ func FindBestState(data planet_data, dims []int, table []State) int {
        max_index := -1
        max_value := 0
        for addr[Location] = 0; addr[Location] < dims[Location]; addr[Location]++ {
-               index := EncodeIndex(dims, addr)
-               if table[index].value > max_value {
-                       max_value = table[index].value
-                       max_index = index
+               if len(end()) == 0 || end()[data.i2p[addr[Location]]] {
+                       index := EncodeIndex(dims, addr)
+                       if table[index].value > max_value {
+                               max_value = table[index].value
+                               max_index = index
+                       }
                }
        }
        return max_index
@@ -484,33 +544,42 @@ func Commas(n int) (s string) {
 
 func DescribePath(data planet_data, dims []int, table []State, start int) (description []string) {
        for index := start; index > 0 && table[index].from > 0; index = table[index].from {
-               line := fmt.Sprintf("%13v", Commas(table[index].value))
+               var line string
                addr := DecodeIndex(dims, index)
                prev := DecodeIndex(dims, table[index].from)
-               if addr[Location] != prev[Location] {
+               if addr[Fuel] != prev[Fuel] {
                        from := data.i2p[prev[Location]]
                        to := data.i2p[addr[Location]]
-                       if addr[Fuel] != prev[Fuel] {
-                               line += fmt.Sprintf(" Jump from %v to %v (%v reactor units)", from, to, prev[Fuel]-addr[Fuel])
-                       } else if addr[Edens] != prev[Edens] {
-                               line += fmt.Sprintf(" Eden warp from %v to %v", from, to)
-                       } else {
-                               panic("Traveling without fuel?")
-                       }
+                       line += fmt.Sprintf("Jump from %v to %v (%v reactor units)", from, to, prev[Fuel]-addr[Fuel])
+               }
+               if addr[Edens] == prev[Edens] - 1 {
+                       from := data.i2p[prev[Location]]
+                       to := data.i2p[addr[Location]]
+                       line += fmt.Sprintf("Eden warp from %v to %v", from, to)
                }
                if addr[Hold] != prev[Hold] {
                        if addr[Hold] == 0 {
                                quantity := *hold - (prev[UnusedCargo] + prev[Edens] + prev[Cloaks])
-                               line += fmt.Sprintf(" Sell %v %v", quantity, data.i2c[prev[Hold]])
+                               line += fmt.Sprintf("Sell %v %v", quantity, data.i2c[prev[Hold]])
                        } else if prev[Hold] == 0 {
                                quantity := *hold - (addr[UnusedCargo] + addr[Edens] + addr[Cloaks])
-                               line += fmt.Sprintf(" Buy %v %v", quantity, data.i2c[addr[Hold]])
+                               line += fmt.Sprintf("Buy %v %v", quantity, data.i2c[addr[Hold]])
                        } else {
                                panic("Switched cargo?")
                        }
 
                }
-               description = append(description, line)
+               if addr[Cloaks] == 1 && prev[Cloaks] == 0 {
+                       // TODO: Dump cloaks, convert from cargo?
+                       line += "Buy a Cloak"
+               }
+               if addr[Edens] > prev[Edens] {
+                       line += fmt.Sprint("Buy ", addr[Edens] - prev[Edens], " Eden Warp Units")
+               }
+               if line == "" {
+                       line = fmt.Sprint(prev, " -> ", addr)
+               }
+               description = append(description, fmt.Sprintf("%13v ", Commas(table[index].value)) + line)
        }
        return
 }
@@ -551,8 +620,6 @@ func main() {
        if best == -1 {
                print("Cannot acheive success criteria\n")
        } else {
-               fmt.Printf("Best state: %v (%v) with $%v\n",
-                       best, DecodeIndex(dims, best), Commas(table[best].value))
                description := DescribePath(data, dims, table, best)
                for i := len(description) - 1; i >= 0; i-- {
                        fmt.Println(description[i])