[SOLVED] Multiple OR Booleans Issue

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Ekamu
Party member
Posts: 178
Joined: Fri Sep 20, 2013 11:06 am

[SOLVED] Multiple OR Booleans Issue

Post by Ekamu »

When I run a loop, return breaks the loop. What if I want to loop through multiple "or" returns?

Code: Select all

Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> t = {1,0,0,0}
> for i = 1, #t do
>> print(t[i])
>> end
1
0
0
0
> t = {
>> {0,0,1},
>> {0,0,0}
>> }
> for i = 1, #t do
>> for j = 1, #t[i] do
>> print(t[i][j])
>> end
>> end
0
0
1
0
0
0
> t = {
>> {0,1,1}
>> }
> 
> for i = 1, #t do
>> for j = 1, #t[i] do
>> if t[i][j] == 1 then
>> return true
>> end
>> end
>> end
true —-should be true true but it breaks
> 
For loops break when you return something from them. I want to do this

Code: Select all

if fun_bool(1) or fun_bool(2) or fun_bool(3) then 
--do stuff
end 
except for like over a hundred fun_bool(1000000).

Why?
So basically I have a 2d matrix that represent a map, like this

Code: Select all

map = {
{1,1,0,0,1,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,1,1,1,1,1}
}
And a table that sets locations of tiles if the map[y][x] == 1

Code: Select all

--tile (multiple tables can be created with a loop)
local tir = 0 --table iterator
local map_check = 1 --integer in map to check
local cx = u*3 --x constant to add
local cy = u*4 --y constant to add  
t = {} --tile objects go in this table
for i = 1, #map do
	for j = 1, #map[i] do
		if map[i][j] == map_check then
			tir = tir + 1 --increment the iterator
			t[tir] = {} --create a new table
			t[tir].x = (i-1)*u + cx --set x position
			t[tir].y = (j-1)*u + cy --set y position
			t[tir].w = u --set width by units u (32)
			t[tir].h = u --set height by units u (32)
		end
	end
