table returning nil value when calling function - function

I'm trying to pass a table through several functions and return it, but it only works to a certain degree. I'm almost sure it has to do something with the scoping, but I can't work it out since I'm new with LUA.
I tried putting the table in line 1 and setting it global, but to no avail.
Error: bag argument: expected table but got nil.
function returnToTunnel(movementTable)
for i = table.maxn(movementTable), 1, -1 do --this is where I get the error.
if (movementTable[i] == 1) then
turtle.down()
elseif (movementTable[i] == 2) then
turtle.up()
elseif (movementTable[i] == 3) then
turtle.back()
turtle.turnRight()
elseif (movementTable[i] == 4) then
turtle.back()
turtle.turnLeft()
elseif (movementTable[i] == 5) then
turtle.back()
end
end
end
function mineOre(locationParam, movementTable)
if (locationParam == 1) then
turtle.digUp()
turtle.suckUp()
turtle.up()
table.insert(movementTable, 1)
elseif (locationParam == 2) then
turtle.digDown()
turtle.suckDown()
turtle.down()
table.insert(movementTable, 2)
elseif (locationParam == 3) then
turtle.turnLeft()
turtle.dig()
turtle.suck()
turtle.forward()
table.insert(movementTable, 3)
elseif (locationParam == 4) then
turtle.turnRight()
turtle.dig()
turtle.suck()
turtle.forward()
table.insert(movementTable, 4)
elseif (locationParam == 5) then
turtle.dig()
turtle.suck()
turtle.forward()
table.insert(movementTable, 5)
end
locationParam = oreCheck()
if (locationParam > 0) then
mineOre(locationParam, movementTable)
else
return movementTable
end
end
function digTunnel(tunnelLengthParam)
local oreFound
local movement = {}
for i = 1, tunnelLengthParam do
turtle.dig()
turtle.forward()
oreFound = oreCheck()
if (oreFound > 0) then
movement = mineOre(oreFound, movement)
returnToTunnel(movement)
end
if ((i % 2) == 1) then
turtle.digUp()
turtle.up()
elseif ((i % 2) == 0) then
turtle.digDown()
turtle.down()
end
oreFound = oreCheck()
if (oreFound > 0) then
movement = mineOre(oreFound, movement)
returnToTunnel(movement)
end
end
end
So, the digTunnel function calls the other two functions mineOre and returnToTunnel.
I've been looking in the LUA manual and several websites but can't figure it out.
Thank you for your help!

Your function mineOre does not return a table but nil, when locationParam is > 0.
if (locationParam > 0) then
mineOre(locationParam, movementTable)
else
return movementTable
end
Hence this will cause a nil value end up in table.maxn
movement = mineOre(oreFound, movement)
returnToTunnel(movement)

Related

AMPscript IF Statement returning variable as empty

