This project explores the techniques of control theory and related concepts to develop a control system for the game Mario Kart DS. The game is played automatically in the DeSmuME emulator, with automation provided by a Lua script. The main loop of the program is:
- Lua script in DeSmuME captures a screenshot of the current game frame
 - Lua script sends the screenshot to a Python script via a TCP IPv4 socket
 - Python script uses computer vision (OpenCV) to extract the game state from the screenshot
 - Python script uses a control algorithm to determine the desired control input (button presses)
 - Python script sends the button press commands back to the Lua script
 - Lua script presses the required buttons in the emulator, progressing the game state
 
- Windows 11 (if using the libraries given here)
 - DeSmuME (x86), set up to use 32-bit Lua 5.1
 - Lua libraries: lua-gd and LuaSocket
 - Python libraries: OpenCV and NumPy
 - Mario Kart ROM: via romsgames.net
 
- Open DeSmuME with Mario Kart DS.
 - In Python, run 
main.pyto set up a server. - In the Lua scripting window of DeSmuME, load 
stream_socket.lua. - Start a race in Mario Kart.
 - You will see game in OpenCV playing itself.
 
- Ensure you have the 32-bit version of 
lua51.dllin a directory added to PATH. - Obtain the pre-built 32-bit Lua 5.1 LuaSocket libraries (
socketandmime) from this source. Download and extract to the script directory. - Obtain the pre-built 
gdlibrary here. Extract all the.dllfiles:free.type6.dll,gd.dll,jpeg62.dll,libgd2.dll,libiconv2.dll,libpng13.dll. - The required directory structure is shown in the 
lua_libsfolder inside this repo. Copy the extracted files to the appropriate directories. It has the following structure: 
    lua_libs/
    ├── gd/
    │   ├── free.type6.dll
    │   ├── gd.dll
    │   ├── jpeg62.dll
    │   ├── libgd2.dll
    │   ├── libiconv2.dll
    │   └── libpng13.dll
    ├── socket/
    │   └── core.dll
    ├── mime/
    │   └── core.dll
    └── luasocket/
        ├── socket/
        │   ├── ftp.lua
        │   ├── http.lua
        │   ├── smtp.lua
        │   ├── tp.lua
        │   └── url.lua
        ├── headers.lua
        ├── ltn12.lua
        ├── mbox.lua
        ├── mime.lua
        └── socket.lua
- In your own Lua scripts, import the modules from those directories as follows:
local script_dir = debug.getinfo(1, "S").source:match[[^@?(.*[\/])[^\/]-$]] -- directory of this file local gd_path = script_dir .. "lua_libs/gd" local socket_path = script_dir .. "lua_libs/socket" local mime_path = script_dir .. "lua_libs/mime" -- import gd library package.cpath = gd_path .. "/gd.dll;" local gd = require('gd') -- import luasocket library package.path = script_dir .. "lua_libs/luasocket/?.lua;" package.cpath = socket_path .. "/core.dll;" .. mime_path .. "/core.dll;" local socket = require('socket') print(gd.VERSION) print(socket._VERSION)
 
- Find out how to take screenshots in Lua
 - Use sockets to stream the screen image data to Python's OpenCV library
 - Use morphological operations to produce sharper images of the track
 - Allow the player to manually steer while the script automatically holds A
 - Write the OpenCV and socket Python program in C++ for faster processing - may not actually improve performance that much but will be good for learning
 
Ideas for control algorithm:
- Set a specified path and design a PID controller to follow it (line following)
 - Or MPC with discrete inputs reference
 - Use MATLAB to design optimal controllers (
$H_2$ or$H_{\infty}$ ) - Deep reinforcement learning using OpenAI gym
 - 
- RL with human feedback - allow manual steering override as feedback signal. Look at how Wayve did this for autonomous driving.