Initial commit

This commit is contained in:
Aly 2021-03-08 19:55:25 -08:00
commit 31f9808a93
6 changed files with 308 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
main.lua

36
README.md Normal file
View file

@ -0,0 +1,36 @@
# ootAI
An experiment to create an AI that plays OoT Randomizers automatically, getting
as many checks as possible in an efficient manner.
## how does it work
This runs using the Lua Core fork of the Dolphin Emulator project. As of right
now it only works on ROMs generated by the OoT Randomizer.
Eventually I'll have an explanation here on how it does pathfinding and memory
reading, but I don't know how to do enough of that yet.
## how to build
1. Install [AmuletML](https://amulet.works/).
2. Run `amc compile main.ml -o main.lua --lib /path/to/amulet/lib`
3. Copy everything between the first `do` and the last `end` from `main.lua`
4. Create a new script in the Dolphin Lua Core Scripts directory:
```lua
function onScriptStart() end
function onScriptCancel() end
function onScriptUpdate()
-- paste what you copied here
end
function onStateLoaded() end
function onStateSaved() end
```
This script should now run properly when you start it from the Dolphin scripts
menu.

103
dolphin.ml Normal file
View file

@ -0,0 +1,103 @@
open import "prelude.ml"
type u8 =
U8 of int
instance show u8 begin
let show (U8 x) = (show x) ^ "_u8"
end
type s8 =
S8 of int
instance show s8 begin
let show (S8 x) =
let signfix =
if x > 127 then
negate (256 - x)
else
x
(show signfix) ^ "_s8"
end
type u16 =
U16 of int
instance show u16 begin
let show (U16 x) = (show x) ^ "_u16"
end
type s16 =
S16 of int
instance show s16 begin
let show (S16 x) =
let signfix =
if x > 32767 then
negate (65536 - x)
else
x
(show signfix) ^ "_s16"
end
type u32 =
U32 of int
type s32 =
S32 of int
instance show s32 begin
let show (S32 x) =
let signfix =
if x > 2147483647 then
negate (4294967296 - x)
else
x
(show signfix) ^ "_s32"
end
module Dolphin = struct
external val read_value_8 : int -> () -> int =
"function(addr, n) return ReadValue8(addr) end"
external val read_value_16 : int -> () -> int =
"function(addr, n) return ReadValue16(addr) end"
external val read_value_32 : int -> () -> int =
"function(addr, n) return ReadValue32(addr) end"
external val read_value_float : int -> () -> float =
"function(addr, n) return ReadValueFloat(addr) end"
external val read_value_string : int -> int -> () -> string =
"function(addr, len, n) return ReadValueString(addr, len) end"
external val msg_box : string -> int -> () -> () =
"function(message, delay, n) MsgBox(message, delay) end"
external val set_screen_text : string -> () -> () =
"function(message, n) SetScreenText(message) end"
end
class decode 'a begin
val decode : int -> () -> 'a
end
instance decode u8 begin
let decode addr x = U8 (Dolphin.read_value_8 addr x)
end
instance decode s8 begin
let decode addr x = S8 (Dolphin.read_value_8 addr x)
end
instance decode u16 begin
let decode addr x = U16 (Dolphin.read_value_16 addr x)
end
instance decode s16 begin
let decode addr x = S16 (Dolphin.read_value_16 addr x)
end
instance decode u32 begin
let decode addr x = U32 (Dolphin.read_value_32 addr x)
end
instance decode s32 begin
let decode addr x = S32 (Dolphin.read_value_32 addr x)
end

20
main.ml Normal file
View file

@ -0,0 +1,20 @@
open import "prelude.ml"
open import "./save_context.ml"
open import "./pretty.ml"
open import "./dolphin.ml"
let base_address = 0xf64120
let g_save_ctx_address = 0x11a5d0
let decode_save_ctx : () -> save_context = decode (base_address + g_save_ctx_address)
let main x =
let save_ctx = decode_save_ctx x
let display_save_ctx = "Save Context: " ^ (pretty save_ctx 0)
Dolphin.set_screen_text display_save_ctx x
let () =
main ()

5
pretty.ml Normal file
View file

@ -0,0 +1,5 @@
open import "prelude.ml"
class pretty 'a begin
val pretty : 'a -> int -> string
end

143
save_context.ml Normal file
View file

@ -0,0 +1,143 @@
open import "prelude.ml"
open import "./pretty.ml"
open import "./dolphin.ml"
type item_equips = ItemEquips of {
button_item_b: u8,
button_item_c_left: u8,
button_item_c_down: u8,
button_item_c_right: u8,
button_slot_c_left: u8,
button_slot_c_down: u8,
button_slot_c_right: u8,
equipment: u16
}
instance decode item_equips begin
let decode addr x = ItemEquips {
button_item_b = decode (addr + 0x00) x,
button_item_c_left = decode (addr + 0x01) x,
button_item_c_down = decode (addr + 0x02) x,
button_item_c_right = decode (addr + 0x03) x,
button_slot_c_left = decode (addr + 0x04) x,
button_slot_c_down = decode (addr + 0x05) x,
button_slot_c_right = decode (addr + 0x06) x,
equipment = decode (addr + 0x08) x
}
end
instance pretty item_equips begin
let pretty (ItemEquips item_equips) w =
let rec smul s n =
if n <= 0 then
""
else
s ^ (smul s (n - 1))
let prep = smul " " w
let header = "ItemEquips {\n"
let button_item_b = header ^ prep ^ " button_item_b = " ^ (show item_equips.button_item_b) ^ ",\n"
let button_item_c_left = button_item_b ^ prep ^ " button_item_c_left = " ^ (show item_equips.button_item_c_left) ^ ",\n"
let button_item_c_down = button_item_c_left ^ prep ^ " button_item_c_down = " ^ (show item_equips.button_item_c_down) ^ ",\n"
let button_item_c_right = button_item_c_down ^ prep ^ " button_item_c_right = " ^ (show item_equips.button_item_c_right) ^ ",\n"
let button_slot_c_left = button_item_c_right ^ prep ^ " button_slot_c_left = " ^ (show item_equips.button_slot_c_left) ^ ",\n"
let button_slot_c_down = button_slot_c_left ^ prep ^ " button_slot_c_down = " ^ (show item_equips.button_slot_c_down) ^ ",\n"
let button_slot_c_right = button_slot_c_down ^ prep ^ " button_slot_c_right = " ^ (show item_equips.button_slot_c_right) ^ ",\n"
let equipment = button_slot_c_right ^ prep ^ " equipment = " ^ (show item_equips.equipment) ^ ",\n"
equipment ^ prep ^ "}"
end
type save_context = SaveContext of {
entrance_index: s32,
link_age: s32,
cutscene_index: s32,
day_time: u16,
night_flag: s32,
num_days: s32,
claim_days: s32,
(* char newf[6], *)
deaths: s16,
(* char playerName[8], *)
n64dd_flag: s16,
health_capacity: s16,
health: s16,
magic_level: s8,
magic: s8,
rupees: s16,
sword_health: u16,
navi_timer: u16,
magic_acquired: u8,
(* char unk_3B[0x01], *)
double_magic: u8,
double_defense: u8,
bgs_flag: u8,
ocarina_game_reward: u8,
child_equips: item_equips,
adult_equips: item_equips
}
instance decode save_context begin
let decode addr x = SaveContext {
entrance_index = decode (addr + 0x0000) x,
link_age = decode (addr + 0x0004) x,
cutscene_index = decode (addr + 0x0008) x,
day_time = decode (addr + 0x000C) x,
night_flag = decode (addr + 0x0010) x,
num_days = decode (addr + 0x0014) x,
claim_days = decode (addr + 0x0018) x,
(* newf, *)
deaths = decode (addr + 0x0022) x,
n64dd_flag = decode (addr + 0x002C) x,
health_capacity = decode (addr + 0x002E) x,
health = decode (addr + 0x0030) x,
magic_level = decode (addr + 0x0032) x,
magic = decode (addr + 0x0033) x,
rupees = decode (addr + 0x0034) x,
sword_health = decode (addr + 0x0036) x,
navi_timer = decode (addr + 0x0038) x,
magic_acquired = decode (addr + 0x003A) x,
double_magic = decode (addr + 0x003C) x,
double_defense = decode (addr + 0x003D) x,
bgs_flag = decode (addr + 0x003E) x,
ocarina_game_reward = decode (addr + 0x003F) x,
child_equips = decode (addr + 0x0040) x,
adult_equips = decode (addr + 0x004A) x
}
end
instance pretty save_context begin
let pretty (SaveContext save_context) w =
let rec smul s n =
if n <= 0 then
""
else
s ^ (smul s (n - 1))
let x = w + 2
let prep = smul " " w
let header = "SaveContext {\n"
let entrance_index = header ^ prep ^ " entrance_index = " ^ (show save_context.entrance_index) ^ ",\n"
let link_age = entrance_index ^ prep ^ " link_age = " ^ (show save_context.link_age) ^ ",\n"
let cutscene_index = link_age ^ prep ^ " cutscene_index = " ^ (show save_context.cutscene_index) ^ ",\n"
let day_time = cutscene_index ^ prep ^ " day_time = " ^ (show save_context.day_time) ^ ",\n"
let night_flag = day_time ^ prep ^ " night_flag = " ^ (show save_context.night_flag) ^ ",\n"
let num_days = night_flag ^ prep ^ " num_days = " ^ (show save_context.num_days) ^ ",\n"
let claim_days = num_days ^ prep ^ " claim_days = " ^ (show save_context.claim_days) ^ ",\n"
let deaths = claim_days ^ prep ^ " deaths = " ^ (show save_context.deaths) ^ ",\n"
let n64dd_flag = deaths ^ prep ^ " n64dd_flag = " ^ (show save_context.n64dd_flag) ^ ",\n"
let health_capacity = n64dd_flag ^ prep ^ " health_capacity = " ^ (show save_context.health_capacity) ^ ",\n"
let health = health_capacity ^ prep ^ " health = " ^ (show save_context.health) ^ ",\n"
let magic_level = health ^ prep ^ " magic_level = " ^ (show save_context.magic_level) ^ ",\n"
let magic = magic_level ^ prep ^ " magic = " ^ (show save_context.magic) ^ ",\n"
let rupees = magic ^ prep ^ " rupees = " ^ (show save_context.rupees) ^ ",\n"
let sword_health = rupees ^ prep ^ " sword_health = " ^ (show save_context.sword_health) ^ ",\n"
let navi_timer = sword_health ^ prep ^ " navi_timer = " ^ (show save_context.navi_timer) ^ ",\n"
let magic_acquired = navi_timer ^ prep ^ " magic_acquired = " ^ (show save_context.magic_acquired) ^ ",\n"
let double_magic = magic_acquired ^ prep ^ " double_magic = " ^ (show save_context.double_magic) ^ ",\n"
let double_defense = double_magic ^ prep ^ " double_defense = " ^ (show save_context.double_defense) ^ ",\n"
let bgs_flag = double_defense ^ prep ^ " bgs_flag = " ^ (show save_context.bgs_flag) ^ ",\n"
let ocarina_game_reward = bgs_flag ^ prep ^ " ocarina_game_reward = " ^ (show save_context.ocarina_game_reward) ^ ",\n"
let child_equips = ocarina_game_reward ^ prep ^ " child_equips = " ^ (pretty save_context.child_equips x) ^ ",\n"
let adult_equips = child_equips ^ prep ^ " adult_equips = " ^ (pretty save_context.adult_equips x) ^ ", \n"
adult_equips ^ prep ^ "}"
end