end
--collision function from (https://love2d.org/wiki/BoundingBox.lua)
function CheckCollision(x1,y1,w1,h1, x2,y2,w2,h2)
	return x1 < x2+w2 and x2 < x1+w1 and y1 < y2+h2 and y2 < y1+h1
end
So far the only way to check each tile is like this. (O.K for a small map but unpractical for a real map)

Code: Select all

if love.keyboard.isDown('up') then
	p.y = p.y - p.s*dt
		if (p.x < t[1].x+t[1].w and t[1].x < p.x+p.w and p.y < t[1].y+t[1].h and t[1].y < p.y+p.h) or
		(p.x < t[2].x+t[2].w and t[2].x < p.x+p.w and p.y < t[2].y+t[2].h and t[2].y < p.y+p.h) or
		(p.x < t[3].x+t[3].w and t[3].x < p.x+p.w and p.y < t[3].y+t[3].h and t[3].y < p.y+p.h) or
		(p.x < t[4].x+t[4].w and t[4].x < p.x+p.w and p.y < t[4].y+t[4].h and t[4].y < p.y+p.h) or
		(p.x < t[5].x+t[5].w and t[5].x < p.x+p.w and p.y < t[5].y+t[5].h and t[5].y < p.y+p.h) or
		(p.x < t[6].x+t[6].w and t[6].x < p.x+p.w and p.y < t[6].y+t[6].h and t[6].y < p.y+p.h) or
		(p.x < t[7].x+t[7].w and t[7].x < p.x+p.w and p.y < t[7].y+t[7].h and t[7].y < p.y+p.h) or
		(p.x < t[8].x+t[8].w and t[8].x < p.x+p.w and p.y < t[8].y+t[8].h and t[8].y < p.y+p.h) or
		(p.x < t[9].x+t[9].w and t[9].x < p.x+p.w and p.y < t[9].y+t[9].h and t[9].y < p.y+p.h) or
		(p.x < t[10].x+t[10].w and t[10].x < p.x+p.w and p.y < t[10].y+t[10].h and t[10].y < p.y+p.h) or
		(p.x < t[11].x+t[11].w and t[11].x < p.x+p.w and p.y < t[11].y+t[11].h and t[11].y < p.y+p.h) or
		(p.x < t[12].x+t[12].w and t[12].x < p.x+p.w and p.y < t[12].y+t[12].h and t[12].y < p.y+p.h) or
		(p.x < t[13].x+t[13].w and t[13].x < p.x+p.w and p.y < t[13].y+t[13].h and t[13].y < p.y+p.h) or
		(p.x < t[14].x+t[14].w and t[14].x < p.x+p.w and p.y < t[14].y+t[14].h and t[14].y < p.y+p.h) or
		(p.x < t[15].x+t[15].w and t[15].x < p.x+p.w and p.y < t[15].y+t[15].h and t[15].y < p.y+p.h) or
		(p.x < t[16].x+t[16].w and t[16].x < p.x+p.w and p.y < t[16].y+t[16].h and t[16].y < p.y+p.h)
		then
		p.y = math.ceil(p.y) + 1
		end
	end
	if love.keyboard.isDown('down') then
	p.y = p.y + p.s*dt
		if (p.x < t[1].x+t[1].w and t[1].x < p.x+p.w and p.y < t[1].y+t[1].h and t[1].y < p.y+p.h) or
		(p.x < t[2].x+t[2].w and t[2].x < p.x+p.w and p.y < t[2].y+t[2].h and t[2].y < p.y+p.h) or
		(p.x < t[3].x+t[3].w and t[3].x < p.x+p.w and p.y < t[3].y+t[3].h and t[3].y < p.y+p.h) or
		(p.x < t[4].x+t[4].w and t[4].x < p.x+p.w and p.y < t[4].y+t[4].h and t[4].y < p.y+p.h) or
		(p.x < t[5].x+t[5].w and t[5].x < p.x+p.w and p.y < t[5].y+t[5].h and t[5].y < p.y+p.h) or
		(p.x < t[6].x+t[6].w and t[6].x < p.x+p.w and p.y < t[6].y+t[6].h and t[6].y < p.y+p.h) or
		(p.x < t[7].x+t[7].w and t[7].x < p.x+p.w and p.y < t[7].y+t[7].h and t[7].y < p.y+p.h) or
		(p.x < t[8].x+t[8].w and t[8].x < p.x+p.w and p.y < t[8].y+t[8].h and t[8].y < p.y+p.h) or
		(p.x < t[9].x+t[9].w and t[9].x < p.x+p.w and p.y < t[9].y+t[9].h and t[9].y < p.y+p.h) or
		(p.x < t[10].x+t[10].w and t[10].x < p.x+p.w and p.y < t[10].y+t[10].h and t[10].y < p.y+p.h) or
		(p.x < t[11].x+t[11].w and t[11].x < p.x+p.w and p.y < t[11].y+t[11].h and t[11].y < p.y+p.h) or
		(p.x < t[12].x+t[12].w and t[12].x < p.x+p.w and p.y < t[12].y+t[12].h and t[12].y < p.y+p.h) or
		(p.x < t[13].x+t[13].w and t[13].x < p.x+p.w and p.y < t[13].y+t[13].h and t[13].y < p.y+p.h) or
		(p.x < t[14].x+t[14].w and t[14].x < p.x+p.w and p.y < t[14].y+t[14].h and t[14].y < p.y+p.h) or
		(p.x < t[15].x+t[15].w and t[15].x < p.x+p.w and p.y < t[15].y+t[15].h and t[15].y < p.y+p.h) or
		(p.x < t[16].x+t[16].w and t[16].x < p.x+p.w and p.y < t[16].y+t[16].h and t[16].y < p.y+p.h)
		then
		p.y = math.floor(p.y) - 1
		end
	end
	if love.keyboard.isDown('left') then
	p.x = p.x - p.s*dt
		if (p.x < t[1].x+t[1].w and t[1].x < p.x+p.w and p.y < t[1].y+t[1].h and t[1].y < p.y+p.h) or
		(p.x < t[2].x+t[2].w and t[2].x < p.x+p.w and p.y < t[2].y+t[2].h and t[2].y < p.y+p.h) or
		(p.x < t[3].x+t[3].w and t[3].x < p.x+p.w and p.y < t[3].y+t[3].h and t[3].y < p.y+p.h) or
		(p.x < t[4].x+t[4].w and t[4].x < p.x+p.w and p.y < t[4].y+t[4].h and t[4].y < p.y+p.h) or
		(p.x < t[5].x+t[5].w and t[5].x < p.x+p.w and p.y < t[5].y+t[5].h and t[5].y < p.y+p.h) or
		(p.x < t[6].x+t[6].w and t[6].x < p.x+p.w and p.y < t[6].y+t[6].h and t[6].y < p.y+p.h) or
		(p.x < t[7].x+t[7].w and t[7].x < p.x+p.w and p.y < t[7].y+t[7].h and t[7].y < p.y+p.h) or
		(p.x < t[8].x+t[8].w and t[8].x < p.x+p.w and p.y < t[8].y+t[8].h and t[8].y < p.y+p.h) or
		(p.x < t[9].x+t[9].w and t[9].x < p.x+p.w and p.y < t[9].y+t[9].h and t[9].y < p.y+p.h) or
		(p.x < t[10].x+t[10].w and t[10].x < p.x+p.w and p.y < t[10].y+t[10].h and t[10].y < p.y+p.h) or
		(p.x < t[11].x+t[11].w and t[11].x < p.x+p.w and p.y < t[11].y+t[11].h and t[11].y < p.y+p.h) or
		(p.x < t[12].x+t[12].w and t[12].x < p.x+p.w and p.y < t[12].y+t[12].h and t[12].y < p.y+p.h) or
		(p.x < t[13].x+t[13].w and t[13].x < p.x+p.w and p.y < t[13].y+t[13].h and t[13].y < p.y+p.h) or
		(p.x < t[14].x+t[14].w and t[14].x < p.x+p.w and p.y < t[14].y+t[14].h and t[14].y < p.y+p.h) or
		(p.x < t[15].x+t[15].w and t[15].x < p.x+p.w and p.y < t[15].y+t[15].h and t[15].y < p.y+p.h) or
		(p.x < t[16].x+t[16].w and t[16].x < p.x+p.w and p.y < t[16].y+t[16].h and t[16].y < p.y+p.h)
		then
		p.x = math.ceil(p.x) + 1
		end
	end
	if love.keyboard.isDown('right') then
	p.x = p.x + p.s*dt
		if (p.x < t[1].x+t[1].w and t[1].x < p.x+p.w and p.y < t[1].y+t[1].h and t[1].y < p.y+p.h) or
		(p.x < t[2].x+t[2].w and t[2].x < p.x+p.w and p.y < t[2].y+t[2].h and t[2].y < p.y+p.h) or
		(p.x < t[3].x+t[3].w and t[3].x < p.x+p.w and p.y < t[3].y+t[3].h and t[3].y < p.y+p.h) or
		(p.x < t[4].x+t[4].w and t[4].x < p.x+p.w and p.y < t[4].y+t[4].h and t[4].y < p.y+p.h) or
		(p.x < t[5].x+t[5].w and t[5].x < p.x+p.w and p.y < t[5].y+t[5].h and t[5].y < p.y+p.h) or
		(p.x < t[6].x+t[6].w and t[6].x < p.x+p.w and p.y < t[6].y+t[6].h and t[6].y < p.y+p.h) or
		(p.x < t[7].x+t[7].w and t[7].x < p.x+p.w and p.y < t[7].y+t[7].h and t[7].y < p.y+p.h) or
		(p.x < t[8].x+t[8].w and t[8].x < p.x+p.w and p.y < t[8].y+t[8].h and t[8].y < p.y+p.h) or
		(p.x < t[9].x+t[9].w and t[9].x < p.x+p.w and p.y < t[9].y+t[9].h and t[9].y < p.y+p.h) or
		(p.x < t[10].x+t[10].w and t[10].x < p.x+p.w and p.y < t[10].y+t[10].h and t[10].y < p.y+p.h) or
		(p.x < t[11].x+t[11].w and t[11].x < p.x+p.w and p.y < t[11].y+t[11].h and t[11].y < p.y+p.h) or
		(p.x < t[12].x+t[12].w and t[12].x < p.x+p.w and p.y < t[12].y+t[12].h and t[12].y < p.y+p.h) or
		(p.x < t[13].x+t[13].w and t[13].x < p.x+p.w and p.y < t[13].y+t[13].h and t[13].y < p.y+p.h) or
		(p.x < t[14].x+t[14].w and t[14].x < p.x+p.w and p.y < t[14].y+t[14].h and t[14].y < p.y+p.h) or
		(p.x < t[15].x+t[15].w and t[15].x < p.x+p.w and p.y < t[15].y+t[15].h and t[15].y < p.y+p.h) or
		(p.x < t[16].x+t[16].w and t[16].x < p.x+p.w and p.y < t[16].y+t[16].h and t[16].y < p.y+p.h)
		then
		p.x = math.floor(p.x) - 1
		end
	end	
I could simplyfy it like this with some hard coding in the collision function.

Code: Select all

--hard coded values
function chk(i)
	return (p.x < t[i].x+t[i].w and t[i].x < p.x+p.w and p.y < t[i].y+t[i].h and t[i].y < p.y+p.h)
end
This is more readable. but is it possible to loop though an (if x or y or z or ...) then statement?

Code: Select all

	if love.keyboard.isDown('up') then
	p.y = p.y - p.s*dt
		if chk(1) or chk(2) or chk(3) or chk(4) or
		chk(5) or chk(6) or chk(7) or chk(8) or 
		chk(9) or chk(10) or chk(11) or chk(12) or 
		chk(13) or chk(14) or chk(15) or chk(16)
		then
		p.y = math.ceil(p.y) + 1
		end
	end
	if love.keyboard.isDown('down') then
	p.y = p.y + p.s*dt
		if chk(1) or chk(2) or chk(3) or chk(4) or
		chk(5) or chk(6) or chk(7) or chk(8) or 
		chk(9) or chk(10) or chk(11) or chk(12) or 
		chk(13) or chk(14) or chk(15) or chk(16)
		then
		p.y = math.floor(p.y) - 1
		end
	end
	if love.keyboard.isDown('left') then
	p.x = p.x - p.s*dt
		if chk(1) or chk(2) or chk(3) or chk(4) or
		chk(5) or chk(6) or chk(7) or chk(8) or 
		chk(9) or chk(10) or chk(11) or chk(12) or 
		chk(13) or chk(14) or chk(15) or chk(16)
		then
		p.x = math.ceil(p.x) + 1
		end
	end
	if love.keyboard.isDown('right') then
	p.x = p.x + p.s*dt
		if chk(1) or chk(2) or chk(3) or chk(4) or
		chk(5) or chk(6) or chk(7) or chk(8) or 
		chk(9) or chk(10) or chk(11) or chk(12) or 
		chk(13) or chk(14) or chk(15) or chk(16)
		then
		p.x = math.floor(p.x) - 1
		end
	end	
I'm stuck here. I think making each tile and object and then running the collision by checking each tile with self might work but I have very basic knowledge on OOP with Lua.

Code: Select all

--tile (multiple tables can be created with a loop)
local tir = 0 --table iterator
local map_check = 1 --integer in map to check
local cx = u*3 --x constant
local cy = u*4 --y constant  
t = {} --tile objects go in here
for i = 1, #map do
	for j = 1, #map[i] do
		if map[i][j] == map_check then
			tir = tir + 1
			t[tir] = {}
			t[tir].x = (i-1)*u + cx
			t[tir].y = (j-1)*u + cy
			t[tir].w = u
			t[tir].h = u
			function t[tir]:tilecollision() --LINE 41 problem with syntax?
				CheckCollision(p.x,p.y,p.w,p.h,self.x,self.y,self.w,self.h)
			end 
		end
	end
end
I get this error
Screenshot 2016-02-26 18.47.53.png
Screenshot 2016-02-26 18.47.53.png (15.56 KiB) Viewed 1555 times
Basically how do I loop an or statement with n booleans.

(Unrelated: I can't seem to attach .love anymore, Is it my Mac settings?)
Last edited by Ekamu on Sat Feb 27, 2016 12:36 pm, edited 1 time in total.
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Multiple OR Booleans Issue

Post by airstruck »

I'd probably do something like this:

Code: Select all

local function canMove (entity, x, y)
    -- Do your checks here. Return true if entity can move there, else false.
end

local function tryMove (entity, x, y)
    if canMove(entity, x, y) then
        entity.x, entity.y = x, y
    end
end

-- In love.update (or another function called from love.update)

if love.keyboard.isDown('up') then
    tryMove(p, p.x, p.y - p.s * dt)
end
if love.keyboard.isDown('down') then
    tryMove(p, p.x, p.y + p.s * dt)
end
if love.keyboard.isDown('left') then
    tryMove(p, p.x, p.x - p.s * dt)
end
if love.keyboard.isDown('right') then
    tryMove(p, p.x, p.x + p.s * dt)
end
Inside canMove, you can probably just collision-check the tiles adjacent to the entity if you know which tile it's on, so you'll only have to check 8 or 9 tiles instead of the whole map.
function t[tir]:tilecollision()
The function declaration syntax sugar doesn't work with subscript notation. You'd have to write it as an assignment:

Code: Select all

t[tir].tilecollision = function (self)
    -- ...
end
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Multiple OR Booleans Issue

Post by s-ol »

An OR is true when at least one of the parameters is true. Therefore, as soon as you find ONE 'true' you are done; if you don't find any you know it's 'false'. Your first example works actually:

Code: Select all

function AreAnyTilesOne()
  for x=1,#map do
    for y=1,#map[x] do
      if map[x][y] == 1 then
        return true
      end
    end
  end
  return false -- if you leave this out, the function returns nil, which is also falsy, so you can just do that
end
If for some reason you want to visit all tiles (for example because you update each one but still want the return values OR'd, you need to keep state

Code: Select all

function ArenAnyTilesOne()
  local result = false
  for x=1,#map do
    for y=1,#map[x] do
      result = result or update_tile(x, y)
    end
  end
  return result
end
That's the same as

Code: Select all

return update_tile(1,1) or update_tils(1,2) or update_tile(1, ...) or update_tile(2, 1) or ...
(Except even that stops after the first "true", while the loop above doesn't)

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
Ekamu
Party member
Posts: 178
Joined: Fri Sep 20, 2013 11:06 am

Re: Multiple OR Booleans Issue

Post by Ekamu »

Wow. I actually made something like what I was planning on years ago. With functions to create the map and collision and even a basic map editor. (right click to place a tile, left click to remove a tile)
Its like I'm getting much worse in general logic skills and intelligence ever since I got a job and now work 9 - 5. Sometimes I miss school days. I was a lot sharper then. I'm 23 now, I made this when I was 18 (Like 4-5 years). (optimized the code from LOVE 8 to 10)

Anyway, looks like it works out. I might need to optimize some of the code with a TryMove() function buts its basically the same.
(I attached a .zip, you can change it to .love yourself. I think its a general problem with attachments. .love in not supported)

So the solution was like you where explaining. You check the area around the player and not the entire map. simplify your boolean to something recursive instead of doing the entire thing all in one go. Unless your searching for a needle in a haystack

Thanks for the OOP tip. So no syntax sugar in functions/loops?

Check out the source code if this is bugging you too. I'm going to optimize this with OOP and continue. One thing I learned. NEVER DELETE CODE.

(Note to Self. Get on Github ASAP)
Attachments
COL0.4.zip
(6.03 KiB) Downloaded 35 times
Post Reply

Who is online

Users browsing this forum: No registered users and 220 guests