From 4a0929eb3ac7518c7e1a229e09fe5f2dec95bca2 Mon Sep 17 00:00:00 2001 From: DarkSirrush Date: Sat, 12 Sep 2026 17:16:39 -0700 Subject: [PATCH 1/4] Update Museum Combiner to function (poorly) --- README.md | 86 ++-------- museum/Buy.tpt2 | 160 ------------------ museum/Calculate.tpt2 | 137 ---------------- museum/Combine.tpt2 | 160 ++++-------------- museum/Combining.tpt2 | 227 -------------------------- museum/Main.tpt2 | 227 ++------------------------ museum/README.md | 5 + museum/Waiting.tpt2 | 323 ------------------------------------- museum/museum5_macros.tpt2 | 114 ------------- museum/museum_macros.tpt2 | 35 ---- 10 files changed, 56 insertions(+), 1418 deletions(-) delete mode 100644 museum/Buy.tpt2 delete mode 100644 museum/Calculate.tpt2 delete mode 100644 museum/Combining.tpt2 delete mode 100644 museum/Waiting.tpt2 delete mode 100644 museum/museum5_macros.tpt2 delete mode 100644 museum/museum_macros.tpt2 diff --git a/README.md b/README.md index 24f3224..7cce235 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,30 @@ 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.0** -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, *really* slow. It is barely 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:` -``` -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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*. - -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. +Then go to the museum and press "E" to enable the script. -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. -![The combiner running](/museum_combiner.png) - -### 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.) +(below gif is from previous version of combiner) -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. - -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. +![The combiner running](/museum_combiner.png) -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 +158,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 index fea9bc9..064d3cc 100644 --- a/museum/Combine.tpt2 +++ b/museum/Combine.tpt2 @@ -1,133 +1,27 @@ -: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) +:name Museum:Auto Gem + +:global int MaxGemSlot +:global int GemSlot +:global int GemTier +:local int CombineCount + +isopen("museum") + +MaxGemSlot = 135 +GemSlot = 0 +GemTier = 0 +museum.moveTo("loadout", GemSlot, "inventory", 0) +gotoif(14, -1 == tier("inventory", 0)) +GemTier = min(tier("inventory", 0), museum.preferredTier()) +gotoif(14, GemTier < tier("inventory", 0)) +museum.buyTier(element("inventory", 0), 1, freeSlots("inventory")) +CombineCount = 0 +combine(0) +CombineCount = CombineCount + 1 +gotoif(10, CombineCount <= 7) +gotoif(8, tier("inventory", 0) <= GemTier) +museum.moveTo("inventory", 0, "loadout", GemSlot) +clear("inventory") +GemSlot = GemSlot + 1 +gotoif(4, GemSlot < MaxGemSlot) +goto(0) \ No newline at end of file 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 index 22c9b9e..93c9d69 100644 --- a/museum/Main.tpt2 +++ b/museum/Main.tpt2 @@ -1,219 +1,18 @@ -:import museum_macros -:name {script(Main)} +:name Museum:Gem Start -; 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 bool isrunning +:global int GemSlot -: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() +key.e() 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 = "" +gotoif(5, isrunning) +execute("Auto Gem") +isrunning = true +goto(99) +stop("Auto Gem") +isrunning = false +museum.moveTo("inventory", 0, "loadout", GemSlot) +clear("inventory") +lu("End") \ No newline at end of file diff --git a/museum/README.md b/museum/README.md index 5ee9492..4459913 100644 --- a/museum/README.md +++ b/museum/README.md @@ -22,6 +22,11 @@ changing them. ## Changelog +### 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/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}))) From b5613d60277db4442b93e9caf578ab8dc12da030 Mon Sep 17 00:00:00 2001 From: DarkSirrush Date: Sat, 12 Sep 2026 17:16:39 -0700 Subject: [PATCH 2/4] Update Museum Combiner to function (poorly) --- README.md | 87 ++-------- museum/Buy.tpt2 | 160 ------------------ museum/Calculate.tpt2 | 137 ---------------- museum/Combine.tpt2 | 160 ++++-------------- museum/Combining.tpt2 | 227 -------------------------- museum/Main.tpt2 | 227 ++------------------------ museum/README.md | 5 + museum/Waiting.tpt2 | 323 ------------------------------------- museum/museum5_macros.tpt2 | 114 ------------- museum/museum_macros.tpt2 | 35 ---- 10 files changed, 58 insertions(+), 1417 deletions(-) delete mode 100644 museum/Buy.tpt2 delete mode 100644 museum/Calculate.tpt2 delete mode 100644 museum/Combining.tpt2 delete mode 100644 museum/Waiting.tpt2 delete mode 100644 museum/museum5_macros.tpt2 delete mode 100644 museum/museum_macros.tpt2 diff --git a/README.md b/README.md index 24f3224..e308515 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.0** -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, *really* slow. It is barely 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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 ``` -**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. -![The combiner running](/museum_combiner.png) - -### 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 gif 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. +![The combiner running](/museum_combiner.png) -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 index fea9bc9..064d3cc 100644 --- a/museum/Combine.tpt2 +++ b/museum/Combine.tpt2 @@ -1,133 +1,27 @@ -: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) +:name Museum:Auto Gem + +:global int MaxGemSlot +:global int GemSlot +:global int GemTier +:local int CombineCount + +isopen("museum") + +MaxGemSlot = 135 +GemSlot = 0 +GemTier = 0 +museum.moveTo("loadout", GemSlot, "inventory", 0) +gotoif(14, -1 == tier("inventory", 0)) +GemTier = min(tier("inventory", 0), museum.preferredTier()) +gotoif(14, GemTier < tier("inventory", 0)) +museum.buyTier(element("inventory", 0), 1, freeSlots("inventory")) +CombineCount = 0 +combine(0) +CombineCount = CombineCount + 1 +gotoif(10, CombineCount <= 7) +gotoif(8, tier("inventory", 0) <= GemTier) +museum.moveTo("inventory", 0, "loadout", GemSlot) +clear("inventory") +GemSlot = GemSlot + 1 +gotoif(4, GemSlot < MaxGemSlot) +goto(0) \ No newline at end of file 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 index 22c9b9e..93c9d69 100644 --- a/museum/Main.tpt2 +++ b/museum/Main.tpt2 @@ -1,219 +1,18 @@ -:import museum_macros -:name {script(Main)} +:name Museum:Gem Start -; 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 bool isrunning +:global int GemSlot -: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() +key.e() 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 = "" +gotoif(5, isrunning) +execute("Auto Gem") +isrunning = true +goto(99) +stop("Auto Gem") +isrunning = false +museum.moveTo("inventory", 0, "loadout", GemSlot) +clear("inventory") +lu("End") \ No newline at end of file diff --git a/museum/README.md b/museum/README.md index 5ee9492..4459913 100644 --- a/museum/README.md +++ b/museum/README.md @@ -22,6 +22,11 @@ changing them. ## Changelog +### 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/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}))) From 143f37a8112bb4a7df74b4d6b23be39ae11d3cae Mon Sep 17 00:00:00 2001 From: DarkSirrush <79956291+DarkSirrush@users.noreply.github.com> Date: Sat, 12 Sep 2026 17:25:58 -0700 Subject: [PATCH 3/4] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 7cce235..1de82bb 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,10 @@ This script is very similar to my other autominer: It mines all layers across al This package combines museum powerstones, *really* slow. It is barely 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. +`Import Code:` +``` +3VdNj5swEP0rEdeuENBtV6qSQ7ta9bSn7a3Zg4GBWsFjZOzNRqs992dVav9YjSEbAiaA8nFYRbLij3l+M/PGNi9OEQmay8L5Mvv54pBIUo6m4yyV53mQAoKgkZtyyWmyDCM9LQlKMxuY9pNpvU6bpBkPSeaGnGduCrJlfL2UtBAKkWLqXM2c2qbeD54hUhI6NuFXJfnsO7CGSWOb4uA2rSm/ag1S0nS07WbU9XDfqJA8vwBVb4fEVAGKuYw/wUPGbUj4BCi52Fhz1s2W14Eo25uMk5grWYuhok9RWvNpDLS/JaEqPjXLKAMiDlB8cyvMeKQ3UGgLTtl+vMPYedTLQxVrClqonu7ohTHdV64fSL5Gd00x5muXFjwHtCJ+rjgaUMpylRVQoaxg44IZRsJADznatdmDJMI4l5NoRVIzfl8h6EH959uWWEI01OvVzFpVu0DaPMV78lzHsZ29v797tDgGt5mgsbKYDP6DQjvXw+CDej5KjCeojkYYhk9E6EGBiLOcCK1GLHm3bf/9qX5WX4LFwujaryOljxwEV3aDfaR3E5JsOuVKRvF83AxyuNUHESuQbi4gASEgLnmcJTVTJGZRfDXpz8+fMt/bQw/Vxoxe741CBgw6gjvBLRE0b6dO1rbUEgGmqouhO0BU53+f+pJbzkKKcMtVt3qGtb29jSqQSfaTiJnNtJbkLwZSy7HUUwPAJqVDntVa+jA29KPrAUfWwtHcg/nCSv7mCPLh+EI+07nU5+nUo+O9P+omvUpstTOV5qXqZwd+2vuk34f5KJzG83H426b32LvIK7v5vG5+Lo18XT++/gc= +``` ### Details From 43b19517b919a75be0f429c46aa09e663f005931 Mon Sep 17 00:00:00 2001 From: DarkSirrush Date: Sat, 12 Sep 2026 22:27:54 -0700 Subject: [PATCH 4/4] Apparently doing things concurrently increases speed concurrently! Who would have thunk? --- README.md | 8 ++++---- museum/Combine.tpt2 | 27 --------------------------- museum/Main.tpt2 | 18 ------------------ museum/README.md | 4 ++++ museum/auto_gem.tpt2 | 30 ++++++++++++++++++++++++++++++ museum/combine.tpt2 | 6 ++++++ museum/loops.tpt2 | 19 +++++++++++++++++++ museum/purchase.tpt2 | 6 ++++++ museum/toggle.tpt2 | 30 ++++++++++++++++++++++++++++++ 9 files changed, 99 insertions(+), 49 deletions(-) delete mode 100644 museum/Combine.tpt2 delete mode 100644 museum/Main.tpt2 create mode 100644 museum/auto_gem.tpt2 create mode 100644 museum/combine.tpt2 create mode 100644 museum/loops.tpt2 create mode 100644 museum/purchase.tpt2 create mode 100644 museum/toggle.tpt2 diff --git a/README.md b/README.md index e308515..3ae99f8 100644 --- a/README.md +++ b/README.md @@ -125,13 +125,13 @@ This script is very similar to my other autominer: It mines all layers across al ``` ## Museum combiner v5 -**v5.0** +**v5.1** -This package combines museum powerstones, *really* slow. It is barely 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 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. `Import Code:` ``` -3VdNj5swEP0rEdeuENBtV6qSQ7ta9bSn7a3Zg4GBWsFjZOzNRqs992dVav9YjSEbAiaA8nFYRbLij3l+M/PGNi9OEQmay8L5Mvv54pBIUo6m4yyV53mQAoKgkZtyyWmyDCM9LQlKMxuY9pNpvU6bpBkPSeaGnGduCrJlfL2UtBAKkWLqXM2c2qbeD54hUhI6NuFXJfnsO7CGSWOb4uA2rSm/ag1S0nS07WbU9XDfqJA8vwBVb4fEVAGKuYw/wUPGbUj4BCi52Fhz1s2W14Eo25uMk5grWYuhok9RWvNpDLS/JaEqPjXLKAMiDlB8cyvMeKQ3UGgLTtl+vMPYedTLQxVrClqonu7ohTHdV64fSL5Gd00x5muXFjwHtCJ+rjgaUMpylRVQoaxg44IZRsJADznatdmDJMI4l5NoRVIzfl8h6EH959uWWEI01OvVzFpVu0DaPMV78lzHsZ29v797tDgGt5mgsbKYDP6DQjvXw+CDej5KjCeojkYYhk9E6EGBiLOcCK1GLHm3bf/9qX5WX4LFwujaryOljxwEV3aDfaR3E5JsOuVKRvF83AxyuNUHESuQbi4gASEgLnmcJTVTJGZRfDXpz8+fMt/bQw/Vxoxe741CBgw6gjvBLRE0b6dO1rbUEgGmqouhO0BU53+f+pJbzkKKcMtVt3qGtb29jSqQSfaTiJnNtJbkLwZSy7HUUwPAJqVDntVa+jA29KPrAUfWwtHcg/nCSv7mCPLh+EI+07nU5+nUo+O9P+omvUpstTOV5qXqZwd+2vuk34f5KJzG83H426b32LvIK7v5vG5+Lo18XT++/gc= +7VjdatswFH6V4NsVY6dpB2MpbGPsZh2D9W7thWwfuyK2ZPTTNJRe77EG24tNkZzMseVETtyMjhIQsazz5Tv/R3nweMxwKbj3ZvT9wUOxwJToB+9aBkEAGRBgOPYzKihOr6NYvRaICP12rNczvQatNc1yGqHcjyjN/QxEQ3hyLTBnkhBMMu9k5LVl+FaZxqvQrDWkijncQywFtJCid1LQ0ScotEhaV7SpZtzWcFOIC1q2f+CrZPEt4uBy1k7Gena5vv5AiwgTGMxwwV+kQnKQhV/QO/iWUxsSuQMiKFtYw6EdCIFdhZyihEpRxZmhj4mwhooWUOZZEjImqljGOSC2heJarSinsfoBSWzGWa6nH0ni3ajjkUwUBZUDgXpQBxO8mRThWNA58eeYJHTuY05LIFbEc8NRg+KilDkHgzKDhQ96m6AC1JZ3RbMs194sUTxDmd68NOJqU315v2KVIoXzeDJqZ2sYVEZRYUPAj+RC7042diGHQplmeK+O69HUXNfUUgY6qvgun21NyC5Kx/Ff3XH1HD/AdQ7laqOaPJVIR215kXqR+ndSR0/qz5SW/NCMhlWHMlo4l7BnVPxqbj3IUrXmb+vO5BLdV72/aYtfPzos6IJbHyp6uacP+BWG5nwyELiyigbXAohhcVuAUDGDzbEwWg1yiM1A+CWDFBiDxMLIIIavXFu6JsrMRLWN49kXqkzQRP3903xq6u68ZYQdg0UAKr9KpT2nZK15uDHxiC59955ArS/H02ndJF0YxiT/meoXU3egKmzd7xvD8u0/5+6X8o7O2J9OeNpoonxBYnvIrfuZYbWSmyMsJBE4PySaBroNhhe9XLuOoOGu4Bq6Nag8i8twy6spW3bove7JvZpmR+s5vKL0bEWulXTiXkkHqIpv3apibbx5+tFl92R5bpE8+mRZ/zvMcbS8efwD ``` ### Details @@ -147,7 +147,7 @@ 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. -(below gif is from previous version of combiner) +(below image is from previous version of combiner) ![The combiner running](/museum_combiner.png) diff --git a/museum/Combine.tpt2 b/museum/Combine.tpt2 deleted file mode 100644 index 064d3cc..0000000 --- a/museum/Combine.tpt2 +++ /dev/null @@ -1,27 +0,0 @@ -:name Museum:Auto Gem - -:global int MaxGemSlot -:global int GemSlot -:global int GemTier -:local int CombineCount - -isopen("museum") - -MaxGemSlot = 135 -GemSlot = 0 -GemTier = 0 -museum.moveTo("loadout", GemSlot, "inventory", 0) -gotoif(14, -1 == tier("inventory", 0)) -GemTier = min(tier("inventory", 0), museum.preferredTier()) -gotoif(14, GemTier < tier("inventory", 0)) -museum.buyTier(element("inventory", 0), 1, freeSlots("inventory")) -CombineCount = 0 -combine(0) -CombineCount = CombineCount + 1 -gotoif(10, CombineCount <= 7) -gotoif(8, tier("inventory", 0) <= GemTier) -museum.moveTo("inventory", 0, "loadout", GemSlot) -clear("inventory") -GemSlot = GemSlot + 1 -gotoif(4, GemSlot < MaxGemSlot) -goto(0) \ No newline at end of file diff --git a/museum/Main.tpt2 b/museum/Main.tpt2 deleted file mode 100644 index 93c9d69..0000000 --- a/museum/Main.tpt2 +++ /dev/null @@ -1,18 +0,0 @@ -:name Museum:Gem Start - -:global bool isrunning -:global int GemSlot - -key.e() - -isopen("museum") - -gotoif(5, isrunning) -execute("Auto Gem") -isrunning = true -goto(99) -stop("Auto Gem") -isrunning = false -museum.moveTo("inventory", 0, "loadout", GemSlot) -clear("inventory") -lu("End") \ No newline at end of file diff --git a/museum/README.md b/museum/README.md index 4459913..adef0a0 100644 --- a/museum/README.md +++ b/museum/README.md @@ -22,6 +22,10 @@ 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. 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/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