Open API written in Python 3 for making your own Smash Bros: Melee AI that works with Slippi Online
Libmelee is on pip, this will be the easiest way to get the library and stay updated.
pip3 install melee
And definitely stay updated, as the library will be actively improved.
pip3 install --upgrade melee
Linux / OSX / Windows
Install and configure Slippi, just like you would for rollback netplay. Full instructions here: https://slippi.gg
If you're on Linux using the official appimage, extract it using ./Slippi_Online-x86_64.AppImage --appimage-extract
. This will pull apart the app image into a folder in the same directory.
If you want to play interactively with or against your AI, you'll probably want a GameCube Adapter, available on Amazon here: https://www.amazon.com/Super-Smash-GameCube-Adapter-Wii-U/dp/B00L3LQ1FI. Or alternatively the HitBox adapter works well too: https://www.hitboxarcade.com/products/gamecube-controller-adapter
Install some custom Slippi Gecko Codes. You can find them here: https://github.com/altf4/slippi-ssbm-asm/blob/libmelee/Output/Netplay/GALE01r2.ini Simply replace your existing GALE01r2.ini
file with this one. On Linux with the appimage, the file is located at squashfs-root/usr/bin/Sys/GameSettings/GALE01r2.ini
.
Make sure you have all the Required
and Recommended
Gecko Codes enabled.
Run ./example.py -e PATH_TO_SLIPPI_FOLDER
(Not the exe itself, the folder) If you're using the Linux appimage, set this to squashfs-root/usr/bin/
.
Do not play on Unranked There is no libmelee option for it, but don't try. Eventually we'll have a way to register an account as a "bot account" that others will have the ability to opt in or out of playing against. But we don't have it yet. Until then, do not play any bots on Unranked. If you do, we'll know about it, ban your account, overcook all of your food, and seed you against a campy Luigi every tournament. Don't do it.
Here's a ~10 minute video that will show you how easy it can be to write a Melee AI from scratch.
Some of the minor aspects of the API have changed since this video was made, but it's still a good resource.
This readme will give you a very high level overview of the API. For a more detailed view into specific functions and their params, check out the ReadTheDocs page here: https://libmelee.readthedocs.io/
The GameState represents the current state of the game as a snapshot in time. It's your primary way to view what's happening in the game, holding all the information about the game that you probably care about including things like:
Also a list of PlayerState objects that represent the state of the 4 players:
The GameState object should be treated as immutable. Changing it won't have any effect on the game, and you'll receive a new copy each frame anyway.
Libmelee tries to create a sensible and intuitive API for Melee. So it may break with some low-level binary structures that the game creates. Some examples:
character.animation_frame == 7
.Other values in Melee are unintuitive, but are a core aspect of how the game works so we can't abstract it away.
Libmelee lets you programatically press buttons on a virtual controller via Dolphin's named pipes input mechanism. The interface for this is pretty simple, after setting up a controller and connecting it, you can:
controller.press_button(melee.enums.BUTTON_A)
or
controller.release_button(melee.enums.BUTTON_A)
Or tilt one of the analog sticks by:
controller.tilt_analog(melee.enums.BUTTON_MAIN, X, Y)
(X and Y are numbers between 0->1. Where 0 is left/down and 1 is right/up. 0.5 is neutral)
Dolphin will accept whatever your last button input was each frame. So if you press A, and then release A on the same frame, only the last action will matter and A will never be seen as pressed to the game.
Also, if you don't press a button, Dolphin will just use whatever you pressed last frame. So for example, if on frame 1 you press A, and on frame 2 you press Y, both A and Y will be pressed. The controller does not release buttons for you between frames. Though there is a helper function:
controller.release_all()
which will release all buttons and set all sticks / shoulders to neutral.
Each of these old values will be removed in version 1.0.0. So update your programs!
gamestate.player
has been changed to gamestate.players
(plural) to be more Pythonic.gamestate.x
and gamestate.y
have been combined into a named tuple: gamestate.position
. So you can now access it via gamestate.position.x
.projectile.x
and projectile.y
have been combined into a named tuple: projectile.position
. So you can now access it via projectile.position.x
.projectile.x_speed
and projectile.y_speed
have been combined into a named tuple: projectile.speed
. So you can now access it via projectile.speed.x
gamestate.stage_select_cursor_x
and gamestate.stage_select_cursor_x
have both been combined into the PlayerState cursor
. It makes the API cleaner to just have cursor be separate for each player, even though it's a shared cursor there.playerstate.character_selected
has been combined into playerstate.charcter
. Just use the menu to know the context.playerstate.ecb_left
and the rest have been combined into named tuples like: playerstate.ecb.left.x
for each of left
, right
, top
, bottom
. And x
, y
coords.hitlag
boolean has been changed to hitlag_left
intProjectileSubtype
has been renamed to ProjectileType
to refer to its primary type enum. There is a new subtype
int that refers to a subtype.libmelee is inspired by, but not exactly conforming to, the OpenAI Gym API.
Version | Tag | Published |
---|---|---|
0.37.0 | 6d ago | |
0.36.0 | 1mo ago | |
0.35.0 | 8mos ago | |
0.34.0 | 9mos ago |