diff --git a/README.md b/README.md
index 24f3224..3ae99f8 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
- [Factory automation](#factory-automation)
- [Auto mining script V3](#auto-mining-script-v3)
- [Example miner](#example-miner)
-- [Museum combiner v4](#museum-combiner-v4)
+- [Museum combiner v5](#museum-combiner-v5)
- [Auto Adventure](#auto-adventure)
- [Adventure Map](#adventure-map)
- [Timed Task Looping](#timed-task-looping)
@@ -124,87 +124,33 @@ This script is very similar to my other autominer: It mines all layers across al
5VVNT8MwDP0t5MCFUjXj4zDBBcENThzphNLU7aK1cZWk6iq0/46SDq3QdGoHNy7WVsfv2X5O/EE0V6IymizfPgjjRqC0v0lcR1EEBXJWhAliEWowccJRasOkcd5rZxO9xrpI3wvE6scB6mxEAhKrDklIMwp0ZVjSsTIlzLoEI7gN8H7r4eXH8LyOEtMfjkWcdbl+s75gejEI7ZXat7bspBQSQpvIxIRtUJaDBCV4mKNBL9utn005NglNwVpQB/5U5FP46XbSqXainnT7l2rS7S/lmD4KB/egwy75vjwimypQF8uxrJgSGuUvC1+c3XuZh5xT7x9t/1Sv9r/q5S98pl6+xN1ra0BJptqDNO6Gr5l+tndeezluRpiGYPPLHX1l6d0Jb+xitDNTsOoooguDjQwbIVNsQqGxAulN79r2bd9pSr863TBhMsVKmDM8vuG1Nut1067QDrC3Usd6emSl7ofp/PyEYlcB4ShT8W3Hz8cQZVUXGhxCwzZQVyQgNiz8OiFtA5fkMXoNn7asrAp4EdItpIrxDcutkwQkqdMcDFle0oDUGh72f42qYbfafQI=
```
-## Museum combiner v4
-**v4.7**
+## Museum combiner v5
+**v5.1**
-This package combines museum powerstones, *really* fast. It is very close to
-the theoretical maximum speed. On my machine, it can upgrade a stone 11 tiers
-in 1.25 seconds, and do the entire equipped grid in ~2.5 minutes.
+This package combines museum powerstones. It is definitely faster than manually doing this. This "update" was made purely so there was a working combiner script, that didn't rely on the defunct Turbo Exec script.
-**This has been extensively changed for the museum update in 0.11.0.** It is
-also slower than it used to be, because the new, larger inventory has made
-combining slower.
-
-`Import code:`
+`Import Code:`
```
-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
+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
```
-**This requires `turbo exec v2.2` to function, found here: https://github.com/d0sboots/TPT2_scripts/blob/main/common/turbo_exec/README.md**
-
### Details
-To use this, import and enable all the scripts in both this package and `turbo exec`.
+To use this, import and enable all the scripts in this package.
(You can right-click a package to quick-toggle-enable the whole package.)
-Then go to the museum and use W/S to change your *budget*.
+Then go to the museum and press "E" to enable the script.
-The budget is (roughly) how much will get spent to upgrade every stone in the
-grid; it's not what will get used every time. A good rule of thumb is to set
-this to the amount of Museum resources you have, or maybe a little more.
-
-Press "M" to start the combiner. (If you don't like these keys, see [the
-modification instructions](/museum/README.md) for how you can change them.)
+The script will then start iterating through every loadout slot that has a powerstone, upgrading them by 1 tier, up to a maximum set by the shop's Preferences Tier.
+It will not purchase gems above T1, so it is recommended to lock a T1 Universal slot if those are unlocked. Script may require Offshore Market to function without modification.
**Once you understand how the combiner works, switch to the "Artifacts" tab
-while it is running for best speed.** It runs ~11x faster without graphics
+while it is running for best speed.** It runs ~2x faster without graphics
(i.e. when you aren't looking at it) then when you are. You still need to be
in the museum for it to work at all, though.
-
-
-### Features
-
-The combiner tries to upgrade every stone you already have in your equipped
-grid, while respecting the budget. If you want more of a particular type of
-stone, buy it from the basic market, and it will then get upgraded.
-
-Internally, it's allocating 1/100 of the budget for each stone. (So if you
-have very few stones, you can increase the budget a bit.)
-
-The "preferred tier" of the offshore market will be automatically set to the
-best value for your current budget. You can manually change it, but it will
-get overwritten when you run the combiner again.
+(below image is from previous version of combiner)
-Once the combining is done, a countdown timer will show, synced to the
-offshore market's refresh. If you let the combiner sit like this, it will try
-to combine once every hour (or faster, if you are boosting the museum), to
-take advantage of new offers in the offshore market. If you don't want to do
-that, you can press "M" to cancel, or just leave the museum.
-
-Pressing "M" will also cancel a running combine. You can also exit the museum
-or turn off AI, but pressing "M" cleans up the inventory so you don't lose
-stones.
-
-The script gracefully handles running out of resources and offshore market
-rollovers. (In both cases, it continues on as best it can.) It also handles
-not having an offshore market at all (it will just use regular stones).
-
-This script uses worker-name storage to hold the budget even when AI is turned
-off. This will overwrite one of your worker's names (generally, the first one).
-If you want to use a different worker, name one of them `[museum]` and delete/rename
-the old name. You can also manually change the budget by editing the value stored
-here, which can be faster than hitting "W" or "S" a lot of times.
-
-### Why are my gems stuck at T12?
-
-The combiner can only increase tiers 11 levels. This is a time-based
-limitation: Every additional tier requires 3x as many gems, and thus takes 3x
-as long. Beyond 11, it starts taking too long to be practical.
+
-Thus, without offshore market the maximum tier will be 12. With offshore
-market you can go higher, but only when useful gems appear in the market. It
-may take a few cycles for that to happen for all your gems. (You can influence
-the chances by enabling/disabling specific elements in "Preferences" in the
-Shop.)
### Transmuting
@@ -215,13 +161,6 @@ needed.
### Troubleshooting
-The script will show some error messages for common conditions, like a
-bad/missing Turbo Exec installation. Other common issues:
-
-If the script finishes instantly, without ever doing anything (even though you
-have budget set plenty high enough): Is your Museum fully upgraded in the HQ?
-The script requires all the inventory slots to be unlocked.
-
If the script hangs in the middle of combining: Have you bought the "Quick
Combine" skill?
diff --git a/museum/Buy.tpt2 b/museum/Buy.tpt2
deleted file mode 100644
index b973b63..0000000
--- a/museum/Buy.tpt2
+++ /dev/null
@@ -1,160 +0,0 @@
-:import museum_macros
-:name {script(Buy)}
-
-; This isn't included in this subdirectory, but comes from the factory/ directory.
-:import worker_storage_lib
-
-; This script is responsible for buying all stones.
-;
-; It also contains initialization logic for variables. They must be set in the
-; proper order, so that the remain hidden inside our block. This also
-; reads/writes the budget from worker storage, and increment/decrements it
-; if the right keys are pressed.
-
-key.{up}()
-key.{down}()
-
-isopen("museum")
-
-:global string museum_status
-:global string offer_tiers
-:global int museum_tier
-:global int target_tier
-:global int museum_pos
-
-:global int turbo.register
-:global int turbo.cycles
-
-:local string local_elem
-:local int local_buy_amount
-:local double worker_val
-
-; If we're being called from Combine, we're a buyer.
-; Otherwise, if we're being invoked due to key-impulse, but the combiner is
-; currently running, abort. We don't want to change the budget in the middle
-; of things.
-goto(if(\
- contains("{script(Combine)}", impulse()),\
- buy,\
- if(\
- contains("key.{up}|key.{down}", impulse()) &&\
- contains(museum_status, "Combining"),\
- end,\
- init\
- )\
-))
-
-init:
-
-; We do *not* direct-start turbo, because we want to detect broken turbo installs.
-; In particular, if someone has turbo v2.1 still installed, that would break, but in a way
-; that's not easy to programatically detect if we direct-start at this point.
-executesync("TE2.2:start")
-
-; Use worker_storage_lib to find a worker_slot to use for permanent storage.
-#prefix [museum]
-:local int worker_slot
-{worker_storage_lib({prefix})}
-
-; Fetch the budget from the chosen worker. The s2d fallback handles the case
-; where we're allocating new storage, as well.
-worker_val = s2d(sub(worker.name(worker_slot), {len({prefix})}, 99), 1e11)
-
-; Ensure this value is set before we start hiding variables.
-; If we're launching on wakeup(), the other turbo variables will get set
-; in time, but this one might not.
-turbo.cycles = turbo.cycles
-
-; If we're incrementing or decrementing the budget, round it to a fixed
-; amount. This allows users to set it to a specific amount by modifying the
-; worker if they wish, but we'll always get clean set-points when changing
-; via the UI.
-; The lower bound is 1e5, since at that point you can't buy any stones
-; (according to our budget).
-; Also, set budget to -1 if there are no worker slots available. This is our
-; signal to Main, so that it can display an appropriate error message.
-gds({budget}, if(\
- worker_slot == 200,\
- -1.,\
- if(\
- contains(impulse(), "key."),\
- (10. ^ 0.5) ^ max(10., min(560.,\
- round(worker_val // (10. ^ 0.5)) +\
- if(contains(impulse(), "key.{up}"), 1., -1.)\
- )),\
- worker_val\
- )\
-))
-; Save the budget back. There's always enough room for the full value.
-worker.setName(\
- worker_slot - if(worker_slot < 100, 0, 100),\
- "{prefix}" . gdg({budget})\
-)
-
-; Set other variables that need to happen before we close the script block.
-
-; If target_tier is -2, we're being invoked because start was pressed: Either
-; during the timer countdown, or to abort a running combine. Either way,
-; museum_tier needs to be set to 0 to signal no countdown.
-;
-; Otherwise, we leave it unchanged, which will usually mean the countdown remains
-; in effect.
-museum_tier = if(target_tier == -2, 0, museum_tier)
-museum_pos = -1
-
-; Signal Main to wake up. We only want to override target_tier if it's idle,
-; i.e. set to 0 - other situations show that it's in use, and notifying about
-; changing budget is the lowest priority.
-target_tier = if(target_tier == 0, -3, target_tier)
-
-; Time for more ugly math! When we set preferred tier to "pref", we get stones in
-; the range [pref-10, pref], at uniform. We want our best stone to be in that
-; range - the one that we can *just* afford to do +11 levels from. Stones smaller
-; than that fall off at a rate of 1 tier/level, and stones higher fall off at a
-; rate of (18 log 3 - 1), or ~1.63 tiers/level. To maximize the potential of the
-; range, we want the top and bottom of the range to have equally high max_tiers,
-; so max_tier(pref - 10.5) = max_tier(pref + .5). (The halves make the range of
-; size 11, which is needed to properly match the actual integer-sized range.)
-;
-; Substituting gives pref - 10.5 + 11 = log_3(budget / (2000*100/18) / 18^(pref+.5)) + pref+.5,
-; 0 = log_3(budget / K) - (pref + .5) * log_3(18),
-; pref + .5 = log_3(budget / K) / log_3(18),
-; pref = log_18(budget / K) - .5,
-; pref = log_18(budget / (2000*100/18) / 18^.5),
-; pref = log_18(budget / (2000*100/18^.5))
-;
-; The result ends up being intuitive - since the range of stones spans 11 tiers, and
-; our uptiers is also +11 tiers, we want to match the preferred tier to the point where
-; we can just barely afford to buy the stone.
-museum.setPreferredTier(max(1, min(50, d2i((gdg({budget}) / (2000. * 100. / (18. ^ 0.5))) // 18.))))
-
-; We don't care about waiting for the frame break, so manipulate the value
-; directly instead of using "turbo stop".
-; This also gives some (useful) extra turbo frames to our caller, Main.
-turbo.register -= 1
-
-buy:
-; If we're only upgrading 5 or fewer levels, we buy one-at-a-time to avoid
-; overbuying. The number of operations is so small that it won't be slow.
-; This actually maxes out on speed at +7 levels, because at that point we are
-; buying 6 each cycle, which matches the amount the combines use.
-local_buy_amount = max(1, (target_tier - museum_tier - 5) * 3)
-
-; If we're a buyer, use the stone in inventory.
-; Otherwise, buy nothing until we can exit normally.
-local_elem = if(\
- contains("{script(Combine)}", impulse()),\
- element("inventory", 0),\
- ""\
-)
-
-; Because of turbo exec, this script will keep running every cycle, until
-; the frame pause. At that point, it will exit, and we rely on Combine to
-; restart it.
-;
-; Everything is very carefully engineered to make this expression as minimal
-; as possible. It's worth spending extra cycles in set-up in order to remove
-; a single node from this expression.
-museum.buyTier(local_elem, museum_tier, local_buy_amount)
-
-end:
diff --git a/museum/Calculate.tpt2 b/museum/Calculate.tpt2
deleted file mode 100644
index 757fc3e..0000000
--- a/museum/Calculate.tpt2
+++ /dev/null
@@ -1,137 +0,0 @@
-:import museum_macros
-:name {script(Calculate)}
-
-; This script contains (stub) logic for handling key.{start}. This would be part
-; of Main normally, but there can only be 2 impulses per script at the
-; resource-cost-levels we're targeting.
-;
-; The final (bulk) of the logic deals with buying test stones from the
-; offshore market and doing calculations/preparations for the actual
-; combining, which is handled by Combine. This script sets museum_tier
-; and target_tier, which directly drive the combining process.
-
-key.{start}()
-
-:global int museum_tier
-:global int target_tier
-:global int museum_pos
-:global double budget
-:global string offer_tiers
-
-:global int turbo.register
-:global int turbo.cycles
-:global int turbo.cycles.max
-
-:local int offer_idx
-
-; If we're called from key.{start}, then check if the museum
-; is open. If it is, signal Main, otherwise exit. We can't just set a
-; condition on the script, because that would possibly mess up scripts
-; that execute us, on exiting the museum.
-; This will overwrite target_tier if we are currently combining,
-; causing an early exit and leading to main resuming - which is what we
-; want.
-; If we're called from Main, then we need to set museum_tier to 0, because it
-; serves as a signal variable. Main waits on it for BuyOffshore/Combine to be done.
-;
-; It's ugly to fold this up into a single conditional set, but between the fact that
-; we need museum_tier reset on the first instruction, and some of the other conditions
-; involved, it wouldn't be less complicated to do it as two instructions.
-global.int.set(\
- if(contains("key.{start}", impulse()), "target_tier", "museum_tier"),\
- if(contains("key.{start}", impulse()),\
- if(isopen("museum"), -2, target_tier),\
- 0\
- )\
-)
-; If we're called from key.{start}, we're done now. Otherwise, if offer_tiers is
-; the default, calculate it now, but don't bother re-doing work if we don't have to.
-; (This would be easier to do at the top, but there's no room in Main.)
-goto(if(\
- contains("key.{start}", impulse()),\
- end,\
- if(\
- contains(offer_tiers, "0101010101010101-1"),\
- get_offers,\
- skip_offers\
- )\
-))
-
-; This loop calculates the best stone to buy, for each element.
-get_offers:
-
-; Turn an element string into an index. The base version is defined in museum_macros.
-#element_to_index(offset) {element_to_index_base(museum.slotElement(offer_idx), {offset})}
-
-; This monstrousity updates the value of the best tier to use for an element.
-; The element is the element in slot [offer_idx], and we're assessing whether
-; that offer will be an improvement.
-; The base logic relies on the top_tier formula.
-offer_tiers = if(\
- museum.slotElement(offer_idx) == "" ||\
- {top_tier(i2d(museum.slotTier(offer_idx)))} <=\
- {top_tier(s2d(sub(offer_tiers, {element_to_index("")}, 2), -1.))},\
- offer_tiers,\
- sub(offer_tiers, 0, {element_to_index("")}) .\
- sub(i2s(100 + museum.slotTier(offer_idx)), 1, 2) .\
- sub(offer_tiers, {element_to_index(" ")}, 99)\
-)
-; There are max 10 offer slots, numbered 0 through 9. We'll exit after #9.
-offer_idx = offer_idx + 1
-gotoif(get_offers, offer_idx < 10)
-
-skip_offers:
-clear("inventory")
-
-; Load the pre-calculated tier of stone we are buying.
-museum_tier = s2i(sub(\
- offer_tiers,\
- {element_to_index_base(element("loadout", museum_pos), "")},\
- 2\
-), -1)
-
-; Determine "target_tier", the level we are trying to upgrade to. In the
-; best case, we can upgrade 11 levels past the tier of the stones we can
-; buy from the museum. (Which may only be tier 1.)
-target_tier = if(min(tier("loadout", museum_pos), museum_tier) < 0,\
- -1,\
- d2i({top_tier(i2d(museum_tier))})\
-)
-; If tier(museum_pos) < museum_tier, buy one of the target stone.
-; In this case, we're about to move our stone into the 0th slot, and
-; if it's below the base level it will never get combined with, so
-; the combine loop will never end.
-; It's OK to still move it, because there's enough room in the inventory
-; for an extra stone.
-; If we can't afford the stone, or for some other reason are unable to buy
-; it, then we'll also fall through in Combine and move the original stone
-; back when we're done. In this way, we can always avoid eating stones,
-; no matter what happens.
-museum.buyTier(\
- element("loadout", museum_pos),\
- museum_tier,\
- if(tier("loadout", museum_pos) < museum_tier, 1, 0)\
-)
-move("loadout", museum_pos, "inventory")
-
-; Extend turbo for a little longer. There's a race condition where we might
-; run out of cycles and start a new frame, but even if we do that on this
-; line, the new frame will start in time for the Combiners to loop properly,
-; and for the max-setting line in Combine to set the max to its proper value.
-;
-; Otherwise, this ensures that we stay in the current loop until the line
-; in Combine sets cycles.max to its full value.
-; This is a small enough extension so that if we never enter the main loop
-; of Combine, we'll still eventually hit turbo.cycles.max and start a new frame.
-; (I.e. we can't loop indefinitely with this extension alone.)
-turbo.cycles.max = max(turbo.cycles.max, turbo.cycles + 15)
-
-; executesync() is used here to pause us until our child Combine stops us.
-; If we jump from the top, we have to be prepared to loop back to this instruction.
-; in that case, this needs to be a no-op.
-executesync(if(contains("key.{start}", impulse()),\
- "%%museum-nop%%",\
- "{script(Combine)}"\
-))
-
-end:
diff --git a/museum/Combine.tpt2 b/museum/Combine.tpt2
deleted file mode 100644
index fea9bc9..0000000
--- a/museum/Combine.tpt2
+++ /dev/null
@@ -1,133 +0,0 @@
-:import museum_macros
-:name {script(Combine)}
-
-; This script is responsible for actually combining gems.
-;
-; That's true in two senses: It both has the actual call to Combine(), and
-; also the logic immediately surrounding it that runs the combines and checks
-; to see if the loop is done.
-
-:global int museum_tier
-:global int target_tier
-:global int museum_pos
-
-:global int turbo.cycles.max
-:global int turbo.register
-
-:local double end_time
-
-; Stop our parent. If we're invoking ourselves, this is a wasted cycle.
-stop("{script(Calculate)}")
-
-; If we're invoking ourselves, we're a dedicated Combine()er.
-; Otherwise, check to see if we've already reached our goal.
-; If we have, we can exit early, otherwise fall through to the main logic.
-goto(if(\
- contains(impulse(), "{script(Combine)}"),\
- combine,\
- if(tier("inventory", 0) >= target_tier, done, restart_loop)\
-))
-
-; Keep restarting the buy and combine scripts whenever the turbo frame ends.
-; They rely on the 1-cycle-end-of-script-loop property of turbo to function,
-; so we also keep the cycle max up for efficiency.
-restart_loop:
-
-; We start 3 copies of combine, because each combine only combines 3 gems.
-; (As opposed to when you do it manually: then it does 2 combines, once on
-; mousedown and one on mouseup.) 3 is roughly optimal: there are very few
-; positions the inventory can be in that don't support 3 combines between buys,
-; whereas there are significantly more for 4. And combine is one of the most
-; time-expensive operations in the loop, so we don't want to run it pointlessly.
-execute("{script(Combine)}")
-execute("{script(Combine)}")
-execute("{script(Combine)}")
-
-; Start the buyer. By running this after the combiners, we'll always
-; end each cycle with a full inventory, which is important for the check below.
-execute("{script(Buy)}")
-
-; Extend the max duration. There is a possible race condition where we might
-; already be exiting turbo due to being at too many cycles; this is dealt with
-; (and discussed more) in Calculate. We can never be in the race condition
-; internally, because it does not take nearly 200 cycles to get from the
-; "turbo stop" to this line.
-;
-; Normally we would calculate this based on cycles and cycles.max, but here
-; we're just setting it to the maximum that turbo supports. We rely on our own
-; fps-based throttling, instead. If we *do* manage to go the whole 50000 cycles
-; in less than 200ms, there's an interesting timing effect where we will execute
-; TE2.2:stop *exactly* as the next turbo cycle is beginning, leading to a wasted
-; turbo cycle and drastically slower execution.
-turbo.cycles.max = 50000
-
-; Calculate a time to end the loop at. This is 1/5 of a second in the future,
-; so it should reliably be 5 FPS.
-end_time = now() + 10000000. / 5.
-
-; The core condition to wait for. This condition needs to be as minimal as
-; possible, because it is draining CPU time away from the important combine/buy
-; tasks every cycle. (So is the turbo exec machinery, but we can't help that.)
-waituntil(tier("inventory", 0) >= target_tier || now() > end_time)
-
-; If we are done, stop the buyers ASAP, to avoid wasting money. The condition
-; here relies on the condition above for correctness, but is simpler.
-; (Technically there's an edge case if it finishes right at the end, but the
-; number of cycles required means that won't happen.)
-stop(if(now() > end_time, "", "{script(Buy)}"))
-
-; We restart turbo by changing the variable directly, so that there isn't a
-; "turbo start" script taking up cycles. In comparison, we stop turbo with
-; executesync(), because we want to block until the end of the frame, and
-; the end of the frame will naturally clean up the script.
-executesync("TE2.2:stop")
-turbo.register += 1
-
-; Do another loop if we're not done yet.
-; Abort if the 3rd-to-last power stone is not the tier we expect it to be.
-; Because Buy runs after the combines, and won't have been stopped
-; in the case where we're not done yet, we can expect the "fill inventory" buy
-; to have left the final position with our target tier. Checking this way
-; catches both museum rollover and out-of-resources.
-;
-; The reason for checking the 3rd-to-last slot, and not the last slot, has to
-; do with the way combine processing is run: It starts checking for combinable
-; stuff from the first slot down. So it's possible for two base-tier stones to
-; be left in the last two slots, but there can't be *3* in the last 3, because
-; they would be combine-eligible. *Unless* they were just bought. (This isn't
-; quite true, because the combines might be occupied with higher-tier stones,
-; but if we've exausted resources or had rollover, it will rapidly become true.)
-;
-; This also interacts in predictable ways with another couple of common issues:
-; lacking the "quick combine" skill and not having all the inventory slots.
-; If all the slots aren't purchased, this condition will always fail immediately.
-; The symptom will be that the combiners seems to "never do anything."
-; Conversely, without quick combine no progress will ever be made. As soon
-; as a power stone is hit that needs fast leveling, it will get "stuck" there.
-; This is a sure sign of lacking quick-combine.
-;
-; If we are doing a "careful" combine without fill-inventory, it shouldn't take
-; more than 1000 cycles, so this condition won't be a problem.
-gotoif(restart_loop,\
- tier("inventory", 0) < target_tier && tier("inventory", 27) == museum_tier)
-
-done:
-; This is the signal for Main that it should continue.
-museum_tier = -2
-
-; Now that we're done, move the finished stone back to "equipped". This also
-; moves partial/original stones back, if we cancelled via {start}.
-;
-; Even though this happens after signalling, we get one extra cycle as a
-; "delay slot" before we're stopped by Main.
-museum.moveTo("inventory", 0, "loadout", museum_pos)
-
-combine:
-; Because of turbo exec, this script will keep running every cycle, until
-; the frame pause. At that point, it will exit, and we rely on Combine to
-; restart it.
-
-; There's no point in using a variable for the combine limit; halting the
-; combines is handled by the end of turbo. Having the limit be a constant
-; removes one node from the hottest execution path.
-combine(50)
diff --git a/museum/Combining.tpt2 b/museum/Combining.tpt2
deleted file mode 100644
index 0fcc610..0000000
--- a/museum/Combining.tpt2
+++ /dev/null
@@ -1,227 +0,0 @@
-:import museum5_macros
-:name {script(Combining)}
-
-; This isn't included in this subdirectory, but comes from the factory/ directory.
-:import worker_storage_lib
-
-:budget_cap max
-
-wakeup()
-open.museum()
-key.{start}()
-key.{down}()
-key.{up}()
-
-; Because of this condition, it is vital that we never blindly execute this script
-; after a frame-break without checking if we've left the museum!
-isopen("museum")
-
-; Despite being called "Combining" this script does not do the the guts of combining!
-; The other script does that; this script handles secondary combining tasks, including
-; the waitframe() of the combine loop. Thus, this is the script that shows up in the
-; task lisk when combining is happening, and that's why it's named this way.
-;
-; In many ways this is the "main" script of the combiner. It handles all impulses, including
-; wakeup/entry into the museum. It hands off to "Waiting" when we are in the "waiting"
-; states (0 and 8), where we spend our downtime. "Waiting" also handles state 2,
-; the initial calculations for beginning the combine.
-;
-; Both this and "Waiting" usually stop the other script. In normal states, either one or
-; the other will be running but not both.
-
-:global string museum_status
-
-; We do some heinous things to make all our global ints have exactly 10 characters
-; in their names. This combined with the macro makes it easy to initialize them in a loop.
-
- ; 0 for ready, 2 for start_combining (transition state),
- ; 4 for combining, 6 for stop_combining (transition state),
- ; 8 for waiting-for-timer
- ; The states are multiples of 2 to allow for a lookup-table with 2 char data
- ; without needing to multiply, see below.
-{intvar(state_____)}
-{intvar(budgetTier)} ; The tier we are trying to get *all* stones to, based on resources
-{intvar(targetTier)} ; What we are trying to get the current stone to
-{intvar(buyTier___)} ; What tier of stone we buy from the shop
-{intvar(numUpgTier)} ; How many +levels we will upgrade, controlled by user
-{intvar(numLoops__)} ; How many loops Combine has run for, if >0 then we are combining
-
-; When the combiner should next framebreak at
-:global double sleepTime
-; All the tiers of the inventory. Used to check if the combiner is stuck.
-:global string lastInventory
-:local string currInventory
-; Ordered list of slots in the loadout to combine. Stored as 4-character strings,
-; even though each number is 3 long at most, for debuggability. The slots will be
-; grouped by element, so that remaning gems in the inventory can be reused.
-:global string combineSlots
-
-; Our ubiquitous local counter. Always returned to 0 after each loop, so that we
-; don't need a line to reset it ever.
-:local int i
-
-; In *all* circumstances, we want to kill anything existing in "Waiting" (whether it's
-; finished or not), because we want to become the only running script. We may re-execute
-; "Waiting" during this frame, and expect to be killed by it, in turn.
-stop("{script(Waiting)}")
-
-; Construct the jump table for the goto below.
-; Because of the one-pass nature of the editor, we can't make this work with labels
-; directly - they won't fold into the expressions. Instead, we define the targets
-; with macros and have a "debug assert" that is enabled as part of the museum status.
-#j_sw 25
-#j_cm 16
-#jumptable {j_sw}{j_sw}{j_cm}{j_sw}{j_sw}
-#labels_jump (switch . switch . combine . switch . switch)
-
-; Master dispatch goto. This is our second line because our script wears many hats, and
-; we want to decide what we're doing immediately.
-;
-; If we've entered into an error state, don't do any further logic. We switch to "Waiting"
-; to wait until the museum is exited, which will clear the (error) status.
-; If we were executed by our scripts, we are continuing existing logic. We use a jump
-; table to jump directly to the relevant line.
-; Otherwise, we are an impulse and either reset our state completely, or else only update
-; certain variables and continue on. Note that being executed by an external script will
-; also end up in the last bucket, so external scripts will be treated similar to W/S/M
-; which is correct.
-goto(if(\
- {in_error},\
- switch,\
- if(\
- contains(impulse(), "D0S.Museum"),\
- s2i(sub("{jumptable}", state_____, 2), 99),\
- if(\
- contains("wakeup|open.museum", impulse()),\
- reset_variables,\
- set_upg_tier\
- )\
- )\
-))
-
-reset_variables:
-; Temporarily define variables here before the hiding block, if you need to debug them
-;budgetTier = 0
-
-; This starts variable hiding.
-{set_elem("fire")}
-
-; Initialize all our int variables here, inside the variable-hiding block.
-init_var_loop:
-global.int.set(\
- sub("{lua(return intvar_names)}", i, 10),\
- 0\
-)
-i = (i + 10) % {lua(return #intvar_names)}
-gotoif(init_var_loop, i != 0)
-
-sleepTime = 0.
-lastInventory = ""
-;combineSlots = ""
-
-set_upg_tier:
-; Use worker_storage_lib to find a worker_slot to use for permanent storage.
-#prefix [museum5]
-:local int worker_slot
-{worker_storage_lib({prefix})}
-
-; Fetch numUpgTier from the chosen worker. The s2i fallback handles the case
-; where we're allocating new storage, as well. This is limited from 10 through 14;
-; 10 is "instant" (not quite but very fast), while 14 is "very slow". Each additional
-; tier takes 3x as long to run (so a total of 81x between 10 and 14), and every two tiers
-; results in roughly an additional tier of final result (see budgetTier below).
-;
-; 14 is the highest that can be supported practically given the constraint of 30 inventory
-; slots; 10 was chosen for the low end because it's fast enough that smaller isn't needed.
-;
-; This also increases or decreases based on keypress. Nothing should change
-; when we are erroring, or the combiner is running. The index condition finds
-; which up/down keypress was used, returning -1 if not matching. The substring
-; truncates -1 to the start of the string, so we get " 0" for no match and either
-; "01" or "-1" otherwise.
-numUpgTier = max(10, min(14,\
- s2i(sub(worker.name(worker_slot), {len({prefix})}, 99), 13) +\
- if(\
- {in_error} || state_____ == 4,\
- 0,\
- s2i(sub(\
- " 01___-1",\
- index(" key.{up}key.{down}", impulse(), 0),\
- 2\
- ), 0)\
- )\
-))
-
-; Construct our status line. This is a complicated conditional, based on all the bits
-; of state. If this contains the color "red", it is an error and the museum will refuse
-; to function further until it is reset (leave and come back, or F4).
-;
-; All actions have been atomic so far, except for the initial stop.
-; Thus, we can directly check our budget to see how much the user has. We want a bare
-; minimum so that combining will be efficient; this also ensures they know about upgrades.
-{set_status(if(\
- budget() < 2200 - 100,\
- "You need at least 3Kb of RAM.
Buy more servers in the HQ.",\
- if(\
- worker_slot == 200,\
- "No available workers!",\
- [REST]\
- )\
-))}
-
-; Save numUpgTier back. It will always naturally be 2 digits.
-worker.setName(worker_slot - if(worker_slot < 100, 0, 100), "{prefix}" . numUpgTier)
-
-; Advance state if needed by impulse
-; 0->2, 2->2, 4->6, 6->6, 8->0
-state_____ = if(\
- not({in_error}) && contains(impulse(), "key.{start}"),\
- s2i(sub("2 2 6 6 0 ", state_____, 2), 0),\
- state_____\
-)
-
-check_state:
-; The active combining states are handled here. All the other states are handled in
-; "Waiting", so we do a script switch.
-gotoif(switch, state_____ < 4 || state_____ > 6)
-
-combine:
-goto(if(\
- tier("inventory", 0) >= targetTier,\
- finish_combine,\
- if(\
- now() >= sleepTime,\
- framebreak,\
- 0\
- )\
-))
-numLoops__ = 0
-
-finish_combine:
-framebreak:
-currInventory = if(i == 0, "", currInventory) . tier("inventory", i)
-i = (i + 1) % 30
-gotoif(framebreak, i != 0)
-
-{set_status(if(\
- lastInventory == currInventory,\
- "Combining is stalled.
Do you have the quick-combine skill?",\
- [REST]\
-))}
-
-lastInventory = currInventory
-waitframe()
-; We want to maintain a steady 5FPS, so we pause every 200ms. The timer counts ticks
-; that are .1µS each, so that's 2e6 ticks. By advancing relative to the previous time,
-; we smooth over jitters caused by not sleeping exactly on time.
-; However, in case of severe lag spikes or sustained slowdowns (which can happen if
-; the user is looking at the Power Stones tab), we don't want sleepTime to "back up"
-; and then have a run of very short frames. So, in case of lags we skip forward so
-; that our frame always has at least 90ms of scheduled duration.
-sleepTime = max(sleepTime + 2e6, now() + 9e5)
-; TODO: Check for changes here
-
-switch:
-execute("{script(Waiting)}")
-
-end:
diff --git a/museum/Main.tpt2 b/museum/Main.tpt2
deleted file mode 100644
index 22c9b9e..0000000
--- a/museum/Main.tpt2
+++ /dev/null
@@ -1,219 +0,0 @@
-:import museum_macros
-:name {script(Main)}
-
-; The "main" script of the combiner. It starts on wakeup/entry into the
-; museum, and keeps running until the user leaves the museum. This is because
-; it is responsible for maintaining the UI global "museum_status", which
-; both conveys information to the user and also ends a block that
-; hides our internal global variables. When we leave the museum, this is
-; set to "" to blank the display and leave no clutter.
-;
-; This script also runs the outer part of the loop, which updates the
-; position of the combiner. It is well-suited to this, because it is the
-; only script that doesn't get stop()'ed at some point.
-
-:global int max_craft_tier
-:global int museum_pos
-
-:global string museum_status
-:global string offer_tiers
-:global int museum_tier
-:global int target_tier
-
-:global int turbo.cycles
-:global int turbo.register
-
-wakeup()
-open.museum()
-
-isopen("museum")
-
-top:
-; Launch Buy to initialize the global variables in the proper order.
-; We re-do this after every run, because it resets museum_pos for us.
-executesync("{script(Buy)}")
-
-; Two characters per tier. Universal is last. These are initialized to what can
-; be bought from the store.
-; This logically belongs in "Buy", but is moved out of there to make space.
-offer_tiers = "0101010101010101-1"
-
-; Macro-substitution for the museum timer, allows mocking it out easily for
-; testing.
-#timer museum.timer()
-
-; No-offshore-market fix: If we get here with museum_tier == -2 (which is the
-; waiting-to-start state), but the timer is *exactly* 1 hour, this means the user
-; doesn't have the offshore market and is getting the default value. In this case,
-; reset museum tier so that the script stops properly.
-museum_tier = if(\
- museum_tier == -2 && {timer} == 60. * 60.,\
- 0,\
- museum_tier\
-)
-
-; This loop usually runs without turbo, although it can have lingering
-; turbo from other scripts without bad effects. It keeps the status line
-; up-to-date while the museum is not running.
-status_loop:
-; We use target_tier to receive signals from other scripts. 0 means nothing
-; is hapenning, so we always reset to 0 at the top.
-target_tier = 0
-
-; This is a useful sub-expression when displaying numbers in rounded
-; scientific notation. We want to extract the exponent, but for numbers like
-; .9996, we know they'll round up to 1.00 (when rounded to 3 places), so we
-; have to consider them as an exponent higher already.
-; The parameter is to allow for the injection of a constant for constant
-; folding in later expressions.
-#adjusted_exp(x) floor(gdg({budget}) // 10. - (0.9995 // 10. + {x}))
-
-; Stringify the budget in rounded-scientific notation, rounded to 3 digits
-; (2 after the decimal place). This is an awkwardly large expression, but
-; it's really the best we can do with the tools we have.
-; The "2" passed to adjusted_exp subtracts 2 from the exponent, so the
-; overall effect is to multiply by 100 (before rounding).
-#rounded_budget round(gdg({budget}) / (10. ^ {adjusted_exp(2.)})) / 100. .\
- "e". {adjusted_exp(0.)}
-
-; Normally we would take the ceiling of the time remaining, because that's
-; how timers work. (You show 1 second left until the time hits 0.)
-; However, the display timer in the museum uses floor, and we want to match
-; that, so we use floor too.
-; The parameter is a divisor, to make dealing with minutes easier.
-#time_floor(x) floor({timer}/ {x})
-
-; Set the status. There's a lot of cases to this:
-; * Error for no workers available.
-; - We don't have direct visibilty to worker_slot, but Buy will signal the
-; error by setting budget to negative, which will never happen otherwise.
-; * Error for a bad Turbo install. This is disturbingly frequent.
-; * Show our current budget, with green highlighting to prompt that this
-; can be adjusted.
-; * Show a brief help line, also with green highlighting to link the keys
-; to the budget.
-; * If we've pressed {start}, show the Combining message instead. This is
-; important because certain things key off of it. target_tier = -2 is the
-; signal for this.
-;
-; We don't bother doing anything special when the museum isn't open, since
-; we'll handle that at the bottom of the script.
-museum_status = if(\
- gdg({budget}) < 0.,\
- "error=No available workers!",\
- if(\
- turbo.cycles == 0,\
- "error=Turbo exec is not working",\
- "museum=" .\
- {rounded_budget} .\
- " budget
\
-{up}/{down} changes, {start} " .\
- if(\
- museum_tier != -2,\
- "begins",\
- "stops
Waiting " .\
- {time_floor(60.)} . ":" . sub(d2s({time_floor(1.)} % 60. + 100.), 1, 2) .\
- ""\
- )\
- )\
-)
-; The s2i()/sub() expression is a jump-table, where the string values are
-; line numbers.
-; The values that target_tier can have when we get here are 0
-; (if it hasn't been set to anything since it was cleared at the top of
-; status_loop), -2 (set when key.{start} is pressed), and -3 (set when
-; budget is adjusted via key.{up}/key.{down}).
-;
-; -2 finishes the loop. -3 should reset target_tier and update status by
-; jumping two lines back. 0 *could* repeat the same line, except sometimes
-; we have to update status, so we jump one back, to set status.
-; We can't merge the -3 and 0 cases, because setting target_tier over-frequently
-; makes keystrokes flaky.
-;
-; We use a modified jump table when museum_tier is -2, which indicates that
-; we are synced to the refresh timer. In that case, we abort when the timer is
-; 59:59 (meaning the refresh just hapenned), and when start is pressed (-2 for
-; target_tier) we jump back to executing Buy, which will reset museum_tier
-; (and also do other things, which we don't care about) in that case.
-goto(if(\
- isopen("museum"),\
- if(\
- museum_tier == -2 && {timer} >= 59. * 60. + 59.,\
- start_museum,\
- s2i(sub(if(museum_tier == -2, "41 5", "47 5"), target_tier + 3, 1), 99)\
- ),\
- end\
-))
-
-start_museum:
-; Now that we're in the active part of the script, start turbo. We want
-; minimal overhead, so don't execute an extra script, just increment
-; the variable.
-turbo.register += 1
-
-upgrade_loop:
-; Go to the next script to perform the actual upgrade.
-; We run this even when museum_pos is -1, in order to set all the variables
-; properly. Combine will exit immediately in that case, without a frame break,
-; so we will fall down below and set the status correctly within the frame
-; that it starts.
-execute("{script(Calculate)}")
-
-; Combine (which gets run from Calculate) will signal us when it's done.
-; It must be stopped for proper cleanup.
-waituntil(museum_tier == -2)
-stop("{script(Combine)}")
-
-skip:
-museum_pos += 1
-; While running, we have fewer conditions to check, since the errors were
-; already signaled at the top. (There's nothing actually stopping the user
-; from starting the script anyway, but that's on them at that point.)
-;
-; The condition for displaying Combining is reversed, since it's usual
-; here, and if {start} is pressed it means we should exit.
-museum_status = "museum=" .\
- {rounded_budget} .\
- " budget
" .\
- if(\
- target_tier != -2,\
- "Combining... [" . museum_pos . "] {start} stops",\
- "{up}/{down} changes, {start} begins"\
- )
-
-stop_turbo:
-; Most of the time, we do not want to stop turbo. We only want to do it in
-; the specific cases where we'll be ending the loop. So, this duplicates a lot
-; of the logic in the loop below, all for the benefit of saving a line.
-;
-; Note that if we jumped to stop_turbo directly, museum_status can never
-; contain "Combining".
-executesync(if(\
- isopen("museum") && museum_pos < 130 && contains(museum_status, "Combining"),\
- "%%museum-nop%%",\
- "TE2.2:stop"\
-))
-
-; This very complicated gotoif consolidates the ends of lots of loops into
-; one statement.
-; If the museum is closed, fall through to exit the script.
-; If we're through all the positions, or if we're no longer "Combining"
-; (which means {start} was pressed), go to the top to reset our state.
-;
-; Otherwise, continue the loop: Either normally, or via a shortcut if this
-; part of the grid is empty, to avoid executing the sub-scripts.
-gotoif(\
- if(\
- museum_pos < 130 && contains(museum_status, "Combining"),\
- if(tier("loadout", museum_pos) == -1, skip, upgrade_loop),\
- top\
- ),\
- isopen("museum")\
-)
-
-end:
-; Before we exit, blank the status so that there isn't clutter on the screen.
-; This is safe to do in the last slot because turbo shouldn't be running by
-; this point. Even if it is, we're the only ones who set museum_status, so
-; it's still safe.
-museum_status = ""
diff --git a/museum/README.md b/museum/README.md
index 5ee9492..adef0a0 100644
--- a/museum/README.md
+++ b/museum/README.md
@@ -22,6 +22,15 @@ changing them.
## Changelog
+### v5.1 (Now with Threads!)
+
+Update to the bare basics script that actually runs at a reasonable speed. Still much slower than v4.7 was, but faster than manual clicking now.
+
+### v5.0 (Simple Edition)
+
+Not really a version increase, just a very simple script to iterate through all gems and upgrade them.
+MUCH slower than v4.7, but works without Turbo Exec. Pull request was made purely for those that can't make this themselves, but are looking for a museum script.
+
### v4.7
Increased the max cycles of the combiner to 50000, so that it is solely FPS limited,
diff --git a/museum/Waiting.tpt2 b/museum/Waiting.tpt2
deleted file mode 100644
index ae7e214..0000000
--- a/museum/Waiting.tpt2
+++ /dev/null
@@ -1,323 +0,0 @@
-:import museum5_macros
-:name {script(Waiting)}
-
-:budget_cap max
-
-:global int state_____
-:global int buyTier___
-:global int budgetTier
-:global int numLoops__
-:global int targetTier
-:global int numUpgTier
-
-:global string museum_status
-:global string combineSlots
-
-; Cubes needed to upgrade to budgetTier. Temporary variable, can be made global
-; for debugging.
-:local double neededCubes
-
-; Time of next budget calc. Used to avoid recalculating budget too often.
-:local double nextBudget
-
-:local int i
-
-; Construct the jump table for the goto below.
-; Because of the one-pass nature of the editor, we can't make this work with labels
-; directly - they won't fold into the expressions. Instead, we define the targets
-; with macros and have a "debug assert" that is enabled as part of the museum status.
-#j_ui 02
-#j_se 16
-#j_cm 30
-#jumptable {j_ui}{j_se}{j_cm}{j_ui}{j_ui}
-#labels_jump (0 . ui_loop . setup_combine . start_combine . 0 . ui_loop . 0 . ui_loop)
-
-; Master dispatch goto. This is our first line because our script wears many hats, and
-; we want to decide what we're doing immediately. Also, for the combiner to be effecient
-; we want to execute as little extra cruft as possible (it will run millions of times).
-; So, we optimize our ternaries on the assumption that we are combining, first.
-goto(if(\
- contains(impulse(), "Waiting"),\
- loop_inc,\
- if(\
- {in_error},\
- ui_loop,\
- s2i(sub("{jumptable}", state_____, 2), 99)\
- )\
-))
-
-ui_loop:
-; We want this script to be the only running one while we wait.
-; This line is duplicated with start_combine, but it's not worth trying to merge them.
-stop("{script(Combining)}")
-
-budget_start:
-; Looping through all the slots and doing the explicit budget tier calculation is
-; slow. Thus, we do an approximation here that is an intentional underestimate, and
-; then let the loop refine it.
-; Assumptions:
-; * All 135 slots are filled with universal stones (the most expensive)
-; * We get no credit for existing stones (they're all too low to count)
-; (See below for where the initial formula comes from)
-; neededCubes = 135. * 3. ^ numUpgTier * 18. ^ (budgetTier - 1 - numUpgTier) * 20000.
-; neededCubes = 135. * 20000. * 18. ^ (budgetTier - 1) / 6. ^ numUpgTier
-; 6. ^ numUpgTier * neededCubes / (135. * 20000.) = 18. ^ (budgetTier - 1)
-; budgetTier = log(6 ^ numUpgTier * neededCubes / (135. * 20000.), 18.) + 1
-; budgetTier = neededCubes // 18. - (135. * 20000.) // 18. + numUpgTier * (6. // 18.) + 1
-; Replace "neededCubes" with "resources" and floor the result.
-; Subtract 2 because we'll be adding one in the next line, and because the convention
-; for budgetTier within the calculation below is to be one less.
-budgetTier = max(0, d2i(floor(resource("museum.resources") // 18. - ((135. * 20000.) // 18. + 1.) + i2d(numUpgTier) * (6. // 18.))))
-
-budget_outer_loop:
-budgetTier += 1
-
-; Determine budgetTier based on a neededCubes calculation.
-;
-; The user does not explicitly set the tier they want to combine to, nor do they set a
-; "budget" like past scripts. Instead, they set numUpgTier, which says how many +tiers
-; we will combine, and this combined with the current number of cubes (which can now be
-; read) determines the final budgetTier.
-;
-; To determine this, we answer the following question: If we *could* buy stones at
-; tier (budgetTier - numUpgTier) and upgrade them to tier budgetTier (i.e., we assume that
-; they will be available at the needed tier in the offshore market), how much would it
-; cost to do so? We keep incrementing budgetTier until this cost becomes more than our
-; current resources, and then take the previous value, which worked.
-;
-; To calculate the cost, we go over every slot. Wrinkles in the calculation:
-; * If (budgetTier + numUpgTier < 1), we clamp it to 1 and we'll end up upgrading less
-; that the full numUpgTier levels.
-; * If the clamped value is 1, we buy (cheaper) stones from the market instead of the
-; offshore market. (Market costs 1000 vs 2000 base cost from offshore).
-; * For efficiency reasons, budgetTier is actually budgetTier - 1 at this point.
-; We want that value because when calculating powers to get the price of stones,
-; the costs start at T1 but the power needs to start at 0. Because of this,
-; the loop check is offset by one and we have to fix the value after the loop.
-; * Universal stones cost 10x more.
-; * We use the value of the existing stone to offset the cost, since we will be using
-; the pre-existing stone to help pay for and speed up the combining.
-
-budget_inner_loop:
-; Explanation of specific terms in this equation:
-; The first term is the cost savings from a pre-existing stone, which scales
-; with 3^x, but negatively. It is multiplied by 3 to avoid a correction factor
-; of 1 to budgetTier; this is cancelled in the next term.
-; The last term is an if-chain to get the base cost of the gems.
-; There is an odd factor of 1/3 that has been redistributed to avoid adding
-; one to budgetTier, instead absorbing it into constants.
-neededCubes = if(i == 0, 0., neededCubes) +\
- max(0.0, 3.0 - 3. ^ i2d(tier("loadout", i) - budgetTier)) *\
- if(\
- contains(element("loadout", i), "universal"),\
- 20000. / 3.,\
- if(\
- tier("loadout", i) < 0,\
- 0.,\
- if(\
- numUpgTier >= budgetTier,\
- 1000. / 3.,\
- 2000. / 3.\
- )\
- )\
- )
-; The loadout grid is 15x9 = 135
-i = (i + 1) % 135
-; Multi-condition loop. Because ifs early-out, most of the expensive condtions
-; here aren't evaluated for the common case, which is just doing the next iteration.
-;
-; The first special case is if neededCubes is 0. This happens iff the grid is
-; empty, and we let budget_adjust set the tier to 0 in this case. It prevents us
-; from having to iterate through a lot of levels, reducing FPS.
-;
-; The comparison against neededCubes is multiplied by the number of stones we'll
-; be buying, which scales with 3^x, and the tier of stones we're buying, which
-; scales with 18x. These terms doesn't depend on i, so we can
-; factor them out here and only evaluate them once.
-;
-; If we successfully reach T50, we can exit without testing the next tier.
-; Since budget_tier = 49 for that case, we must adjust it up. Otherwise, if
-; we fail due to budget then it is already set correctly.
-goto(if(\
- i != 0,\
- budget_inner_loop,\
- if(\
- neededCubes <= 0.,\
- budget_adjust,\
- if(\
- (3. ^ i2d(min(numUpgTier, budgetTier))) *\
- (18. ^ i2d(max(budgetTier - numUpgTier, 0))) * neededCubes >\
- resource("museum.resources"),\
- budget_done,\
- if(\
- budgetTier >= 49,\
- budget_adjust,\
- budget_outer_loop\
- )\
- )\
- )\
-))
-
-budget_adjust:
-budgetTier = if(neededCubes <= 0., 0, budgetTier + 1)
-
-budget_done:
-; Update the budget every 200ms
-nextBudget = now() + 2000000.
-
-ui_set:
-{set_status([REST])}
-; From observation, stones spawn in the market in the range
-; [preferredTier - 10, preferredTier] inclusive (11 tiers total), uniformly.
-; We will never use a powerstone *higher* than what is needed to get to budgetTier,
-; so we set the preferredTier accordingly.
-museum.setPreferredTier(max(1, budgetTier - numUpgTier))
-waitframe()
-
-; We refresh the UI every frame to display the timer as it changes. (When the
-; museum is boosted, it can change very rapidly.) However, recalculating the budget
-; is expensive, and usually it won't change. (Aside from the user changing tiers,
-; which is handled by killing and restarting this script, it only happens from
-; resource changes, which would be from producers or manual conversion.)
-; So, we only recalculate it at 5FPS.
-goto(if(\
- isopen("museum"),\
- if(\
- now() < nextBudget,\
- ui_set,\
- budget_start\
- ),\
- close_ui\
-))
-
-close_ui:
-museum_status = ""
-goto(99)
-
-; Set to global for debugging of these expressions
-#offscope local
-; The first two letters are enough to uniquely identify every element
-#offvar ("offer_" . sub(museum.slotElement(i), 0, 2))
-
-setup_combine:
-; Initialize the offers. Most elements are always available at tier 1 from the
-; market, but universal *must* be bought from offshore.
-; Because these loops are small (10 elements) and the next loops are bigger,
-; we don't store the tier of the market offer but instead the tier that we will
-; be able to combine to *using* this offer; this is +numUpgTier from the first
-; value.
-;
-; We could potentially fold this into the next expression with careful arranging,
-; but that would rely on the automatic 0-initialization of local variables. Since
-; we want to be able to switch to globals for debugging, we spend the extra lines
-; to initialize explicitly.
-{offscope}.int.set(\
- "offer_" . sub("lielfidanaaiwaeaun", i, 2),\
- if(i == 16, -99, min(budgetTier, 1 + numUpgTier))\
-)
-i = (i + 2) % 18
-gotoif(setup_combine, i != 0)
-
-offshore_loop:
-; Loop over all the offshore market offers to find the limiting offer to use for
-; each element. We can't exceed budgetTier. If we hit a slot with
-; no offer, we will harmlessly set the variable "offer_", so the rest of the
-; expression does not matter.
-{offscope}.int.set(\
- {offvar},\
- max(\
- {offscope}.int.get({offvar}),\
- if(museum.slotTier(i) + numUpgTier > budgetTier, -99, museum.slotTier(i) + numUpgTier)\
- )\
-)
-i = (i + 1) % 10
-gotoif(offshore_loop, i != 0)
-
-; Bucket-sort: We traverse the loadout once, looking for eligible slots, and
-; add them to one of 9 different lists based on element. Then we combine those
-; lists together at the end so that each element is grouped together. Grouping
-; by element lets us reuse gems that remain in the inventory across combines,
-; and precalculating the slots saves us time and effort during the combine, as
-; well as making it easy to compute a (reasonably) accurate completion percentage.
-#slotvar(x) ({x} . sub(element("loadout", i), 0, 2))
-calculate_slots:
-; In the comparison here, we don't need to worry about the case where the tier
-; is -1 because that will also return "" for the element, and thus get appended
-; to the garbage variable "slots_".
-local.string.set({slotvar("slots_")},\
- local.string.get({slotvar("slots_")}) . if(\
- tier("loadout", i) >= {offscope}.int.get({slotvar("offer_")}),\
- "",\
- sub(i . " ", 0, 4)\
- )\
-)
-i = (i + 1) % 135
-gotoif(calculate_slots, i != 0)
-
-combineSlots = ""
-combine_slots:
-combineSlots .= local.string.get("slots_" . sub("lielfidanaaiwaeaun", i, 2))
-i = (i + 2) % 18
-gotoif(combine_slots, i != 0)
-
-goto(99)
-
-start_combine:
-; We kill our parent to avoid copies of it piling up. This takes budget, so we usually don't
-; do it.
-stop("{script(Combining)}")
-
-loop_inc:
-numLoops__ += 1
-
-; This is an incredibly simple unrolled buy-combine loop.
-; I tested other things, such as a loop that dynamically combines as long as there are still
-; buyTier___ stones left to combine, but this performs (much) better: combine() is cheap enough
-; that the overhead from the goto and logic inside that is significant.
-; With 6 combines, some of them end up occaisonally wasted when doing +14 levels. But it is counterbalanced
-; by the speed gain from doing less buys/gotos the rest of the time. Overall, 4/5/6 combines performed
-; similarly for +14 levels, but more combines is faster at +13 and below.
-;
-; The order is inverted from the "natural" order of having the buy first to allow for an
-; important check later on. Because this runs back-to-back so many times, it doesn't
-; actually make a difference in efficiency which comes first.
-combine:
-museum.combine(0)
-museum.combine(0)
-museum.combine(0)
-museum.combine(0)
-museum.combine(0)
-museum.combine(0)
-museum.buyTier({buy_elem}, buyTier___, 30) ; Last is how many, always hardcoded to all
-; Since everything is about speed here, we don't test *anything* except the budget, which is
-; hardcoded. We will run this loop a fixed number of times, and then check the more complicated
-; conditions down below. This means we overshoot on buying stones by a small amount; we can
-; recover some of this cost by re-using them when we're not changing elements.
-gotoif(combine, budget() > 700)
-
-; Create another copy to keep the chain going. It's *vital* that we save budget to get to this
-; line, otherwise we will have a spurious framebreak and the efficiency will tank.
-; If we are finished combining, or if we have spawned too many scripts, exec "Combining" to
-; handle things.
-;
-; We leave a significant buffer in running scripts (we can spawn up to 100 copies but we are
-; only doing 50). The reason for this is complicated; if the user is looking at the
-; "Power Stones" tab while combining then the efficiency will suck. We have checks to alert
-; them about this, however if we do a full 100 loops and the budget is 100 then by the time
-; we do the check for a frame-break, we may have already have spent 1000ms+, i.e. FPS will
-; be <1. This is too laggy, so we cut back a little on loops to test more often, resulting
-; in *slightly* decreased efficiency overall but much less lag for this case.
-;
-; We only have the absolutely necessary checks here: The loop check and the "we're done"
-; check. Everything else we defer to "Combining", to be done once every 50 loops. This is
-; so miniscule in occurence compared to the core combining that everything we do there is
-; basically free.
-finish:
-execute(if(\
- numLoops__ < 50 && tier("inventory", 0) < targetTier,\
- "{script(Waiting)}",\
- "{script(Combining)}"\
-))
-
-; Also for efficiency, it's important that the combine part of the code flows directly
-; into the end of the script. (So it doesn't have to do anything extra after the execute().)
diff --git a/museum/auto_gem.tpt2 b/museum/auto_gem.tpt2
new file mode 100644
index 0000000..dde3e06
--- /dev/null
+++ b/museum/auto_gem.tpt2
@@ -0,0 +1,30 @@
+:name Museum:Auto Gem
+
+:global int MaxGemSlot
+:global int GemSlot
+:global int GemTier
+:global int MaxTier
+:local int NoGem
+
+isopen("museum")
+
+MaxGemSlot = 135
+GemSlot = 0
+GemTier = 0
+MaxTier = museum.preferredTier() + 1
+NoGem = -1
+gotoif(17, tier("loadout", GemSlot) == NoGem)
+gotoif(17, tier("loadout", GemSlot) >= MaxTier)
+museum.moveTo("loadout", GemSlot, "inventory", 0)
+GemTier = tier("inventory", 0)
+executesync("Loops")
+waituntil(tier("inventory", 0) > GemTier)
+stop("Purchase")
+stop("Combine")
+museum.moveTo("inventory", 0, "loadout", GemSlot)
+waitframe()
+clear("inventory")
+GemSlot = GemSlot + 1
+gotoif(20, GemSlot <= MaxGemSlot)
+GemSlot = 0
+goto(6)
\ No newline at end of file
diff --git a/museum/combine.tpt2 b/museum/combine.tpt2
new file mode 100644
index 0000000..72362f1
--- /dev/null
+++ b/museum/combine.tpt2
@@ -0,0 +1,6 @@
+:name Museum:Combine
+
+isopen("museum")
+
+combine(0)
+goto(0)
\ No newline at end of file
diff --git a/museum/loops.tpt2 b/museum/loops.tpt2
new file mode 100644
index 0000000..ee363d0
--- /dev/null
+++ b/museum/loops.tpt2
@@ -0,0 +1,19 @@
+:name Museum:Loops
+
+isopen("museum")
+
+execute("Purchase")
+execute("Purchase")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
+execute("Combine")
\ No newline at end of file
diff --git a/museum/museum5_macros.tpt2 b/museum/museum5_macros.tpt2
deleted file mode 100644
index 8ba8b89..0000000
--- a/museum/museum5_macros.tpt2
+++ /dev/null
@@ -1,114 +0,0 @@
-; Standardized (package) naming across all the scripts
-#script(name) D0S.Museum v5.0:{name}
-
-; Enable for testing assertions, which increase the size of the package.
-; This should be enabled when making modifications, to ensure the jumptable
-; targets are set correctly.
-{lua(museum_assert = true)}
-
-; Keybindings. You can edit these here, or edit them in the scripts directly
-; (but it will be much more error-prone).
-#up w
-#down s
-#start m
-
-; Macro-substitution for the museum timer, allows mocking it out easily for
-; testing. The timer counts in seconds, not ticks.
-#timer museum.timer()
-
-; Name of the buy_elem variable, which begins the script-hiding block.
-#buy_elem_name "mbe*~"
-#buy_elem global.string.get({buy_elem_name})
-#set_elem(x) global.string.set({buy_elem_name}, {x})
-
-#error #fb3
-#in_error contains(museum_status, "color={error}")
-
-{lua(intvar_names = "")}
-#intvar(name) {lua(\
- local name = [[{name}]]\
- if #name ~= 10 then\
- return "! intvar " .. name .. " not length 10!"\
- end\
- intvar_names = intvar_names .. name\
- return ":global int " .. name\
-)}
-
-; Normally we would take the ceiling of the time remaining, because that's
-; how timers work. (You show 1 second left until the time hits 0.)
-; However, the display timer in the museum uses floor, and we want to match
-; that, so we use floor too.
-; The parameter is a divisor, to make dealing with minutes easier.
-#time_floor(x) floor({timer} / {x})
-
-; Descriptions for each tier. We stick the closing parens on, and allow a variable
-; number of spaces after, since they won't be seen due to a linefeed that follows.
-#tier_desc "(" .
-
-; Set the status. There's a lot of moving parts to this:
-; * We have an optional debug-assert to check jumptable correctness. This depends
-; on macros [jumptable] and [labels_jump] that have been set up in each of
-; the scripts.
-; * We take a set of error_conditions as a parameter, which are checked to see
-; if various conditions have gone awry such as lacking execution budget.
-; * Show our current tier, with green highlighting to prompt that this
-; can be adjusted.
-; * Show a brief help line, also with green highlighting to link the keys
-; to the budget.
-; * If we've pressed {start}, show the Combining message instead.
-; * Show the timer if we are waiting.
-;
-; We need to set the status several times in the script, but each time it has a different
-; set of error conditions that are being checked. To handle this, we pass a customizable
-; "if" block, with a literal "[REST]" token that we will lua-substitute with the inner
-; part of the status condition.
-#set_status(error_conditions) {lua(\
- --[[ The outer part of the condition: If there was an error message, preserve it,\
- otherwise close the variable-hiding block and pass to the inner conditions.\
- We also handle debug assertion here. ]]\
- local parts = {}\
- parts[1] = [[museum_status = if({in_error}, museum_status, "" . ]]\
- parts[2] = ")"\
- local ins_point = 2\
- if museum_assert then\
- table.insert(parts, ins_point, [==[if(\
- "{jumptable}" != {labels_jump},\
- "Internal error: Bad constants {jumptable} != " . {labels_jump} . "",]==])\
- ins_point = ins_point + 1\
- table.insert(parts, ins_point, ")")\
- end\
- --[[ The innermost part of the status line, which is in common for all of them.\
- We show how many +tiers we are upgrading, with color highlighting aligned with\
- our key help. There is a lookup table to describe each of the tier amounts, which\
- for implementation simplicity has the parens attached. The final part is determined\
- by the current state.]]\
- local inner_part = ([==[ {error_conditions} ]==]):gsub("%[REST%]", [[\
- if(\
- budgetTier == 0,\
- "museum=Empty loadout!",\
- "museum=+" .\
- numUpgTier . " " .\
- sub("(instant)(fast) (normal) (slow) (glacial)",\
- (numUpgTier - 10) * 9,\
- s2i(sub("_________|96869", numUpgTier, 1), 0)\
- ) .\
- "→T" . budgetTier\
- ) .\
- "
" .\
- "{up}/{down} changes, {start} " .\
- if(\
- state_____ < 2,\
- "begins",\
- if(\
- state_____ >= 4,\
- "stops
Waiting " .\
- {time_floor(60.)} . ":" . sub(d2s({time_floor(1.)} %% 60. + 100.), 1, 2) .\
- "",\
- "stops
Running " .\
- "100%% " .\
- ""\
- )\
- )]])\
- table.insert(parts, ins_point, inner_part)\
- return table.concat(parts)\
-)}
diff --git a/museum/museum_macros.tpt2 b/museum/museum_macros.tpt2
deleted file mode 100644
index 5cd4d2a..0000000
--- a/museum/museum_macros.tpt2
+++ /dev/null
@@ -1,35 +0,0 @@
-; Standardized (package) naming across all the scripts
-#script(name) D0S.Museum v4.7:{name}
-
-; Keybindings. You can edit these here, or edit them in the scripts directly
-; (but it will be much more error-prone).
-#up w
-#down s
-#start m
-
-; Name of the budget variable, which begins the script-hiding block.
-#budget "mb**"
-
-; Turn an element string into an index. For our purpose, all the indexes
-; need to be multiplied by two, so we look for the index of the first two
-; characters of the element.
-; The "offset" string allows us to concatenate on a string and thus add a
-; constant to the result.
-#element_to_index_base(ele, offset) index({offset} . "lielfidanaaiwaeaun", sub({ele}, 0, 2), 0)
-
-; Macro for determining the number of tiers we can boost, given our budget and
-; stones of "in_tier".
-; We allocate 1% of budget to each stone. Based on the tier of the stones we
-; can buy, they cost 2000 * 18^in_tier / 18 each. (We ignore the extra cost
-; of universal stones.) This determines how many stones we can buy, and thus,
-; the max tier.
-; There is an extra division by 9 and a floor. This means that if the level can't
-; be raised by at least 2 levels, the quantity in the log will be rounded down to 0,
-; and thus the log will result in -infinity. We add back the 2 levels on the outside.
-#up_tiers(in_tier) floor(gdg({budget}) / (100. * 2000. * 9. / 18.) / (18. ^ ({in_tier}))) // 3. + 2.
-
-; The top tier that can be achieved, given input stones of "in_tier". Capped
-; either at +11 levels, or by the budget function of up_tiers.
-; If we can't reach +2 levels, up_tiers returns -inf, which will result in -1.
-; from this function.
-#top_tier(in_tier) max(-1., min(50., min(11., {up_tiers({in_tier})}) + ({in_tier})))
diff --git a/museum/purchase.tpt2 b/museum/purchase.tpt2
new file mode 100644
index 0000000..33097e7
--- /dev/null
+++ b/museum/purchase.tpt2
@@ -0,0 +1,6 @@
+:name Museum:Purchase
+
+isopen("museum")
+
+museum.buyTier(element("inventory", 0), 1, freeSlots("inventory"))
+goto(0)
\ No newline at end of file
diff --git a/museum/toggle.tpt2 b/museum/toggle.tpt2
new file mode 100644
index 0000000..dde3e06
--- /dev/null
+++ b/museum/toggle.tpt2
@@ -0,0 +1,30 @@
+:name Museum:Auto Gem
+
+:global int MaxGemSlot
+:global int GemSlot
+:global int GemTier
+:global int MaxTier
+:local int NoGem
+
+isopen("museum")
+
+MaxGemSlot = 135
+GemSlot = 0
+GemTier = 0
+MaxTier = museum.preferredTier() + 1
+NoGem = -1
+gotoif(17, tier("loadout", GemSlot) == NoGem)
+gotoif(17, tier("loadout", GemSlot) >= MaxTier)
+museum.moveTo("loadout", GemSlot, "inventory", 0)
+GemTier = tier("inventory", 0)
+executesync("Loops")
+waituntil(tier("inventory", 0) > GemTier)
+stop("Purchase")
+stop("Combine")
+museum.moveTo("inventory", 0, "loadout", GemSlot)
+waitframe()
+clear("inventory")
+GemSlot = GemSlot + 1
+gotoif(20, GemSlot <= MaxGemSlot)
+GemSlot = 0
+goto(6)
\ No newline at end of file