I am running into an issue in AMPscript where the following IF statement is returning my variable #shippingVendor as nothing when I call it. (Tracking Number is from data extension)
Assuming #trackingNumber = 23456
%%[
var #shippingVendor
IF Substring(#trackingNumber, 1, 1) == "2" THEN
SET #shippingVendor = "https://www.nzpost.co.nz/tools/tracking/item/"
ELSEIF Substring(#trackingNumber, 1, 2) == "T1" THEN
SET #shippingVendor = "https://www.mainfreight.com/en-nz/tracking?trackingnumber="
ELSEIF Substring(#trackingNumber, 1, 3) == "TP1" THEN
SET #shippingVendor = "https://www.mytoll.com/?"
ENDIF
]%%
I would expect %%=v(#shippingVendor)=%% to return https://www.nzpost.co.nz/tools/tracking/item/ - however instead it returns nothing...can I please check if I am doing anything wrong?
Fairly new to AMPscript so would love your help on this - thanks in advance!
It's dangerous to do substring in AMPscript without checking for existence and length. I'd also set a default value for the shipping vendor URL.
%%[
set #trackingNumber = 23456
set #shippingVendor = "DEFAULVENDORURLHERE"
if not empty(#trackingNumber) then
IF length(#trackingNumber) >= 1 and Substring(#trackingNumber, 1, 1) == "2" THEN
SET #shippingVendor = "https://www.nzpost.co.nz/tools/tracking/item/"
ELSEIF length(#trackingNumber) >= 2 and Substring(#trackingNumber, 1, 2) == "T1" THEN
SET #shippingVendor = "https://www.mainfreight.com/en-nz/tracking?trackingnumber="
ELSEIF length(#trackingNumber) >= 3 and Substring(#trackingNumber, 1, 3) == "TP1" THEN
SET #shippingVendor = "https://www.mytoll.com/?"
ENDIF
endif
]%%
shippingVendor: %%=v(#shippingVendor)=%%
Output:
shippingVendor: https://www.nzpost.co.nz/tools/tracking/item/
Demo: https://mcsnippets.herokuapp.com/s/eiSqyIcb

Lua Function stuck in a loop

I'm using the standard lua 5.4.4 distribution and interpreter, no libraries, etc.
I'm attempting to write a script to evaluate user defined values of the Collatz Conjecture
(TLDR at the bottom)
I want the script to read a user input (this part works so I didn't include it)
and based on that input, set a starting number (ognumber), and a range of numbers to try
then, i want it to iterate through every number between the ognumber and the range (in increments of 1)
for every iteration, i want it to check if each number is odd or even, do some math with the result being "newnumber", then set number = newnumber to try the result of the previous operation.
The problem I'm facing is that when I call the function, it doesn't end.
it gets stuck continuously trying the same number, it doesn't return number, and it doesn't set number = newnumber.
function isodd(number, newnumber, ResultsPath, results)
newnumber = math.floor(number * 3 + 1)
print(number..' x 3 + 1 = '..newnumber)
local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
writetoresultsfile:write(' '..number..' x 3 + 1 = '..newnumber..'\n')
writetoresultsfile:close()
number = math.floor(newnumber)
return number
end
function iseven(number, newnumber, ResultsPath, results)
newnumber = math.floor(number / 2)
print(number..' / 2 = '..newnumber)
local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
writetoresultsfile:write(' '..number..' / 2 = '..newnumber..'\n')
writetoresultsfile:close()
number = math.floor(newnumber)
return number
end
for number = ognumber, range, 1 do
local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
writetoresultsfile:write(' <List name = "Attempt '..ognumber..'"> \n')
writetoresultsfile:close()
print('Trying '..number)
while(number > 1) do
if(number % 2 ~= 0) then
isodd(number, newnumber, ResultsPath, results)
else
iseven(number, newnumber, ResultsPath, results)
end
end
ognumber = ognumber + 1
number = ognumber
end
if(ognumber == range + 1) then
local resultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
resultsfile:write(' </Table>\n')
resultsfile:write('</Data>\n')
resultsfile:close()
end
This is what shows up when I run the script using function()
This script works, but I wanted to achieve the same thing using functions
for number = ognumber, range, 1 do
local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
writetoresultsfile:write(' <List name = "Attempt '..ognumber..'"> \n')
writetoresultsfile:close()
print('Trying '..number)
while(number > 1) do
if(number % 2 ~= 0) then
newnumber = math.floor(number * 3 + 1)
print(number..' x 3 + 1 = '..newnumber)
local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
writetoresultsfile:write(' '..number..' x 3 + 1 = '..newnumber..'\n')
writetoresultsfile:close()
number = newnumber
else
newnumber = math.floor(number / 2)
print(number..' / 2 = '..newnumber)
local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
writetoresultsfile:write(' '..number..' / 2 = '..newnumber..'\n')
writetoresultsfile:close()
number = newnumber
end
end
ognumber = ognumber + 1
number = ognumber
end
if(ognumber == range + 1) then
local resultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
resultsfile:write(' </Table>\n')
resultsfile:write('</Data>\n')
resultsfile:close()
end
This is what it shows when I don't use function()
Edit: This Script works using the advice Shingo gave me
function isodd(number, ResultsPath, results)
newnumber = math.floor(number * 3 + 1)
print(number..' x 3 + 1 = '..newnumber)
local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
writetoresultsfile:write(' '..number..' x 3 + 1 = '..newnumber..'\n')
writetoresultsfile:close()
number = math.floor(newnumber)
return number
end
function iseven(number, ResultsPath, results)
newnumber = math.floor(number / 2)
print(number..' / 2 = '..newnumber)
local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
writetoresultsfile:write(' '..number..' / 2 = '..newnumber..'\n')
writetoresultsfile:close()
number = math.floor(newnumber)
return number
end
for number = ognumber, range, 1 do
local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
writetoresultsfile:write(' <List name = "Attempt '..ognumber..'"> \n')
writetoresultsfile:close()
print('Trying '..number)
while(number > 1) do
if(number % 2 ~= 0) then
number = isodd(number, ResultsPath, results)
else
number = iseven(number, ResultsPath, results)
end
end
ognumber = ognumber + 1
number = ognumber
end
if(ognumber == range + 1) then
local resultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
resultsfile:write(' </Table>\n')
resultsfile:write('</Data>\n')
resultsfile:close()
end
TLDR about the Collatz Conjecture for those interested:
The Collatz Conjecture states that for any positive integer, if you apply 2 rules to it, will always return to 1.
The rules are: if the previous number is even, the next number is one half of the previous number. If the previous number is odd, the next number is 3 times the previous number plus 1
Although you return number from the function, it won't be updated out of the scope, you need accept it like this (same as iseven):
number = isodd(number, newnumber, ResultsPath, results)
Moreover newnumber is only used inside the function, so it's not necessary to be an argument. The function could be change to:
function isodd(number, ResultsPath, results)
local newnumber = math.floor(number * 3 + 1)

Lua - Exception has occurred: attempt to call a nil value

I run the following code, but Lua keeps giving me "attempt to call a nil value". When I change the _G[fi] to _G.fi it gives me "attempt to call a string value".
i = "0"
j = "0"
k = "0"
fi = "f"..i
fj = "f"..j
fk= "f"..k
functions = {
f1 = function(next, v)
for t = 1, 1, 4 do
v[t] = v[t] + 1
v[t] = v[t] % 3
end
if (next == "0") then return v
else return functions[next](0, v) end
end,
f2 = function(next, v)
for t = 1, 1, 4 do
v[t] = v[t] + 2
v[t] = v[t] % 3
end
if (next == "0") then return v
else return functions[next](0, v) end
end,
f3 = function(next, v)
if (next == "0") then return v
else return functions[next](0, v) end
end,
f4 = function(next, v)
swap(v[2], v[3])
if (next == "0") then return v
else return functions[next](0, v) end
end,
f5 = function(next, v)
swap(v[1], v[3])
if (next == "0") then return v
else return functions[next](0, v) end
end,
f6 = function(next, v)
swap(v[1], v[2])
if (next == "0") then return v
else return functions[next](0, v) end
end,
}
for i = 0, 1, 6 do
for j = 0, 1, 6 do
for k = 0, 1, 6 do
if _G[fi](fj, {1,2,0}) == _G[fj](fk, {1,2,0}) and not _G[fi](-1, {1,2,0}) == _G[fk](-1, {1,2,0}) then
print(i + " " + j + " " + k)
end
end
end
end
The problem is you set fi = "f"..i at the start, which sets fi == "f0", and that never changes for the rest of the program until you later invoke _G[fi]. The value of fi does not automatically change just because you changed the value of i.
You probably want to expand i (and j and k) at the call point, with something more like:
_G["f"..i]("f"..j, {1,2,0})... etc

Lua nested Json, remove single occurs or list of occurs if multiple

So what I am trying to do here is for a given json_body which is decoded json into a table using cjson I want to remove a given element by a configurable value conf.remove.json, I feel I am pretty close but its still not working, and is there a better way? Is there a safe way to find the tables "depth" and then reach out like conf.remove.json= I.want.to.remove.this creates the behavior json_table[I][want][to][remove][this] = nil without throwing some kind of NPE?
local configRemovePath= {}
local configRemoveDepth= 0
local recursiveCounter = 1
local function splitString(inputstr)
sep = "%." --Split on .
configRemovePath={}
configRemoveDepth=0
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
configRemovePath[configRemoveDepth + 1] = str
configRemoveDepth = configRemoveDepth + 1
end
end
local function recursiveSearchAndNullify(jsonTable)
for key, value in pairs(jsonTable) do --unordered search
-- First iteration
--Sample Json below, where conf.remove.json = data.id and nothing happened. conf.remove.json=data.id
--{
--"data": {
-- "d": 2,
-- "id": 1
--}
--}
-- value = {"d": 2, "id": 1}, key = "data", configRemovePath[recursiveCounter] = "data" , configRemovePath ['data','id'] , configRemoveDepth = 2
if(type(value) == "table" and value == configRemovePath[recursiveCounter] and recursiveCounter < configRemoveDepth) then --If the type is table, the current table is one we need to dive into, and we have not exceeded the configurations remove depth level
recursiveCounter = recursiveCounter + 1
jsonTable = recursiveSearchAndNullify(value)
else
if(key == configRemovePath[recursiveCounter] and recursiveCounter == configRemoveDepth) then --We are at the depth to remove and the key matches then we delete.
for key in pairs (jsonTable) do --Remove all occurances of said element
jsonTable[key] = nil
end
end
end
end
return jsonTable
end
for _, name in iter(conf.remove.json) do
splitString(name)
if(configRemoveDepth == 0) then
for name in pairs (json_body) do
json_body[name] = nil
end
else
recursiveCounter = 1 --Reset to 1 for each for call
json_body = recursiveSearchAndNullify(json_body)
end
end
Thanks to any who assist, this is my first day with Lua so I am pretty newb.
This is the official answer, found a better way with the help of Christian Sciberras!
local json_body_test_one = {data = { id = {"a", "b"},d = "2" }} --decoded json w cjson
local json_body_test_two = {data = { { id = "a", d = "1" }, { id = "b", d = "2" } } }
local config_json_remove = "data.id"
local function dump(o) --Method to print test tables for debugging
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end
local function splitstring(inputstr, sep)
if sep == nil then
sep = "%." --Dot notation default
end
local t={} ; i=1
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
t[i] = str
i = i + 1
end
return t
end
local function setjsonprop(json_object, path, newvalue)
local configarray = splitstring(path)
while (#configarray > 1) do
json_object = json_object[table.remove(configarray, 1)]
if(type(json_object) == "table" and #json_object > 0) then
local recursepath = table.concat(configarray, ".")
for _, item in pairs(json_object) do
setjsonprop(item, recursepath, newvalue)
end
return
end
end
json_object[table.remove(configarray, 1)] = newvalue
end
setjsonprop(json_body_test_one, config_json_remove, nil)
print(dump(json_body_test_one))

Lua table read and match efficient

My problem is simple, i used to do this in order to check if any of my lines (see photo) bump into any other line (or trail of any other line). But the way i do this now is by doing a lot of if statements, which is not good. So here is the code i used:
function Bumper:draw()
for id,posx1 in pairs(tableposx1) do
posy1 = tableposy1[id]
posx2 = tableposx2[id]
posy2 = tableposy2[id]
posx3 = tableposx3[id]
posy3 = tableposy3[id]
posx4 = tableposx4[id]
posy4 = tableposy4[id]
if (posx1 ~= nil) and (posy1 ~= nil) and
((math.abs(xposplayer1 - posx1) < 5) and (math.abs(yposplayer1 - posy1) < 5))
and (id < (count - 5) and killp1 == "false") then
killp1 = "true"
tint(255, 0, 0, 162)
sprite("Dropbox:kill",xposplayer1,yposplayer1)
noTint()
end
if (posx2 ~= nil) and (posy2 ~= nil) and
((math.abs(xposplayer1 - posx2) < 5) and (math.abs(yposplayer1 - posy2) < 5))
and killp1 == "false" then
killp1 = "true"
tint(255, 0, 0, 162)
sprite("Dropbox:kill",xposplayer1,yposplayer1)
noTint()
end
if (posx3 ~= nil) and (posy3 ~= nil) and
((math.abs(xposplayer1 - posx3) < 5) and (math.abs(yposplayer1 - posy3) < 5))
and killp1 == "false" then
killp1 = "true"
tint(255, 0, 0, 162)
sprite("Dropbox:kill",xposplayer1,yposplayer1)
noTint()
end
if (posx4 ~= nil) and (posy4 ~= nil) and
((math.abs(xposplayer1 - posx4) < 5) and (math.abs(yposplayer1 - posy4) < 5))
and killp1 == "false" then
killp1 = "true"
tint(255, 0, 0, 162)
sprite("Dropbox:kill",xposplayer1,yposplayer1)
noTint()
end
if (posx1 ~= nil) and (posy1 ~= nil) and
((math.abs(xposplayer2 - posx1) < 5) and (math.abs(yposplayer2 - posy1) < 5))
and killp2 == "false" then
killp2 = "true"
tint(0, 29, 255, 162)
sprite("Dropbox:kill",xposplayer2,yposplayer2)
noTint()
end
if (posx2 ~= nil) and (posy2 ~= nil) and
((math.abs(xposplayer2 - posx2) < 5) and (math.abs(yposplayer2 - posy2) < 5))
and (id < (count - 5) and killp2 == "false")then
killp2 = "true"
tint(0, 29, 255, 162)
sprite("Dropbox:kill",xposplayer2,yposplayer2)
noTint()
end
if (posx3 ~= nil) and (posy3 ~= nil) and
((math.abs(xposplayer2 - posx3) < 5) and (math.abs(yposplayer2 - posy3) < 5))
and killp2 == "false" then
killp2 = "true"
tint(0, 29, 255, 162)
sprite("Dropbox:kill",xposplayer2,yposplayer2)
noTint()
end
if (posx4 ~= nil) and (posy4 ~= nil) and
((math.abs(xposplayer2 - posx4) < 5) and (math.abs(yposplayer2 - posy4) < 5))
and killp2 == "false" then
killp2 = "true"
tint(0, 29, 255, 162)
sprite("Dropbox:kill",xposplayer2,yposplayer2)
noTint()
end
if (posx1 ~= nil) and (posy1 ~= nil) and
((math.abs(xposplayer3 - posx1) < 5) and (math.abs(yposplayer3 - posy1) < 5))
and killp3 == "false" then
killp3 = "true"
tint(1, 255, 0, 162)
sprite("Dropbox:kill",xposplayer3,yposplayer3)
noTint()
end
if (posx2 ~= nil) and (posy2 ~= nil) and
((math.abs(xposplayer3 - posx2) < 5) and (math.abs(yposplayer3 - posy2) < 5))
and killp3 == "false" then
killp3 = "true"
tint(1, 255, 0, 162)
sprite("Dropbox:kill",xposplayer3,yposplayer3)
noTint()
end
if (posx3 ~= nil) and (posy3 ~= nil) and
((math.abs(xposplayer3 - posx3) < 5) and (math.abs(yposplayer3 - posy3) < 5))
and (id < (count - 5) and killp3 == "false") then
killp3 = "true"
tint(1, 255, 0, 162)
sprite("Dropbox:kill",xposplayer3,yposplayer3)
noTint()
end
if (posx4 ~= nil) and (posy4 ~= nil) and
((math.abs(xposplayer3 - posx4) < 5) and (math.abs(yposplayer3 - posy4) < 5))
and killp3 == "false" then
killp3 = "true"
tint(1, 255, 0, 162)
sprite("Dropbox:kill",xposplayer3,yposplayer3)
noTint()
end
if (posx1 ~= nil) and (posy1 ~= nil) and
((math.abs(xposplayer4 - posx1) < 5) and (math.abs(yposplayer4 - posy1) < 5))
and killp4 == "false" then
killp4 = "true"
tint(255, 0, 229, 162)
sprite("Dropbox:kill",xposplayer4,yposplayer4)
noTint()
end
if (posx2 ~= nil) and (posy2 ~= nil) and
((math.abs(xposplayer4 - posx2) < 5) and (math.abs(yposplayer4 - posy2) < 5))
and killp4 == "false" then
killp4 = "true"
tint(255, 0, 229, 162)
sprite("Dropbox:kill",xposplayer4,yposplayer4)
noTint()
end
if (posx3 ~= nil) and (posy3 ~= nil) and
((math.abs(xposplayer4 - posx3) < 5) and (math.abs(yposplayer4 - posy3) < 5))
and killp4 == "false" then
killp4 = "true"
tint(255, 0, 229, 162)
sprite("Dropbox:kill",xposplayer4,yposplayer4)
noTint()
end
if (posx4 ~= nil) and (posy4 ~= nil) and
((math.abs(xposplayer4 - posx4) < 5) and (math.abs(yposplayer4 - posy4) < 5))
and id < (count - 5) and killp4 == "false" then
killp4 = "true"
tint(255, 0, 229, 162)
sprite("Dropbox:kill",xposplayer4,yposplayer4)
noTint()
end
end
end
Here is my init:
-- Main
a = 1
gameover = 0
tx = 0
paused = 1
count = 0
stagecount = 0
player1count = 0
player2count = 0
player3count = 0
player4count = 0
-- Random hole times
thistime1 = 0
thistime2 = 0
thistime3 = 0
thistime4 = 0
-- Dead players
killp1 = "false"
killp2 = "false"
killp3 = "false"
killp4 = "false"
kills = 0
-- Touch control
touches = {}
-- Player direction
pi = math.pi
o5pi = 50 * pi
mo5pi = - (50 * pi)
minpi = - (100*pi)
-- Random start direction
r1t = math.random(0,o5pi)
r2t = math.random(mo5pi,0)
r3t = math.random(minpi,mo5pi)
r4t = math.random(o5pi,100*pi)
r1 = r1t / 100
r2 = r2t / 100
r3 = r3t / 100
r4 = r4t / 100
deltar1 = pi / 55
deltar2 = pi / 55
deltar3 = pi / 55
deltar4 = pi / 55
-- Player speed
speed1 = 2.5
speed2 = 2.5
speed3 = 2.5
speed4 = 2.5
-- Player random start position
xposplayer1 = math.random(123,300)
yposplayer1 = math.random(123,300)
xposplayer2 = math.random(123,300)
yposplayer2 = math.random(468,645)
xposplayer3 = math.random(724,901)
yposplayer3 = math.random(468,645)
xposplayer4 = math.random(724,901)
yposplayer4 = math.random(123,300)
-- Player coordinate tables
tableposx1 = {}
tableposy1 = {}
tableposx2 = {}
tableposy2 = {}
tableposx3 = {}
tableposy3 = {}
tableposx4 = {}
tableposy4 = {}
Now i tried doing the following, but failed because i dont now how to use variable variable names:
for id,posx[a] in pairs(tableposx[a]) do
posy[a] = tableposy[a][id]
if ((posx[a] ~= nil) and (posy[a] ~= nil))
and (math.abs(xposplayer[a] - posx[a]) < 5)
and (math.abs(yposplayer[a] - posy[a]) < 5)
and (id < (count - 5))
and (killp[a] == "false")
then
killp[a] = "true"
tintp[a]
sprite("Dropbox:kill",xposplayer[a],yposplayer[a])
noTint()
end
end
a = a + 1
if a = 4 then
a = 1
end
-- EDIT: i use is 4 times, for 4 players!
function Player:draw1()
fill(255, 0, 11, 255)
xposplayer1 = xposplayer1 + speed1 * math.cos(r1)
yposplayer1 = yposplayer1 + speed1 * math.sin(r1)
if player1count == 0 then
thistime1 = math.random(200,500)
end
player1count = player1count + 1
if player1count < thistime1 then
table.insert(tableposx1,count,xposplayer1)
table.insert(tableposy1,count,yposplayer1)
tint(255, 0, 0, 162)
ellipse(xposplayer1,yposplayer1,10,10)
noTint()
elseif player1count > thistime1 then
tint(255, 0, 0, 162)
ellipse(xposplayer1,yposplayer1,5,5)
noTint()
if player1count > thistime1 + 20 then
player1count = 0
end
end
end
-- EDIT
How should i do this correctly? Thanks in advance!
Image:
You probably don't really want variable variable names like you said, but you can do it...
All globals are accessible by table named _G, and you can access your global variables by doing this:
_G['killp1']
_G['killp2']
-- etc
You can then use string manipulation as usual.
local i = 1
_G['killp' .. tostring(i)] -- same as _G['killp1']
i = i + 1
_G['killp' .. tostring(i)] -- same as _G['killp2']
But this is going to get really messy, fast. What you probably want to do instead is start using objects. You object might look something like this:
Linething = { x = 0, y = 0, dead = false, speed = 2.5 }
function Linething:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Linething:checkCollision(other)
if self.x - other.x < 5 and self.y - other.y < 5 then
self.dead = true
-- other stuff
end
end
function Linething:update(delta_t)
-- update the game logic
self.x = self.x + self.speed * cos(self.angle) * delta_t
self.y = self.y + self.speed * sin(self.angle) * delta_t
end
function Linething:draw()
-- do line drawing here
tint(255, 0, 0, 162)
ellipse(self.x, self.y, 10, 10)
noTint()
-- etc
end
-- in main:
linething1 = Linething:new()
linething2 = Linething:new()
linething1.checkCollision(linething2)
EDIT: Typically you want to seperate the game logic from the rendering. Most games have a loop that looks like this:
function main_loop()
while true do
delta_t = get_change_in_time()
update_all(delta_t)
draw_all()
end
end
-- where update_all is something like this:
function update_all(delta_t)
player1:update(delta_t)
player2:update(delta_t)
-- things in a table:
for _, x in pairs(table_of_x) do
x:update(delta_t)
end
end
-- and draw all is basically the same
function draw_all()
player1:draw()
player2:draw()
-- things in a table:
for _, x in pairs(table_of_x) do
x:draw()
end
end
It looks like your Player object has-a Linething object. So you might want to add a Linething object to the Player object and change Player:draw() to call players_linething:draw(). Then you can have 4 Player objects, which each have a Linething object. Does that make sense?
The problem is that you're using variables with subscripts (player1, player2, etc.) rather than arrays (player[1], player[2], etc.) which makes it impossible to iterate over them in a loop.
You should also be grouping related items together. Rather than player 1 being represented by a bunch of global variables:
player1count = 0
speed1 = 2.5
Those things should be organized into a table:
player1.count = 0
speed1.speed = 2.5
And, as mentioned before, any time you have a bunch of variables that vary by subscript, you should be using an array (or more generally, some kind of iterable list type, which in Lua happens to be a table/array):
players = {}
-- initialize players
for i=1,NUM_PLAYERS do
players[i] = {
count = 0,
speed = 2.5
}
end
If you apply this generally to your program, your huge if statement is going to naturally disappear, being replaced by a relatively small, nested for loop.
I have not read everything but in your last snippet:
You cannot do for id,posx[a], because the variables assigned by a for loop are local. To fix it replace instances of posx[a] by a local variable name such as posx_a.
There is a typo here: if a = 4 then (you mean ==).
This line means nothing: tintp[a].