1 2
7 8 9
Masterjun
He/Him
Site Developer, Skilled player (1970)
Joined: 10/12/2010
Posts: 1179
Location: Germany
MUGG wrote:
Is it possible to assign a function to a table, as opposed to the function result?
Language: lua

local function foo() print("a") end local function cool() print("c") end local t = {foo, function() print("b") end} -- either use the function name, or define it in there table.insert(t,cool) -- or insert it later t["DoTheThing"] = function() print("d") end -- or just set it t[1]() -- prints a t[2]() -- prints b t[3]() -- prints c t["DoTheThing"]() -- prints d
Warning: Might glitch to credits I will finish this ACE soon as possible (or will I?)
Editor, Player (163)
Joined: 4/7/2015
Posts: 329
Location: Porto Alegre, RS, Brazil
£e Nécroyeur wrote:
Is there a method to change the orientation (i.e. rotate) lua's displayed output?
As zeromus said, you could rotate it externally. One method I can see is using LuaGD. Download the LuaGD files, extract and copy the dll files into the folder your script is in, then start using the API (for your case, you might use gd.copyRotated), paying attention to always use
Language: lua

gd = require"gd"
in the beginning of the code. After the manipulations, you could save the image and print it in the BizHawk screen, but this sounds laggy if you wanna update the image every frame. You'll have to experiment solutions.
Games are basically math with a visual representation of this math, that's why I make the scripts, to re-see games as math. My things: YouTube, GitHub, Pastebin, Twitter
Post subject: Dealing with big numbers (base16 version)
Editor, Experienced player (817)
Joined: 5/2/2015
Posts: 671
Location: France
I have disassembled an RNG subroutine and am trying to re-implement it in Lua. The hard part is this MUL instruction (I put the ones above for context, platform is GBA):
Language: asm

ROM:0800F908 LDR R3, =0x30016C0 ROM:0800F90A LDR R2, [R3] ROM:0800F90C LDR R0, =0x41C64E6D ROM:0800F90E MUL R0, R2
A small explaination: First it reads from the RNG adress, then multiplies it by 0x41C64E6D, and keeps the last 32 significant bits. So if the value after multiplying was 0x273219DA6F3, then the value of r0 would be 0x219DA6F3. I tried to re-implement this in Lua, but my problem is that the numbers in Lua don't have enough precision to deal with such large values. And I don't need to be able to only get the result of the multiplication, but also to be able to get the last 32 bits. So I tried with a library Masterjun recommended me, BigNum, and it somewhat works but it's old (when I renamed some function which was needed for it to run, it gave me a wrong result for multiplication) Would there be any way to implement this?
Post subject: Re: Dealing with big numbers (base16 version)
Player (142)
Joined: 7/16/2009
Posts: 686
xy2_ wrote:
I tried to re-implement this in Lua, but my problem is that the numbers in Lua don't have enough precision to deal with such large values.
They do, though. Numbers are in double-precision floating-point format, which can accurately represent integers up to 53 bits.
xy2_ wrote:
Would there be any way to implement this?
For powers of two, taking the last n bits is the same as taking the remainder of the division by 2n (so modulo). As such, for getting the last 32 bits doing
Language: lua

local result = value % 0x100000000
will work.
Post subject: Re: Dealing with big numbers (base16 version)
Noxxa
They/Them
Moderator, Expert player (4137)
Joined: 8/14/2009
Posts: 4083
Location: The Netherlands
Scepheo wrote:
They do, though. Numbers are in double-precision floating-point format, which can accurately represent integers up to 53 bits.
Which may not be enough when you're multiplying two 32-bit integers.
http://www.youtube.com/Noxxa <dwangoAC> This is a TAS (...). Not suitable for all audiences. May cause undesirable side-effects. May contain emulator abuse. Emulator may be abusive. This product contains glitches known to the state of California to cause egg defects. <Masterjun> I'm just a guy arranging bits in a sequence which could potentially amuse other people looking at these bits <adelikat> In Oregon Trail, I sacrificed my own family to save time. In Star trek, I killed helpless comrades in escape pods to save time. Here, I kill my allies to save time. I think I need help.
Masterjun
He/Him
Site Developer, Skilled player (1970)
Joined: 10/12/2010
Posts: 1179
Location: Germany
String arithmetic!
Language: lua

