1 2
7 8
Post subject: Lua-scripting discussion thread
Skilled player (1882)
Joined: 4/20/2005
Posts: 2160
Location: Norrköping, Sweden
Now that FCEU supports Lua-scripting, I'm guessing that a lot of TASers (inlucing me) have just started to play around with it. You'll have to excuse the vague subject of this thread, but the intention is that this should be a thread where we can discuss Lua scripting in FCEU, if we need help with coding something or just if we want to discuss different ways of solving something (since these kinds of discussions don't really fit the FCEU development thread). If anyone can think of a better name for this thread, that would be nice. :P I know that SNES9X also supports Lua-scripting, and that there is a Lua-script thread in the SNES9X section of the forum. I haven't tested it yet and I don't know the differences between FCEU's and SNES9x's Lua-scripting, so this thread is aimed for scripting in FCEU, though I guess most codes will work in SNES9X too. I'll start off with a general question: When using a Lua script, the Lua-content shown on screen is 1 frame behind: to be more clear, if I make a Lua-script that display my X-position, it display what my X-position was 1 frame ago. Is there a way to make it display the current values of RAM-addresses instead of the values 1 frame ago? I also wonder how on earth you check if a variable is equal to a certain value. Let's say that I want something done when variable x=0, how do I write that? if x=0 then ... end doesn't work, and neither does if x~=0 then ... end. Any ideas? The way I solve it now, if I want something done when x=c, I do "if x<=c then if x>c-1 then ... end end" which is pretty inconvenient. :) So, if anyone else has questions about Lua-scripting, or just want to share their Lua-scripts, go ahead and post your them here! Please note that things like bug-reports and such should be posted in the FCEU development thread, since they concern the development of FCEU.
Post subject: Re: Lua-scripting discussion thread
Active player (282)
Joined: 3/4/2006
Posts: 341
Randil wrote:
I also wonder how on earth you check if a variable is equal to a certain value. Let's say that I want something done when variable x=0, how do I write that? if x=0 then ... end doesn't work, and neither does if x~=0 then ... end. Any ideas? The way I solve it now, if I want something done when x=c, I do "if x<=c then if x>c-1 then ... end end" which is pretty inconvenient. :)
Use == instead of = to test for equality.
Joined: 3/17/2007
Posts: 97
Location: Berkeley, CA
The FCEU Lua API is almost identical to that of snes9x-lua v0.05. You test for equality with the == operator. Dealing with the one-frame delay is the purpose of the gui.register() function: pass it a function that does the drawing you want to show up with *no* delay. It should behave exactly according to DeHackEd's description, but I haven't tested it thoroughly and have no useful sample code. Happy hacking! :)
IRC nick: UncombedCoconut
Skilled player (1882)
Joined: 4/20/2005
Posts: 2160
Location: Norrköping, Sweden
I thought I tested == and it didn't work, but it seems that I was wrong. Silly me. Well, thanks a lot. :) EDIT: I'm using the gui.register function now, but it doesn't seem to do anything. I tried using it to display my x position and y position by writing gui.register( gui.text(xpos, ypos-8, xpos) ) gui.register( gui.text(xpos, ypos, ypos) ) but it's still 1 frame behind. Should I give gui.register an additional argument, or am I doing something else wrong? Note that the code works, it's just that it's still 1 frame behind.
Joined: 3/17/2007
Posts: 97
Location: Berkeley, CA
Yeah, that code calls gui.text() (drawing before the .frameadvance()), then passes its output to gui.register(). This is not what you want. Outline of this function's intended use:
local function draw_position()
  xpos = memory.readbyte(...)
  ypos = memory.readbyte(...)
  gui.text(xpos, ypos-8, xpos)
  gui.text(xpos, ypos, ypos)
end
gui.register(draw_position)
So you pass just the name of the function into gui.register(), and you make sure the function updates the values of xpos & ypos before drawing stuff. Hope that's helpful.
IRC nick: UncombedCoconut
Skilled player (1882)
Joined: 4/20/2005
Posts: 2160
Location: Norrköping, Sweden
Thanks nitsujrehtona, everything works fine now. Time to play around with it now. :)
Skilled player (1882)
Joined: 4/20/2005
Posts: 2160
Location: Norrköping, Sweden
Here's a script I made for Duck Hunt. It draws a red box around the duck if you play the "1 duck" game, and if you play the "2 duck" game it will draw a blue box around the duck number 2. The code might be ugly and all, but at least it works. :) It's not modified to work for clay shooting yet.
while true do

local function displayer()

