-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Welcome to the __speedrun wiki (currently under construction)! Learn how to use the library here.
To use this library, do the following:
- Drop a copy of the
__speedrun
folder into the directory of the episode you wish to make a TAS in. - Add the following lines to the very top of the episode- or level-wide luna.lua file:
-- small mod for TAS
if Misc.saveSlot() == 2 or Misc.inEditor() then
require("__speedrun/speedrun")
end
This will load the TASBot for the episode, which will override inputs if a) a level in the episode folder is tested from the PGE/Moondust editor, or a level in the folder is entered in-game with the second save file slot being used; and b) there is a .lua file containing input instructions for the current level. You must put this at the very top of the episode's luna.lua file, to ensure that it runs before all onInputUpdate functions in libraries, episode code, and level code. Otherwise, you may get strange behavior.
-
In the episode folder, create a folder named
__runs
. This should be on the same level as the__speedrun
folder, not inside it. -
Create a
.lua
file in theruns
folder with the same name as the level you wish to TAS. For example, if the level is namedwatermelon.lvlx
, you would create a file in theruns
folder namedwatermelon.lua
.
Keeping with the watermelon
example from above, the resulting directory structure should look like this:
EpisodeFolder/
__speedrun/
__runs/
watermelon.lua
watermelon/
watermelon.lvlx
- make that .lua file return a table with the input instructions for the level. Look inside
__speedrun/speedrun.lua
for documentation. I am currently working on documenting everything this library has to offer in this wiki, but it will take some time.
This library uses input instruction tables to tell the bot what to input to the player. Input instruction tables have an appearance similar to a Lisp (list-processing) language. This is because they do essentially the same thing, but with a Lua table instead of a linked list.
This library expects the .lua
file for each level to return a table of input instructions. Read on for more information. For the samples of code below, we will stick with the watermelon
example from the previous section
There are two types of structures available. The input instructions may be stored per-section, or they may be global to the entire level.
This is generally the recommended structure to use. To use it, simply store inputs at indexes corresponding to the section indexes. Since sections are zero-indexed and Lua tables are normally one-indexed, you will need to manually assign to index zero, giving you a watermelon.lua
file that looks like this:
return {
[0] = {
-- ... instructions for section 0 here ...
},
{
-- ... instructions for section 1 here ...
},
-- ... instructions for any other sections. There may be gaps in this table if necessary ...
}
This stores inputs for the whole level in a single list. This should only be used in a limited set of circumstances, such as on a custom world map level made with MrDoubleA's smwMap library. Note that this library currently does not support SMBX 1.3-style world maps. To use this mode, set the global
key in your table. This results in a file like this:
return {
global = true,
-- ... instructions for level here ...
}
By default, the derandomizer sets the RNG seed to 8675309
. Chances are, this isn't the optimal seed. You can change the seed by setting the seed
key in the inputs table:
return {
seed = 23409485023,
[0] = {
-- ...
},
-- ...
}
As for methods for finding the best seed, you're on your own. This is not an area I know much about. However, if, like me, you put the TAS together one section at a time, you may find that the RNG stuff differs from your testing during the final run. There is some crude functionality in this library for handling that situation. This works by repeatedly selecting random seeds until one is found that does not result in the player's death. This isn't yet fully implemented.
To enable it, uncomment lines 527, 528, and 570, and comment out line 568 in speedrun.lua
, then run the level with the TASBot. The run will proceed until the player dies, then it will restart. This will continue until the level has been cleared, at which point, a dialog will appear showing the seed that worked. Copy that seed into the seed field of the instruction table. Note that this could take several hours. I would recommend running it overnight or at any other time when you will be away from the computer.
Input instructions tell the TASBot what to do in a section or level. Each instruction has the following structure: inputs,{condition},
. The input code consists of zero or more characters. Each character represents a single key in the player.keys
table. You can view a list of these characters and their meanings here.
In the place of an instruction, you may also use a special form. These special forms allow for loops and conditional branching within the instructions.
There are many types of input conditions. Go to this page for more information.
Consider the following input instruction table:
return {
[0] = { -- section 0
"run",{math.huge},
},
{ -- section 1
"rn",{10},
"jrn",{"md"},
"rn",{"x",">=",-200000},
"ln",{"ml"},
},
}
First, we will look at the section 0 inputs. There is a single input instruction for this section, "run",{math.huge},
. This instructs the bot to run to the right and hold up forever or until the player changes sections. We will assume for this example that the player will eventually reach a door that leads to section 1, then enter it since up is being held.
Now to look at the section 1 inputs.
The first instruction, "rn",{10},
, instructs the bot to run to the right for 10 ticks, then move on to the next instruction.
The second instruction, "jrn",{"md"},
, instructs the bot to jump while running to the right, until the player begins to move downward (this will be at the apex of the jump), then move on to the next instruction.
The third instruction, "rn",{"x",">=",-200000},
, instructs the bot to run to the right until the player's x-position is at least -200,000, then move on to the next instruction.
The final instruction, "ln",{"ml"},
, instructs the bot to run to the left until the player is moving left (this will occur on the frame when the player stops). Since there are no instructions after this one, the player's inputs will be released back to the user's control when it finishes.