local chars = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"} function add(a,b,base) base = base or 10 local ret = "" while a:sub(1,1)==chars[1] and #a>1 do a=a:sub(2) end while b:sub(1,1)==chars[1] and #b>1 do b=b:sub(2) end while #a<#b do a=chars[1]..a end while #b<a>= base then cur = cur - base c = true end ret = chars[cur+1]..ret end if c then ret = chars[2]..ret end return ret end function mult(a,b,base) base = base or 10 local ret = "" while #a<#b do a=chars[1]..a end while #b<#a do b=chars[1]..b end for i = 1,#a do ret = ret..chars[1] for i=1,tonumber(a:sub(i,i),base) do ret = add(ret,b,base) end end return ret end
Arguments a and b are strings in base base. The base is optional and 10 if not given. The result is a string in base base. Example: mult("B65698F7","41C64E6D",16) gives "2ED93BAD0B84632B". The last 32 significant bits are just the last 8 characters, so result = mult("B65698F7","41C64E6D",16) print(result:sub(-8)) gives 0B84632B. (Additional symbols have to be added to chars for higher bases than 16).
Warning: Might glitch to credits I will finish this ACE soon as possible (or will I?)
Post subject: Re: Dealing with big numbers (base16 version)
Player (142)
Joined: 7/16/2009
Posts: 686
Mothrayas wrote:
Which may not be enough when you're multiplying two 32-bit integers.
Correct, of course, but it is enough for multiplying a 32-bit number and a 16-bit number. So, split the multiplier 0x41C64E6D into 0x41C6 (high) and 0x4E6D (low), multiply your value by those, drop the irrelevant bits (modulo again), multiply the high result with 0x10000 to get it back in range and add them. My previous post was mostly meant as two hints to a solution, rather than a full implementation thereof. EDIT: Here's some code:
Language: lua

function mul(value) local high = (value * 0x41C6) % 0x10000 local low = (value * 0x4E6D) % 0x100000000 return (low + high * 0x10000) % 0x100000000 end
Skilled player (1705)
Joined: 9/17/2009
Posts: 4952
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
I wish to keep track of individual enemies. Right now, I have a for loop that starts from some beginning address to some final one, but attempting to toggle it to display individual npcs made it confusing. I'm trying to instead make it like classes:
Language: lua

local Enemy_data = { Level, HP_Max, HP_Now, DP, Speed, Attack, Defence, Special, Nature, FD, Friend, Attack1, Attack2, Attack3, Attack4 }
Then have npcs 1,2,3...N all refer to copies of that class. I realized I have no idea how to do this other than copypasting the above N amount of times. Searching for lua classes gave this, but I'm not exactly sure how to implement it. Any hints please?
Editor, Skilled player (1171)
Joined: 9/27/2008
Posts: 1085
Oh, now that's an interesting page. What's this metatable thing? I'll admit there's a few things I still don't know. Well, I get the impression you want to do something like this: Enemy[1].HP_Now Enemy[6].Attack This would require another table. In this sense, you can do a for loop to create each thing. Making it shouldn't be too rough.
Language: lua

local function GetStats(addr,o) o= o or {} --Construct a table if we didn't get one o.HP_Now= memory.read_u16_le(addr+0x00) --... And so on return o end local Enemy= {} for i= 1, 6 do Enemy[i]= GetStats(0x8000 + i*0x60) end
Reading it wouldn't be too hard, either.
Language: lua

