Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ Lua ➜ Using function arguments to call a table

Using function arguments to call a table

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Daved   (12 posts)  Bio
Date Fri 22 Apr 2011 11:36 PM (UTC)

Amended on Sat 23 Apr 2011 12:13 AM (UTC) by Daved

Message
The tables in my combat system for aetolia look like this:



limbs_list = { 
	"left leg",
	"right leg",
	"left arm",
	"right arm",
	"head",
	"torso"
} --limbs_list

limbs_default = { -- default values for all limbs
	["damage"] = 0,
	["parrying"] = false,
	["needparry"] = false,
	["triedparry"] = false,
	["lasttriedparry"] = 0,
	["lasthit"] = false,
	["restoring"] = false,
	["broken"] = false,
	["damaged"] = false,
	["mangled"] = false,
	["worst"] = false
} -- limbs_default

limb_vars = {
	"damage",
	"parrying",
	"needparry",
	"triedparry",
	"lasttriedparry",
	"lasthit",
	"restoring",
	"broken",
	"damaged",
	"mangled",
	"worst"
} -- limb_vars
	
my_limbs = {} -- initialize my limb table
	
for _, cur_limb in ipairs (limbs_list) do -- populate my limb table with limbs
	my_limbs[cur_limb] = {}
	for _, cur_var in ipairs (limb_vars) do -- populate my limb tables's limbs with variables
		my_limbs[cur_limb][cur_var] = limbs_default[cur_var] -- set all those values for each limb to their default value
	end -- for limb_vars
end -- for limbs_list

target_limbs = {} -- initialize my target's limb table
	
for _, cur_limb in ipairs (limbs_list) do -- populate my limb table with limbs
	target_limbs[cur_limb] = {}
	for _, cur_var in ipairs (limb_vars) do -- populate my limb tables's limbs with variables
		target_limbs[cur_limb][cur_var] = limbs_default[cur_var] -- set all those values for each limb to their default value
	end -- for limb_vars
end -- for limbs_list



There is a very similar structure for tables to track my and my opponent's balances, afflictions, etc.

Currently, my functions for retrieving useful values from those tables look like:


function GetLimbs(var, limb) -- returns the value of a given variable for a given limb
	return (my_limbs[limb][var])
end -- func

function GetTargetLimbs(var, limb) -- returns the value of a given variable for my target's given limb
	return (target_limbs[limb][var])
end -- func


Again a similar structure for the other types of information.

I would like a more general function, one to retrieve any value from any table, something like


function Get(who, table, key1, key2)
	return (who_table[key1][key2])
end -- func


But that syntax isn't working, most likely because
Get("my", "limbs", "left arm", "parrying") is trying to return who_table too literally, or doesn't know what to do with the string values of those two arguments (who and table) in the context of processing them as variable names.

I recognize that this could be done by combining all my tables into one super table i.e.


function Get(who, table, key1, key2)
	return (AMTS_vars[who][table][key1][key2])
end -- func

Get("my", "limbs", "left arm", "parrying") 

--would then return the value of AMTS_vars["my"]["limbs"]["left arm"]["parrying"]



But surely that's not my only recourse! Halp?

For a more illustrative and slightly simpler example of what I am trying to do, have a look here: http://pastebin.com/S07m4u69

Top

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #1 on Sat 23 Apr 2011 12:28 AM (UTC)
Message
Daved said:

function Get(who, table, key1, key2)
	return (who_table[key1][key2])
end -- func

who, table, and who_table are three entirely separate variable names. An underscore isn't an operator, it's just a part of a name.

Also, I think your function is a little general. If you can do this...
Get("my", "limbs", "left arm", "parrying")
...then why can't you just do this?
return my_limbs["left arm"]["parrying"]


As a suggestion, why don't you do this:
local me = {
  limbs = {},
}

local target = {
  limbs = {},
}

Then you can use Get(me, "limbs", "left arm", "parrying") - notice that I'm passing the table in as the first argument, not a string. It's still a bit pointless since you can just do me.limbs["left arm"]["parrying"], but there you go.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #2 on Sat 23 Apr 2011 12:30 AM (UTC)
Message

function Get(who, table, key1, key2)
	return (who_table[key1][key2])
end -- func


A simple modification would be simply pass down the table, eg.


function Get(t, key1, key2)
	return (t[key1][key2])
end -- func

...

Get(my_limbs, "left arm", "parrying")


