This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
je06's profile picture

Attempt To Index Field '?' (A Boolean Value)

Started by je06, 30 September 2013 - 01:02 PM
je06 #1
Posted 30 September 2013 - 03:02 PM
Why am I getting "attempt to index field '?' (a boolean value)"?

What I'm trying to do is create a program that can do ray tracing.
Code
Spoiler

local w = 52
local h = 19
local world = {}
function newWorld(sizeXmin, sizeXmax, sizeYmin, sizeYmax,  sizeZmin, sizeZmax)
for a=sizeXmin,sizeXmax do
world[a] = {}
for b=sizeYmin,sizeYmax do
world[a][b] = {}
for c=sizeZmin, sizeYmax do
world[a][b][c] = false
end
end
end
end
function importModel(name, model)
  world[name] = model
end
function newRay(x, y, z, xD, yD, zD, d)
  print("x:"..tostring(x).." y:"..tostring(y).." z:"..tostring(z))
  local xC = x
  local yC = y
  local zC = z
  for a=1,d do
	for b,c in pairs(world) do
print(world[b][x][y][z])
	  if world[b][x] == nil then
	  elseif world[b][x][y] == nil then
	  elseif not world[b][x][y][z] then
print("x:"..tostring(x).." y:"..tostring(y).." z:"..tostring(z).." value:"..world[b][x][y][z])
		return world[b][x][y][z]
	  end
	  xC = xC + xD
	  yC = yC + yD
	  zC = zC + zD
	  x = math.floor(xC)
	  y = math.floor(yC)
	  z = math.floor(zC)
	end
  end
  return false
end
function rays(x, y, z, xD, yD, zD, d, a)
  local pointX = x-(xD*a)
  local pointY = y-(yD*a)
  local pointZ = z-(zD*a)
  local sX = x
  local sY = y
  local cenX = math.floor(w/2)
  local cenY = math.floor(h/2)
  local mX = cenX*(-1)
  local mY = cenY*(-1)
  local screen = {}
  for a=mX,cenX do
	screen[sY] = {}
	for b=mY,cenY do
print(tostring(screen[sY][sX]).." x:"..tostring(x).." y:"..tostring(y).." z:"..tostring(z).." pX:"..tostring(pointX+a).." pY:"..tostring(pointY+B)/>/>.." pZ:"..tostring(pointZ+a))
	  screen[sY][sX] = newRay(x, y, z, math.floor(pointX+a), math.floor(pointY+B)/>/>, math.floor(pointZ+a), d)
	  sX = sX + 1
	end
	sY = sY + 1
  end
  return screen
end
newWorld(1, 5, 1, 6, 1, 7)
local m = {}
m[1] = {}
m[1][1] = {}
m[1][1][1] = 3
m[1][2] = {}
m[1][2][1] = 2
importModel("m", m, 1, 1, 1)
local a = rays(1, 1, 1, 1, 1, 0, 8, 5)
What my code is meant to do is create a 'ray' that keeps going until it ether hits something
or when't as far as its meant to go.

My code is working until it read 'world[a][c]' then it gives me the error above.

If someone else posted a problem just like this please tell me because I looked for a long time.

P.S. It is hard coded to work with a computer screen only for a reason
BigTwisty #2
Posted 30 September 2013 - 03:51 PM
Couple of problems:
1:

for c=sizeZmin, sizeYmax do
should be:

for c=sizeZmin, sizeZmax do

2. There are several places where world is referenced with 4 sub tables, but it only seems to be generated with 3.

3. You defined importModel with 2 arguments, but are calling it with 5. The last 3 arguments are being ignored.

Those are just the few I found on a quick scan. If you fix those and it still doesn't work, we can look more in depth.
je06 #3
Posted 25 October 2013 - 09:49 PM
Re-wrote the code. My new code works fine except the function where it calculates all the different ray paths. Now it thinks blue is in every table or something like that.
New Code
Spoilerlocal world = {}
local w, h = term.getSize()
function loadWorld(pWorld)
world = pWorld
end
function unloadWorld()
world = {}
end
function loadObject(name, object)
world[name] = object
end
function unloadObject(name)
world[name] = nil
end
local function newRay(x, y, z, xP, yP, zP, d)
local xD = x + xP
local yD = y + yP
local zD = y + zP
local cX = x
local cY = y
local cZ = z
for a=1,d do
x = math.floor(cX)
y = math.floor(cY)
z = math.floor(cZ)
for b,c in pairs(world) do
return world[x][y][z]
end
cX = cX + xD
cY = cY + yD
cZ = cZ + zD
end
end
local function screen(x, y, z, xP, yP, zP, d, B)/>
local sW2 = math.floor(w/2)
local sW1 = sW2*-1
local sH2 = math.floor(h/2)
local sH1 = sH2*-1
local cX
local cY
local cZ
local tablea = {}
for a=sW1,sW2 do
tablea[a+sW2+1] = {}
for b=sH1,sH2 do
cX = xP+(xP*a/xP)
cY = yP+(yP*b/yP)
cZ = zP+(zP*a/zP)
tablea[a+sW2+1][b+sH2+1] = newRay(x, y, z, cX, cY, cZ, d)
print(cX)
print(cY)
print(cZ)
print(tablea[a+sW2+1][b+sH2+1])
if tablea[a+sW2+1][b+sH2+1] == nil then
tablea[a+sW2+1][b+sH2+1] = b
end
end
end
return tablea
end
local function display(tablea)
for a=1,#tablea do
for b=1,#tablea[a] do
term.setCursorPos(a, B)/>
term.setBackgroundColor(tablea[a])
term.write(" ")
end
end
end
local f = {}
f[1] = {}
f[1][1] = {}
f[1][1][1] = colors.blue
f[1][1][2] = colors.yellow
f[1][2] = {}
f[1][2][1] = colors.green
loadObject("testObject", f)
a = screen(1, 1, 1, 0, 0, -4, 8, colors.black)
display(a)
sleep(1)

If you can please fix my code.

P.S. Sorry it took a while to write back.
Bomb Bloke #4
Posted 26 October 2013 - 05:57 AM
I'm not going to pretend to understand what this is supposed to do (hence I've no idea how to fix it to do exactly what you want; it looks like it wants to be a 3D engine but I'm not entirely sure), though I can tell you what it does do:

1) "f" is dumped into world["testObject"]. Note that line 73 sets f[1][1][1] to the colour blue, hence world["testObject"][1][1][1] is also blue.
2) The screen function is called by line 78. x, y and z are each set to 1 at this point.
3) Line 49 (which calls newRay) will be processed a number of times, but every single time, x, y and z will still each be 1.
4) Lines 19-20 copy the contents of x, y and z into cX, cY and cZ.
5) Lines 23-25 copy the (unchanged) contents of cX, cY and cZ back into x, y and z.
6) The newRay function always returns world["testObject"][x][y][z] at line 27.
7) Since x, y and z will still, under all circumstances, each be one, that means f[1][1][1] (the colour blue) is the only colour that gets dumped into tablea by the newRay function called at line 49.

Also note that when newRay returns, execution of that function stops. The loop started on line 22 only ever gets halfway through one iteration - it then breaks off because the function has returned an answer.

Edit:

I guess that you want line 27 to check what world["testObject"][cX][cY][cZ] is, and return it if non-nil. You'd then return nil if the loop initiated on line 22 finished up without finding a "hit". I've not tested this nor thought through your formulas.