for i= 1, #Enemy do local Cur_Enemy= Enemy[i] if Cur_Enemy.HP_Now > 0 then SomeKindOfCode() end end
This is sort of what I'm thinking of. Is this the right sort of direction you want? Or would you prefer full-blown class style treating each table like a full object?
Editor, Expert player (2312)
Joined: 5/15/2007
Posts: 3855
Location: Germany
If I save an object Actor in a table like this,
Language: Lua

roomData[currentRoom][2] = Actor
does it save the keys/values themselves or just a reference to the object Actor?
Editor, Skilled player (1171)
Joined: 9/27/2008
Posts: 1085
roomData[currentRoom][2] will contain the same reference as Actor, and modifying elements within Actor elsewhere will also change elements within roomData[currentRoom][2], as they point to the same object. Creating a copy of a table, as opposed to simply assigning another reference, is a little more involved.
Skilled player (1705)
Joined: 9/17/2009
Posts: 4952
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
FatRatKnight wrote:
Oh, now that's an interesting page. What's this metatable thing? I'll admit there's a few things I still don't know. Well, I get the impression you want to do something like this: Enemy[1].HP_Now Enemy[6].Attack This would require another table. In this sense, you can do a for loop to create each thing. This is sort of what I'm thinking of. Is this the right sort of direction you want? Or would you prefer full-blown class style treating each table like a full object?
Yes, this is what I had in mind. Thanks very much!
Editor, Expert player (2312)
Joined: 5/15/2007
Posts: 3855
Location: Germany
FatRatKnight wrote:
Creating a copy of a table, as opposed to simply assigning another reference, is a little more involved.
How to do it in this case? This doesn't seem to be working:
		for key, val in pairs(Actor) do
			roomData[currentRoom][2].key = val
		end
Amaraticando
It/Its
Editor, Player (157)
Joined: 1/10/2012
Posts: 673
Location: Brazil
There're at least two kinds of copies: http://lua-users.org/wiki/CopyTable
Editor, Expert player (2312)
Joined: 5/15/2007
Posts: 3855
Location: Germany
Deepcopy seems to be doing what I want. Thank you! I can now go on with my lua game.
Editor, Skilled player (1171)
Joined: 9/27/2008
Posts: 1085
for key, val in pairs(Actor) do
	roomData[currentRoom][2].key = val
end
As an aside, using .key in this case more literally translates to ["key"], as in you're specifically selecting the element indexed by the string "key" over and over again, as opposed to the key value you wanted, which could be other sorts of things, and most certainly not just a repetition of "key" over and over. More appropriate for the loop would be: roomData[currentRoom][2][key] = val But things are cleared up anyway.
Editor, Expert player (2312)
Joined: 5/15/2007
Posts: 3855
Location: Germany
input.get() returns a table that has pressed buttons as true, and non-pressed buttons as nil. I would like to do something based on new button presses instead of buttons "held down". For example, my character should jump only if I newly press the up arrow when he is on the ground. How should I do this? Deepcopying the input.get() table to a previous variable and comparing, or otherwise saving the input.get() table values to previous variables and comparing, didn't work for me so far.
Editor, Skilled player (1171)
Joined: 9/27/2008
Posts: 1085
I have created a function that I've relied on in a few scripts for exactly this.
Language: lua

local keys,lastkeys= {},{} local function UpdateKeys() lastkeys= keys keys= input.get() end local function Press(k) return keys[k] and not lastkeys[k] end while true do UpdateKeys() if Press("A") then --Triggered once whenever you press A --Insert generous amounts of code here --Wait, try to keep the code readable... end if keys["J"] then --Triggered repeatedly while holding J --Insert other sorts of code here end emu.frameadvance() end
No need for a deep copy here. Just reassign the tables you get. Just make sure you assign the old table to the old variable before you get the new table. We don't need to properly copy every individual element, as input.get keeps spitting out a new table each time, and each table already holds all the information on the keys. However, I'm not entirely familiar with BizHawk's functions. Since I used emu.frameadvance(), the script isn't re-running the code while emulation is paused, so one might want to look over the function list for a better fit.
Editor, Expert player (2312)
Joined: 5/15/2007
Posts: 3855
Location: Germany
Thank you!
Language: Lua