duck1x = memory.readbyte(0x303)
duck1y = memory.readbyte(0x302)
duck2x = memory.readbyte(0x353)
duck2y = memory.readbyte(0x352)

box1xcenter = duck1x
box1ycenter = duck1y
box2xcenter = duck2x
box2ycenter = duck2y
boxwidth    = 32
boxheight   = 32
xoffset     = 0
yoffset     = 8

--Sets the coordinates for the sides of the boxes.
leftside1   = box1xcenter-boxwidth/2  +xoffset
bottomside1 = box1ycenter+boxheight/2 -yoffset
rightside1  = box1xcenter+boxwidth/2  +xoffset
topside1    = box1ycenter-boxheight/2 -yoffset

leftside2   = box2xcenter-boxwidth/2  +xoffset
bottomside2 = box2ycenter+boxheight/2 -yoffset
rightside2  = box2xcenter+boxwidth/2  +xoffset
topside2    = box2ycenter-boxheight/2 -yoffset

--The following if-operations force the boxes to stay on screen, thus avoiding error messages.

if bottomside1>223 then bottomside1 = 223 end
if bottomside1<0   then bottomside1 = 0   end
if topside1   <0   then topside1    = 0   end
if rightside1 >255 then rightside1  = 255 end
if leftside1  <0   then leftside1   = 0   end

if bottomside2>223 then bottomside2 = 223 end
if bottomside2<0   then bottomside2 = 0   end
if topside2   <0   then topside2    = 0   end
if rightside2 >255 then rightside2  = 255 end
if leftside2  <0   then leftside2   = 0   end

--Now it's time to draw the boxes!
if duck1x>0 and duck1y>0 then gui.drawbox(leftside1,bottomside1,rightside1,topside1, "red") end
if duck2x>0 and duck2y>0 then gui.drawbox(leftside2,bottomside2,rightside2,topside2, "blue") end

end

gui.register(displayer)
   FCEU.frameadvance()