Although I agree also with Twisol.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Daved   (12 posts)  Bio
Date Reply #3 on Sat 23 Apr 2011 04:58 AM (UTC)

Amended on Sat 23 Apr 2011 07:57 AM (UTC) by Daved

Message
Thanks folks, your answers helped me realise a fundamental flaw between how I wanted to organize my variables this time around and what I was doing. What I was trying to do is have all my variables be referenced by a numerically indexed nested table. I was indexing the subtables with strings!

I searched the forums for a bit to discover some method to index my tables in this manner and came across the table.insert function.

Playing with this function a bit I found I could create such a table by using table.insert in an innermost table -> outermost table order:


iAfflictions = {}
iHerbs = {}
iBloodroot = {}
iParalysis = {}
iState = {
	false
}
iTried = {
	false
}
function IndexAffTable()
	table.insert(iParalysis, iState)
	table.insert(iParalysis, iTried)
	table.insert(iBloodroot, iParalysis)
	table.insert(iHerbs, iBloodroot)
	table.insert(iAfflictions, iHerbs)
end


compare to defining tables like so:


dAfflictions = {
	dHerbs = {
		dBloodroot = {
			dParalysis = {
				dState = {
					false
				}, -- state
				dTried = {
					false
				}, -- tried
			}, --paralysis
		}, --bloodroot
	}, -- herbs
} --afflictions


When I tprint(iAfflictions) I get

1:
  1:
    1:
      1:
        1=false
      2:
        1=false


compared to tprint(dAfflictions)

"dHerbs":
  "dBloodroot":
    "dParalysis":
      "dState":
        1=false
      "dTried":
        1=false


However, the function I'm using - IndexAffTable() is rather clumsy in structure and not easily generalized to other tables. What I seem to need is a mechanism to convert strings to objects so that I can store the names of subtables to be indexed in an intermediary table and have an ipairs loop to table.insert the subtables into each other. Any advice?

EDIT: For the sake of clarity, I'm trying to construct something more like this:


iAffCure = {
	"iHerb",
	"iSalve"
}

iAffHerb = {
	"iBloodroot",
	"iGoldenseal"
}

iAffBR = {
	"iParalysis",
	"iSlickness"
}

iAffGS = {
	"iStupidity",
	"iImpatience"
}

iAffVars = {
		"iState",
		"iTried",
		"iLastTried"
} -- affliction_variables

iState = {
	false
}
iTried = {
	false
}
iLastTried = {
	[1] = 0
}

iAfflictions = {}
iHerb = {}
iBloodroot = {}
iGoldenseal = {}


function LoopIndexAffTable()
	for a, b in ipairs (iAffCure) do
		if (b == "iHerb") then
			for c, d in ipairs (iAffHerb) do
				if (d == "iBloodroot") then
					for e, f in ipairs (iAffBR) do
						for g,h in ipairs (iAffVars) do
							table.insert(f, h)
						end -- for iAffVars
						table.insert(d, f)
					end -- for iAffBR
				elseif (d == "iGoldenseal") then
					for e, f in ipairs (iAffGS) do
						for g, h in ipairs (iAffVars) do
							table.insert(f, h)
						end -- for iAffvars
						table.insert(d, f)
					end -- for iAffGS
				end -- if d ==
				table.insert(b, d)
			end -- for iAffHerb
		end -- if b==
		table.insert(iAfflictions, b)
	end -- for iAffCure
end -- func


But of course that doesn't work because the indexed values of all of those tables are strings, and table.insert doesn't want to use strings.

Ideally looking for something that works more broadly, like

function IndexSubTables(tbl, stbl)
	for a, b in ipairs (stbl) do
		for c, d in ipairs (b) do
			for e, f in ipairs (d) do
				for g,h in ipairs (f) do
					table.insert(f, h)
				end -- for g,h
				table.insert(d, f)
			end -- for e,f
			table.insert(b, d)
		end -- for c, d
		table.insert(tbl, b)
	end -- a, b
end -- func
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #4 on Sat 23 Apr 2011 06:09 AM (UTC)
Message
I think it's too complicated.

There's nothing wrong with using string table keys. It's too roundabout IMO to have numeric keys, and then iterate through it to find a matching name. That's what string keys are for.

The only time I would use numeric keys was when I cared about the order (eg. cure X before Y) and you can do that by having a second table (a sequence table) but still keep your main data in a table keyed by name.

I think there is a fair bit about it here:

Template:post=6074 Please see the forum thread: http://gammon.com.au/forum/?id=6074.



- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


19,834 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.