Requesting help: How to test for river crossing in a wargame?

Greetings all, been awhile and I started back up coding my wargame. I am stuck on something and would appreciate your help if you are willing. I have a data structure for tiles I am using and when declaring an attack from one tile to another I am trying to determine if it is crossing a River. I have established that rivers run along a tile side(s). Example: Tile[x].NorthRiver, Tile[x].EastRiver, Tile[x].SouthRiver, Tile[x].WestRiver all will be 0 if there isnt a river, and 1 if there is. I am struggling to come up with an algorithm to test all possibilities to return true(well River=1 means that yes this unit has to cross a river). Here’s what I have so far but I need to be able to test cases where you are moving say NE. I need to be able to test the square immediately to the N to see if it ALSO has a river on it’s E side as that should also return true. I think what I have works for pure N, S, E, W tests but how to test for that kind of cardinal point cases? I think what I have works for one type of cardinal point test where there is a river to your N AND E but I realized the case above would be missed. This is a real tough one for me, rest of the game…not a problem so far.

The test case also needs to handle checking the sqare to the east and see if that has a N river too.

IE: the following would all return true if moving/attacking NE:

River N AND E

River N but not E AND River N on square to the E

River E but not N AND River E on square to the N

Having a hard time on last 2 cases…

CODE:

local function RiverCrossingCheck(AX, AY, DX, DY)

--AX, AY, DX, DY are the tile x and y values(not pixel points) so that is what must be passed to this function
--Determine if the attacker has to cross a river by checking the vector of the attack. 
--compare the vector with a test to see if that side has a river
--if that side has a river return true, else false

--NOTE: The map will have to be marked as a river on both sides.  IE: if a tile has a river on it's south side then the tile to the immediate south side must be marked with a North river as well...


--attackers riversides
local N = 0
local NW = 0
local NE = 0
local E = 0
local S = 0
local SE = 0
local SW = 0
local W = 0

local River = 0
local AT=0

--Determine the Attackers tile number so you can reference the river properties.
AT = ((AY-1) * MapWidth) + AX;

--ATTACKING NORTH
if (AY-DY = 1) then
	N = Tile[AT].NorthSideRiver
end

--ATTACKING EAST
if (AX-DX = -1) then
	E = Tile[AT].EastSideRiver
end

--ATTACKING SOUTH
if (AY-DY = -1) then
	S = Tile[AT].SouthSideRiver
end

--ATTACKING WEST
if (AX-DX = 1) then
	W = Tile[AT].WestSideRiver
end

--Check all 8 cardinal points to find the vector of attack:
--Need to get the riversides on all 8 adjacent squares:
--because if a river is on E but not N AND your attacking NE
--it would have been missed by my initial algorithym because 
--if the river in the square to the N also has and E river side that 
--should return true..
--
--So 1 algorithm to test pure N, S, E, W
--another for NE, NW, SE, SW is also needed.

if (N==1 ) then 
	if(E==1) then
		River = 1
	end
	
	if(W==1) then
		River = 1
	end
end

return River

end

@Gib I might add river info to each tile similar to this. Then you can check the river location with a lot less code. I show 4 if statements as examples.


function setup()
    -- tile containing river info.
    tile={  {river={"n","ne"}},
            {river={"e","se"}},
            {river={"w"}} }
    
    if riverLocation(1,"n") and riverLocation(1,"ne") then
        print("true")
    else
        print("false")
    end

    if riverLocation(2,"e") and riverLocation(2,"se") then
        print("true")
    else
        print("false")
    end

    if riverLocation(2,"n") and riverLocation(2,"ne") then
        print("true")
    else
        print("false")
    end

    if riverLocation(3,"w") then
        print("true")
    else
        print("false")
    end

end

function riverLocation(location,dir)  
    for pos=1,8 do
        if tile[location].river[pos]==dir then
            return true
        end
    end 
    return false  
end

Since the river details (and your rules for crossing them) won’t change, you could actually use dave’s approach to build a table right at the beginning, which tells you which way to go for each tile on the board. This would keep your code much cleaner.

@Gib The “for” loop in the Function riverLocation() can be changed to what I have below. It didn’t need to loop to 8, but just the size of direction data in each table.


function riverLocation(location,dir)  
    for pos=1,#tile[location].river do
        if tile[location].river[pos]==dir then
            return true
        end
    end 
    return false  
end

@Gib Here’s a riverLocation function that will allow you to check multiple directions using one “if” statement by passing multiple directions.


function setup()
    -- tile containing river info.
    tile={  {river={"n","ne","e","se","s"}},
            {river={"e","se","s"}},
            {river={"w","nw"}} }
    
    if riverLocation(1,"n","ne","se","s") then
        print("true")
    else
        print("false")
    end
    
    if riverLocation(1,"ne","s","sw") then
        print("true")
    else
        print("false")
    end
    
    if riverLocation(3,"w") then
        print("true")
    else
        print("false")
    end

end

function riverLocation(...)
    location=arg[1]
    temp1=true
    for z=2,#arg do
        temp2=false
        for pos=1,#tile[location].river do
            if tile[location].river[pos]==arg[z] then
                temp2=true
            end
        end
        if not temp2 then
            temp1=false
        end    
    end 
    return temp1
end

Oh thanks bud, that’s so much nicer and concise! I don’t fully understand it yet but will study it and probably learn a thing or two about better data structuring in programming.