end
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
With nitsujrehtona gone, and me back, I'm going to try and pick up where he left. I was going to implement BasicBot from scratch, give it better and faster support and all that, but we talked about it (we being the developers at #fceu on irc, freenode) and we decided to go with the following: - finish lua as started by nitsujrehtona - implement a new basicbot, which serves as a translator between the user and lua. simplified code entered in basicbot fields will be translated to lua and fed to lua - allow users to code directly in lua instead, if they desire to do so Which means we'll have two ways of giving arguments for BasicBot for each field; a very simple language (that of BasicBot) and a scripting language (Lua). The main problem is that none of the people left in the project know much about Lua so bear with us :p I'm diving into it right now and am about to inspect the code nitsujrehtona made. nitsujrehtona, dude, if you're still around, I can sure use a hand :p
qfox.nl
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
The current FCEUX build supports the same Lua code as released by nitsujrehtona (in fact, it's his code). You can get it on SourceForge. I'm working on a BasicBot that works as a translator for those who don't know Lua.
qfox.nl
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
While working on a concept for BasicBot in Lua (only took like two hours, with no prior Lua coding experience, so I guess that was ok) I tested it by porting my 3D world runner script to it. The result is here: http://lua.pastey.net/92325 Neato stuff :D
qfox.nl
Player (120)
Joined: 2/11/2007
Posts: 1522
qFox, you're awesome. So will this script serve as a template, with a GUI to make changes to it?
I make a comic with no image files and you should read it. While there is a lower class, I am in it, and while there is a criminal element I am of it, and while there is a soul in prison, I am not free. -Eugene Debs
Skilled player (1882)
Joined: 4/20/2005
Posts: 2160
Location: Norrköping, Sweden
Here are two questions for you: 1. If I want to fetch the value of RAM address 601D, typing memory.readbyte(6x01D) or memory.readbyte(601D) don't work (it says somwthing about malformed number near '601D'). How do I fetch this value? 2. Is there any way to perform modulo operations in Lua scripting?
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
1: it should be 0x601D 2: math.mod()
qfox.nl
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
Alden: for now it's a template, but at some point in the near future a gui will be built for it to easily fill in those functions. We're just working out the details on the best approach and stuff like that. The script also works for snes9x btw, just add the extra functions for additional buttons.
qfox.nl
Player (120)
Joined: 2/11/2007
Posts: 1522
Don't know if this is feasible, but it would be cool if you could build the GUI in Lua and then make it possible to tweak it / change it entirely (would probably have to have some huge library to import though). I can think of a few applications where it would be nice to have a sort of "control panel"
I make a comic with no image files and you should read it. While there is a lower class, I am in it, and while there is a criminal element I am of it, and while there is a soul in prison, I am not free. -Eugene Debs
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
Yes, one a gui can be constructed with Lua, we are free to do as we please. But for now we are bound by the emulator and so am I...
qfox.nl
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
Ok. Created another script for SMB1 (well, it's my first, but somebody already posted a script for it). This script shows the hitboxes for you and the enemies. When the green boxes collide, so do you. Otherwise you dont collide! (Use it in level 1.2 and watch the pirana's and the elevator near the end, isn't that interesting?). The blue box shows your hitbox for hitting solid level elements like the floor, bricks and whatever. Will (probably) work with the fceu build of nitsujarehtona, or otherwise the current build of FCEUX. Works on mario and duckhunt U rom, but probably any SMB1 rom will do. http://lua.pastey.net/92520 I actually never suspected the hitbox to work like that. Quite interesting. -- I would Youtube it, but it has been bitching all day, not accepting a single video I uploaded, so I'm not going to try.
qfox.nl
Joined: 4/25/2004
Posts: 498
Ooh nifty :) Interestingly (though expectedly, seeing as how the engine is almost exactly the same :p) it also works just fine on SMB2J, although the "generic small" hitbox (used mainly for goombas and piranha plants) is a bit taller...I'm guessing because it makes it easier for upside-down plants close to the ground to hit you. :p
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
Here's a super mario jump script: v1: http://lua.pastey.net/92550 v2: http://lua.pastey.net/92579 (improved landing detection and positioning of results) I'll add a cool screenshot later (it shows you the path's :) Right now I'm thinking something like repeating this script and determine the best ending position each time, continue from there. That ought to bring me close to the end of the level without even doing any enemy detection, I'd say. --- screenshot: The prediction wraps around (that's why you see a few dots on the left). Make sure you have started the game (so press start at the title screen!) because otherwise you'll see crap. I would make a vid, but youtube keeps refusing my vids >:(
qfox.nl
Joined: 4/25/2004
Posts: 498
Oh hey, this scripting thingy is fun. :D Here's one I made for Zelda 2: What it shows: - Enemy health, above their heads. (The left "32" in the pic is due to the Mago teleporting every frame as it randomly picks a spot to appear at. Somewhat amusing. :p) - Just below the status bar: how much damage your sword does, and numerical life and magic values. - At the bottom: how many points you need for level-ups in each category, and how many small and large enemies you need to kill to get the next magic jar or point bag.
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
Nice :) Also what I noticed is that you actually joined here on the same day as me :p
qfox.nl
Joined: 4/25/2004
Posts: 498
*makes a few modifications* Now shows how many times you actually need to hit the enemy; turns the item drop counters into Nifty Little Meters(tm); and squishes everything into the top of the screen since I didn't like how showing stuff at the bottom obstructed the view of the floor, possibly leading to mistiming of water/lava jumps...<_<' http://lua.pastey.net/93478
Active player, Editor (296)
Joined: 3/8/2004
Posts: 7468
Location: Arzareth
Yesterday for the first time I tried a bit of Lua too. I'm making a bot for beating Yie Ar Kung-fu in the fastest time. I posted some source code at http://tasvideos.org/Bisqwit/LuaFunctions.html ― it contains many functions and a framework that might be useful for other bot makers as well.
Joined: 4/25/2004
Posts: 498
Played around with this a bit more... Download: http://stashbox.org/214267/4m_fceux_scripts.zip General: I realized I'd probably use some generic shapes often if I ever made some more scripts like this in the future, so I threw together some sets of drawing commands and stuck 'em in shapedefs.lua. Zelda 2: I finally took the time to figure out where the "is the enemy alive or dead" data is, so no more of this "health text hangs around stuck at 255 after I'm dead" thing. :p Also gave said enemies some nifty lifebars, and changed the item drop meter gfx. ^_^ SMB1: Not much to this one. Just adds a lives counter to the status bar and shows Bowser's health. :p (Though I did solve a mystery that's been bugging me for years. Y'know how Bowser sometimes dies after only 4 fireballs? Well, look at the screenshot...Bowser is actually two 16x24-pixel sprites connected together, and it seems that the game registers a fireball on either half as a hit. You can see that the fireball hit both halves at once...I shot it underneath him as he was coming down from a jump.)
Banned User
Joined: 12/23/2004
Posts: 1850
It started out as something relatively simple (left). Then I kind of got carried away and you get the other one (right). It even has a bonus cheat feature that constantly adds experience. Good for a few dozen levels early on, I guess. Get it here, though why anybody would bother is beyond me.
Perma-banned
1 2
7 8