local actorMove = { (...) ["Dies"] = function(x) Actor[x].HP = -1 Actor[x].deathframes=100 end, ["Damage"] = function(x,damage,reason) if Actor[x].invulnTime<1 then Actor[x].HP = Actor[x].HP - damage end if Actor[x].HP<0 then actorMove["Dies"](x) Actor[x].deathReason = reason end end, (...) }
I'm getting an error because of the line actorMove["Dies"](x). The damage function can't call the dies function. If it's outside of a table, it works fine. Is there a way to make it work in a table? I remember javascript can use expressions such as this.["Dies"]...
Editor, Skilled player (1171)
Joined: 9/27/2008
Posts: 1085
Language: lua

local actorMove= {} actorMove["Dies"]= function(x) -- ... end actorMove["Damage"]= function(x,damage,reason) -- ... end
Doing it like this might work. Create the table first, then stuff it with the functions, rather than define the functions in the table constructor. As I understand lua variables, a variable defined on the spot can't refer to itself. Having local a= a, for example, will have the script look for a different variable a within scope to put into the local a you're defining right there. In your case, since the table isn't finished being constructed for the local variable you're making, any references to that name isn't looking for that local definition on that spot. It's looking for another actorMove that may have been defined earlier, or even a global one, anything within scope other than itself, essentially. Mostly going off of memory here, but just in case, create a function SelfAware() print(type(actorMove)) end and see what it gives you in your structure, and if you were to try my suggestion.
Editor, Expert player (2312)
Joined: 5/15/2007
Posts: 3855
Location: Germany
Thanks, your first suggestion works!
Skilled player (1650)
Joined: 7/1/2013
Posts: 433
Thank you, zeromus and brunovalads. I had a feeling this was nonstandard usage.
Editor, Expert player (2312)
Joined: 5/15/2007
Posts: 3855
Location: Germany
Note: I fixed the problem I'm describing here, see the edit below. I'm using lua to press keys on the keyboard, in order to tilt GBA Yoshi Topsy-Turvy. The tilt is delayed one frame which is fine, except when I want to load a state... For example, I want to keep tilting right: frame 1: tiltRight frame 2: tiltRight frame 3: tiltRight -- I save a state here frame 4: whatever I load the state and do frame 4: tiltRight but at this point, it behaves as if I didn't tiltRight on frame 3. A way to work around this is to hold the tiltRight key and load the state. But it's very unintuitive and would leads to mistakes if I had to remember this every time I need to loadstate. I was wondering if it's possible to fix this, maybe by using userdata functions (to save the info that I did tiltRight on frame 3, so after loadstating, it does the tiltRight automatically). I'm not familiar with those functions, so I would appreciate your help. My current script that has the behavior as explained above is here line 523 in the pastebin. Edit: I found a solution. Userdata wasn't of any help because the code is always executed at the end of a frame. So I put the tilt function like this:
Language: Lua

event.onframestart(function() if Displays[4][2] then -- "tilt" is active doTilt() end end)
and it behaves perfectly now!
Skilled player (1705)
Joined: 9/17/2009
Posts: 4952
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Recently, I encountered this: https://springrts.com/wiki/Lua_Performance Basically, it recommends localizing globals for faster performance. Does anyone have knowledge on should that be naively done inside a while true emu.frameadvance() loop like the ones for BizHawk?
Masterjun
He/Him
Site Developer, Skilled player (1970)
Joined: 10/12/2010
Posts: 1179
Location: Germany
Yes locals are faster. Yes they are faster everywhere. Yet I don't understand your question.
Warning: Might glitch to credits I will finish this ACE soon as possible (or will I?)
1 2
7 8 9