Related
Hello I am trying to get some data from a text file and put it into a table.
Im not sure how to add more then one pattern while also doing what I want, I know this pattern by its self %a+ finds letters and %b{} finds brackets, but I am not sure how to combine them together so that I find the letters as a key and the brackets as a value and have them be put into a table that I could use.
text file :
left = {{0,63},{16,63},{32,63},{48,63}}
right = {{0,21},{16,21},{32,21},{48,21}}
up = {{0,42},{16,42},{32,42},{48,42}}
down = {{0,0},{16,0},{32,0},{48,0}}
code:
local function get_animations(file_path)
local animation_table = {}
local file = io.open(file_path,"r")
local contents = file:read("*a")
for k, v in string.gmatch(contents, ("(%a+)=(%b{})")) do -- A gets words and %b{} finds brackets
animation_table[k] = v
print("key : " .. k.. " Value : ".. v)
end
file:close()
end
get_animations("Sprites/Player/MainPlayer.txt")
This is valid Lua code, why not simply execute it?
left = {{0,63},{16,63},{32,63},{48,63}}
right = {{0,21},{16,21},{32,21},{48,21}}
up = {{0,42},{16,42},{32,42},{48,42}}
down = {{0,0},{16,0},{32,0},{48,0}}
If you don't want the data in globals, use the string library to turn it into
return {
left = {{0,63},{16,63},{32,63},{48,63}},
right = {{0,21},{16,21},{32,21},{48,21}},
up = {{0,42},{16,42},{32,42},{48,42}},
down = {{0,0},{16,0},{32,0},{48,0}},
}
befor you execute it.
If you insist on parsing that file you can use a something like this for each line:
local line = "left = {{0,63},{16,63},{32,63},{48,63}}"
print(line:match("^%w+"))
for num1, num2 in a:gmatch("(%d+),(%d+)") do
print(num1, num2)
end
This should be enough to get you started. Of course you wouldn't print those values but put them into a table.
I'm currently starting work on a text adventure game in Lua--no addons, just pure Lua for my first project. In essence, here is my problem; I'm trying to find out how I can do a "reverse lookup" of a table using one of its variables. Here's an example of what I've tried to do:
print("What are you trying to take?")
bag = {}
gold = {name="Gold",ap=3}
x = io.read("*l")
if x == "Gold" then
table.insert(bag,gold)
print("You took the " .. gold.name .. ".")
end
Obviously, writing a line like this with every single object in the game would be very... exhausting--especially since I think I'll be able to use this solution for not just taking items but movement from room to room using a reverse lookup with each room's (x,y) coordinates. Anyone have any ideas on how to make a more flexible system that can find a table by the player typing in one of its variables? Thanks in advance!
-blockchainporter
This doesn't directly answer your question as you asked it, but I think it would serve the purpose of what you are trying to do. I create a table called 'loot' which can hold many objects, and the player can place any of these in their 'bag' by typing the name.
bag = {}
loot = {
{name="Gold", qty=3},
{name="Axe", qty=1},
}
print("What are you trying to take?")
x = io.read("*l")
i = 1
while loot[i] do
if (x == loot[i].name) then
table.insert(bag, table.remove(loot,i))
else
i = i + 1
end
end
For bonus points, you could check 'bag' to see if the player has some of that item already and then just update the quantity...
while loot[i] do
if (x == loot[i].name) then
j, found = 1, nil
while bag[j] do
if (x == bag[j].name) then
found = true
bag[j].qty = bag[j].qty + loot[i].qty
table.remove(loot,i)
end
j = j + 1
end
if (not found) then
table.insert(bag, table.remove(loot,i))
end
else
i = i + 1
end
end
Again, this isn't a 'reverse lookup' solution like you asked for... but I think it is closer to what you are trying to do by letting a user choose to loot something.
My disclaimer is that I don't use IO functions in my own lua usage, so I have to assume that your x = io.read("*l") is correct.
PS. If you only ever want objects to have a name and qty, and never any other properties (like condition, enchantment, or whatever) then you could also simplify my solution by using key/val pairs:
bag = {}
loot = { ["Gold"] = 3, ["Axe"] = 1 }
print("What are you trying to take?")
x = io.read("*l")
for name, qty in pairs(loot) do
if x == name then
bag.name = (bag.name or 0) + qty
loot.name = nil
end
end
I have a few notes to start before I specifically address your question. (I just want to do this before I forget, so please bear with me!)
I recommend printing to the terminal using stderr instead of stdout--the Lua function print uses the latter. When I am writing a Lua script, I often create a C-style function called eprintf to print formatted output to stderr. I implement it like this:
local function eprintf(fmt, ...)
io.stderr:write(string.format(fmt, ...))
return
end
Just be aware that, unlike print, this function does not automatically append a newline character to the output string; to do so, remember to put \n at the end of your fmt string.
Next, it may be useful to define a helper function that calls io.read("*l") to get an entire line of input. In writing some example code to help answer your question, I called my function getline--like the C++ function that has similar behavior--and defined it like this:
local function getline()
local read = tostring(io.read("*l"))
return read
end
If I correctly understand what it is you are trying to do, the player will have an inventory--which you have called bag--and he can put items into it by entering item names into stdin. So, for instance, if the player found a treasure chest with gold, a sword, and a potion in it and he wanted to take the gold, he would type Gold into stdin and it would be placed in his inventory.
Based on what you have so far, it looks like you are using Lua tables to create these items: each table has a name index and another called ap; and, if a player's text input matches an item's name, the player picks that up item.
I would recommend creating an Item class, which you could abstract nicely by placing it in its own script and then loading it as needed with require. This is a very basic Item class module I wrote:
----------------
-- Item class --
----------------
local Item = {__name = "Item"}
Item.__metatable = "metatable"
Item.__index = Item
-- __newindex metamethod.
function Item.__newindex(self, k, v)
local err = string.format(
"type `Item` does not have member `%s`",
tostring(k)
)
return error(err, 2)
end
-- Item constructor
function Item.new(name_in, ap_in)
assert((name_in ~= nil) and (ap_in ~= nil))
local self = {
name = name_in,
ap = ap_in
}
return setmetatable(self, Item)
end
return Item
From there, I wrote a main driver to encapsulate some of the behavior you described in your question. (Yes, I know my Lua code looks more like C.)
#!/usr/bin/lua
-------------
-- Modules --
-------------
local Item = assert(require("Item"))
local function eprintf(fmt, ...)
io.stderr:write(string.format(fmt, ...))
return
end
local function printf(fmt, ...)
io.stdout:write(string.format(fmt, ...))
return
end
local function getline()
local read = tostring(io.read("*l"))
return read
end
local function main(argc, argv)
local gold = Item.new("Gold", 3)
printf("gold.name = %s\ngold.ap = %i\n", gold.name, gold.ap)
return 0
end
main(#arg, arg)
Now, as for the reverse search which you described, at this point all you should have to do is check the user's input against an Item's name. Here it is in the main function:
local function main(argc, argv)
local gold = Item.new("Gold", 3)
local bag = {}
eprintf("What are you trying to take? ")
local input = getline()
if (input == gold.name) then
table.insert(bag, gold)
eprintf("You took the %s.\n", gold.name)
else
eprintf("Unrecognized item `%s`.\n", input)
end
return 0
end
I hope this helps!
As you can tell I'm a beginner in lua. I am trying to understand a function I'm stuck at what the following code segment does?
It is used in the following code snippet in the last line:
function classify(txt_dir, img_dir, cls_list)
local acc = 0.0
local total = 0.0
local fea_img = {}
local fea_txt = {}
for fname in io.lines(cls_list) do
local imgpath = img_dir .. '/' .. fname .. '.t7'
local txtpath = txt_dir .. '/' .. fname .. '.t7'
fea_img[#fea_img + 1] = extract_img(imgpath)
fea_txt[#fea_txt + 1] = extract_txt(txtpath)
end
for i = 1,#fea_img do
-- loop over individual images.
for k = 1,fea_img[i]:size(1) do
local best_match = 1
local best_score = -math.huge
for j = 1,#fea_txt do
local cur_score = torch.dot(fea_img[i][{k,{}}], fea_txt[j])
From my understanding, fea_img is a lua table. Is the line fea_img[i][{k,{}}] some sort of slicing for the value for the key 'i' in the table fea_img?
I tried searching for more examples and found this being used here too (last line):
for i = 1,nsamples,batchsize do
-- indices
local lasti = math.min(i+batchsize-1,nsamples)
local m = lasti - i + 1
-- k-means step, on minibatch
local batch = x[{ {i,lasti},{} }]
Any help on this would be really appreciated. Thank you!
In lua you can access a specific index on a table in multiple ways. Like these two examples
local myValue = someTable.theIndex
-- or
local myOtherValue = someTable[2]
So the construct you see here is to access some values from a (nested) table.
Also in lua you can use anything except nil as a index, so even tables are possible.
The line
fea_img[i][{k,{}}]
Can be extended to this:
local index1 = i -- i in this case is your loop variable
local index2 = { k , { } } -- This creates a table with 2 values, the first one will be the vaule of the var k, the second one is an empty table
local value1 = fea_img[index1] -- This will get you a table
local value2 = value1[index2] -- This will get the same as: fea_img[i][{k,{}}]
Correction and Addition:
As Nicol Bolas already said in the comments: The index must be an exact match. Which means it literally has to be the same table, which is not the case for the presented code from you. Either you dropped code you thought is unnecessary or fea_img has some some kind of metatable on it.
In the case of
local k = 2
local table1 = {k, { } }
local table2 = {k, { } }
table2 and table1 do have the exact same content. But they are not the same table. Which will lead to nil always being retrieved if one is used to store data in a table and the other is used to get it back.
Syntactically, t[k] is indexing a table with a key. Normally, if there is a record in the table with the key k, its value is returned. Nothing more, nothing less.
If fea_img[i] was a normal table, {k,{}} would always return nil, since table indices are resolved based on their identity ({k,{}} is always a new table). Based on your code, I have to conclude that the elements of fea_img (i.e. what extract_img returns) are not normal tables.
In Lua, you can override the indexing operation using a metatable. If you index a value that has a metatable with __index, it will be used if there is no matching record in the table:
local t = {}
setmetatable(t, {
__index = function(t, k)
return k
end
})
print(t[{}])
This table has a metatable associated with it, which is used in the indexing operation. In this case __index returns the key, but whatever library you are using might provide more complex behaviour.
This is specific to the library you are using, not something related to the Lua syntax.
I make a function to parsing path name and file name from a computer directory using Lua Cheat Engine, next I want store the results in to a Lua table.
My function :
function addSongList()
load_dialog = createOpenDialog(self)
load_dialog.InitalDir = os.getenv('%USERPROFILE%')
load_dialog.Filter = 'MP3 files|*.mp3|*'
load_dialog.execute()
file = load_dialog.FileName
if file then
--- parsing path and filename
local pathN = file:match("(.*[\\/])")
local path, name = file:match('(.*\\)(.*)%.mp3')
--- test to open E:\MyMP3\mysong.mp3
print(pathN) --- result : E:\MyMP3\
print(name) --- result : mysong.mp3
end
end
local mp3Table = {}
table.insert(mp3Table,{pathN,name})
Is this correct way and correct syntax using table.insert(mp3Table,{pathN,name})
How to check if elements already added to the table by print out them?
How to clearing / empty the table ?
Thank you
1 - Inserting to the table:
table.insert(tb, value) inserts the value to de table tb. Using table.insert(mp3Table,{pathN,name}) you are dynamically creating a (sub)table and then appending to the main one.
2 - Printing the table.
As already pointed out you can just traverse the table using pairs or ipairs in order to get the elements.
I prefer ipairs in this case because the table is numerically indexed and order is guaranteed in accordance to table.insert.
The inner table must be indexed by numbers because you created it usign numeric indices.
for k, v in ipairs(mp3Table) do
print(v[1], v[2])
end
But you can also opt for a metatable which will also give you the possibility to generate a string representation for the table:
mp3Table_mt =
{
__tostring = function(self)
local ret = {}
for k, v in ipairs(self) do
table.insert(ret, v[1] .. "\t" .. v[2])
end
return table.concat(ret, "\n")
end
}
When initializing mp3Table you have to assign the metatable
local mp3Table = setmetatable({}, mp3Table_mt)
Then you can just tell Lua to print the table:
print(mp3Table)
3 - Empty/Delete the table:
Well there are two different things here. One is empty another is delete.
Lua uses garbage collection so actual deleting only occurs when there are no more references to a particular table. What you can do to tell Lua you no longer need a variable is assing nil to it. If there is no other reference to the value your variable was pointing to, the GC will clean it when it runs.
But you can empty the table without deleting it.
It may be tempting to say that mp3Table = {} "empties the table". But it does not.
What you are doing in this case is assigning a fresh new table to mp3Table variable. And if any other variable is still pointing to the old table it will no get collected and the inner values will remain untouched. If there's no such other variable, the table will be garbage collected just as if you assigned nil to mp3Table variable.
So to effectivelly empty a table you have to traverse it and set all its variables to nil.
function clearTable(tb)
for i, v in pairs(tb) do
tb[i] = nil
end
end
Specifically in the case asked, just assigning a new table to mp3Table may be enough because there are no more references to the same table. Assign nil afterwards is not necessary. What matters is if there are variables pointing to the same value. If you know what you are doing and the consequenses then no problem go ahead.
Putting it all together:
mp3Table_mt =
{
__tostring = function(self)
local ret = {}
for k, v in ipairs(self) do
table.insert(ret, v[1] .. "\t" .. v[2])
end
return table.concat(ret, "\n")
end
}
function addSongList(mp3Table)
local load_dialog = createOpenDialog(self)
load_dialog.InitalDir = os.getenv('%USERPROFILE%')
load_dialog.Filter = 'MP3 files|*.mp3|*'
load_dialog.execute()
file = load_dialog.FileName
if file then
--- parsing path and filename
local pathN = file:match("(.*[\\/])")
local path, name = file:match('(.*\\)(.*)%.mp3')
--- test to open E:\MyMP3\mysong.mp3
print(pathN) --- result : E:\MyMP3\
print(name) --- result : mysong.mp3
table.insert(mp3Table,{pathN,name})
end
return mp3Table
end
function clearTable(tb)
for i, v in pairs(tb) do
tb[i] = nil
end
end
local mp3Table = setmetatable({}, mp3Table_mt)
print(addSongList(mp3Table))
clearTable(mp3Table) -- I'm not assigning a new one. Just clearing the fields.
print(mp3Table) -- Must print nothing
1)yes
2)printing table in cycle:
for k,v in pairs(mp3Table) do
print( v.pathN, v.name)
end
3)empty table
mp3Table = {} -- clean
mp3Table = nil -- delete
I wonder how does table.insert work in lua?!
I am asking this because I have tried to use it on a custom table with __newindex metamethod
but it seems not to call it. Is there a way to make my custom table functionality to work with table.insert?!
From my humble knowledge about the language I would say it uses something like rawset or something maybe I donno.
Sample I worked on:
do
tabl = {1,2,3}
local _tabl = tabl
tabl = {}
local mt = { __newindex = function(t,k,v) print"changing" ;_tabl[k] = v end, __index = _tabl}
setmetatable(tabl,mt)
end
tabl[4] = 4; --prints "changing"
table.insert(tabl,5) -- prints nothing!!
There's no such metamethod, table.insert just inserts a new value to a specified table.
local myTable = {}
table.insert(myTable, "somestring")
-- so now myTable has one value, myTable = { "somestring" }
It works like:
local myTable = {}
myTable[#myTable + 1] = "somestring"
__newindex metamethod affects only assignment operator "=", table.insert is just a separate function not related with metatables, you can modify the behaviour of this function if you want:
_tableinsert = table.insert
function table.insert(t, v)
-- here your actions, before real function will be used
_tableinsert(t, v)
end
I think that would be possible to make your own metamethod __tableinsert this way.
table.insert does, in fact, use rawset. See the lua 5.1 source here.
As indicated if you do the assignment yourself you should be able to get the behavior you want.