I am attempting to make a simple, flowing dynamic across a grid of tiles for a game. Essentially, I want water values of cells in the grid to flow to one adjacent cell each frame according to a couple rules.
Pls consult image below. I ran out of words trying to explain and include code. Context_img_bcIranoutofwords
Below is the flow function I am calling on the tiles. I apologize I know it's excessive to write it out like this, and if you have a way of consolidating I would love to hear it! I mainly did this to assure that I could see every single step because I cannot figure out why program is behaving how it is.
The question is: Is there something specifically about iterating through a list of lists like this that would cause the flow function to preferentially flow to the east? I have tried my best in the function to force a fair decision between the east and west tiles. And if it's not that, is there something else in this function that could be causing this?
(I have double checked that the adjacency functions are working as they should. So I know it has nothing to do with that.)
In the function "self.BLANK_adj" is a list assigned when finding adjacent squares. "self.BLANK_adj[0]" = the beta tile object. "self.BLANK_adj[_1]" = a check that is True if the adjacent square being looked
def gravity_water_flow_nl_2(self):
#self._adj [0] = beta tile
#self._adj [1] = greater alt check
flow_tile = self
if self.water > FLOW:
#S exists
if self.S_adj != None:
#S not tall
if self.S_adj[1] != True:
#S not full
if self.S_adj[0].water < (100-FLOW):
flow_tile = self.S_adj[0]
#S Full
else:
#S full, W exists
if self.W_adj != None:
#W not tall
if self.W_adj[1] != True:
#W not full
if self.W_adj[0].water < (100 - FLOW):
#Check E
#E exists
if self.E_adj != None:
#E tall
if self.E_adj[1] == True:
flow_tile = self.W_adj[0]
#E not tall
else:
#E not full
if self.E_adj[0].water <= (100 - FLOW):
#E less water than self
if self.E_adj[0].water < self.water:
#W less water than self
if self.W_adj[0].water < self.water:
if self.E_adj[0].water > self.W_adj[0].water:
flow_tile = self.W_adj[0]
elif self.E_adj[0].water < self.W_adj[0].water:
flow_tile = self.E_adj[0]
else:
flow_tile = random.choice([self.E_adj[0],self.W_adj[0]])
#W equal or more than self
else:
flow_tile = self.E_adj[0]
#E equal or more than self
else:
flow_tile = self.W_adj[0]
#E doesn't exist
else:
flow_tile = self.W_adj[0]
#W full
else:
#E exists
if self.E_adj != None:
#E not tall
if self.E_adj[1] != True:
#E not full
if self.E_adj[0].water < (100-FLOW):
flow_tile = self.E_adj
#E full
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E tall
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E doesn't exist
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#W tall
else:
#E exists
if self.E_adj != None:
#E not tall
if self.E_adj[1] != True:
#E not full
if self.E_adj[0].water < (100-FLOW):
flow_tile = self.E_adj
#E full
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E tall
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E doesn't exist
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#S full, W doesn't exist
else:
#E exists
if self.E_adj != None:
#E not tall
if self.E_adj[1] != True:
#E not full
if self.E_adj[0].water < (100-FLOW):
flow_tile = self.E_adj
#E full
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E tall
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E doesn't exist
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#S tall
else:
#W exists
if self.W_adj != None:
#W not tall
if self.W_adj[1] != True:
#W not full
if self.W_adj[0].water < (100 - FLOW):
#Check E
#E exists
if self.E_adj != None:
#E tall
if self.E_adj[1] == True:
flow_tile = self.W_adj[0]
#E not tall
else:
#E not full
if self.E_adj[0].water < (100 - FLOW):
#E less water than self
if self.E_adj[0].water < self.water:
#W less water than self
if self.W_adj[0].water < self.water:
if self.E_adj[0].water > self.W_adj[0].water:
flow_tile = self.W_adj[0]
elif self.E_adj[0].water < self.W_adj[0].water:
flow_tile = self.E_adj[0]
else:
flow_tile = random.choice([self.E_adj[0],self.W_adj[0]])
#W equal or more than self
else:
flow_tile = self.E_adj[0]
#E equal or more than self
else:
flow_tile = self.W_adj[0]
#E doesn't exist
else:
flow_tile = self.W_adj[0]
#W full
else:
#E exists
if self.E_adj != None:
#E not tall
if self.E_adj[1] != True:
#E not full
if self.E_adj[0].water < (100-FLOW):
flow_tile = self.E_adj
#E full
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E tall
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E doesn't exist
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#W tall
else:
#E exists
if self.E_adj != None:
#E not tall
if self.E_adj[1] != True:
#E not full
if self.E_adj[0].water < (100-FLOW):
flow_tile = self.E_adj
#E full
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E tall
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E doesn't exist
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#W doesn't exist
else:
#E exists
if self.E_adj != None:
#E not tall
if self.E_adj[1] != True:
#E not full
if self.E_adj[0].water < (100-FLOW):
flow_tile = self.E_adj
#E full
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E tall
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E doesn't exist
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#S doesn't exist
else:
#W exists
if self.W_adj != None:
#W not tall
if self.W_adj[1] != True:
#W not full
if self.W_adj[0].water < (100 - FLOW):
#Check E
#E exists
if self.E_adj != None:
#E tall
if self.E_adj[1] == True:
flow_tile = self.W_adj[0]
#E not tall
else:
#E not full
if self.E_adj[0].water < (100 - FLOW):
#E less water than self
if self.E_adj[0].water < self.water:
#W less water than self
if self.W_adj[0].water < self.water:
if self.E_adj[0].water > self.W_adj[0].water:
flow_tile = self.W_adj[0]
elif self.E_adj[0].water < self.W_adj[0].water:
flow_tile = self.E_adj[0]
else:
flow_tile = random.choice([self.E_adj[0],self.W_adj[0]])
#W equal or more than self
else:
flow_tile = self.E_adj[0]
#E equal or more than self
else:
flow_tile = self.W_adj[0]
#E doesn't exist
else:
flow_tile = self.W_adj[0]
#W full
else:
#E exists
if self.E_adj != None:
#E not tall
if self.E_adj[1] != True:
#E not full
if self.E_adj[0].water < (100-FLOW):
flow_tile = self.E_adj
#E full
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E tall
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E doesn't exist
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#W tall
else:
#E exists
if self.E_adj != None:
#E not tall
if self.E_adj[1] != True:
#E not full
if self.E_adj[0].water < (100-FLOW):
flow_tile = self.E_adj
#E full
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E tall
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E doesn't exist
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#W doesn't exist
else:
#E exists
if self.E_adj != None:
#E not tall
if self.E_adj[1] != True:
#E not full
if self.E_adj[0].water < (100-FLOW):
flow_tile = self.E_adj
#E full
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E tall
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
#E doesn't exist
else:
#N exists
if self.N_adj != None:
#N not tall
if self.N_adj[1] != True:
#N not full
if self.N_adj[0].water < (100 - FLOW):
flow_tile = self.N_adj
I suggest that you split the logic into helper function for each direction then you'll collect all eligible direction then perform random.choice()
on it
direction = []
## Check condition for each direction
## you can update values based on it
if condition_for_W:
direction.append(W_adj[0])
if condition_for_E:
direction.append(E_adj[0])
if condition_for_N:
direction.append(N_adj[0])
if condition_for_S:
direction.append(S_adj[0])
if direction:
flow_tile = random.choice(direction)
Try this:
import random
FLOW = 10 # Min
class Tile:
def __init__(self, water=0, tall=False):
self.water = water
self.tall = tall
self.N_adj = None
self.S_adj = None
self.E_adj = None
self.W_adj = None
def can_flow_to(self, adj):
# True and False and True
return adj and not adj[1] and adj[0].water < (100 - FLOW)
def water_flow(self):
flow_tile = self
# S -> W -> E(E tall = W)
if self.water <= FLOW:
return flow_tile
# flow South immediately
if self.can_flow_to(self.S_adj):
return self.S_adj[0]
# east and west options
options = []
if self.can_flow_to(self.W_adj):
options.append(self.W_adj[0])
if self.can_flow_to(self.E_adj):
options.append(self.E_adj[0])
# Random
if self.W_adj and self.E_adj:
W_ok = self.W_adj[0] in options
E_ok = self.E_adj[0] in options
if W_ok and E_ok:
W_water = self.W_adj[0].water
E_water = self.E_adj[0].water
if W_water < self.water or E_water < self.water:
if W_water < E_water:
return self.W_adj[0]
elif E_water < W_water:
return self.E_adj[0]
else:
return random.choice([self.E_adj[0], self.W_adj[0]])
else:
return self.W_adj[0] # default
if options:
return random.choice(options)
# Check North
if self.can_flow_to(self.N_adj):
return self.N_adj[0]
return flow_tile
def test_flow():
for i, case in enumerate([case1 ,case2, case3, case4, case5]):
result_tile = case()
print(f"Case {i+1}: flows to ->",result_tile)
def case1():
center = Tile(water=80)
south = Tile(water=30, tall=False)
center.S_adj = [south, False]
res = center.water_flow()
res = center.water_flow()
return result(center=center, res=res)
def case2():
center = Tile(water=80)
south = Tile(water=95, tall=False)
east = Tile(water=25, tall=False)
west = Tile(water=10, tall=False)
center.S_adj = [south, False]
center.E_adj = [east, False]
center.W_adj = [west, False]
res = center.water_flow()
return result(center=center, res=res)
def result(center, res):
if center.N_adj != None:
if res == center.N_adj[0]:
return "North"
if center.S_adj != None:
if res == center.S_adj[0]:
return "South"
if center.E_adj != None:
if res == center.E_adj[0]:
return "east"
if center.W_adj != None:
if res == center.W_adj[0]:
return "West"
else:
return "Center"
def case3():
center = Tile(water=80)
west = Tile(water=20, tall=False)
east = Tile(water=20, tall=False)
center.W_adj = [west, False]
center.E_adj = [east, False]
res = center.water_flow()
return result(center=center, res=res)
def case4():
center = Tile(water=80)
south = Tile(water=20, tall=True)
west = Tile(water=20, tall=True)
east = Tile(water=15, tall=False)
center.S_adj = [south, True]
center.W_adj = [west, True]
center.E_adj = [east, False]
res = center.water_flow()
return result(center=center, res=res)
def case5():
center = Tile(water=80)
south = Tile(water=90, tall=True)
east = Tile(water=100, tall=False)
west = Tile(water=100, tall=False)
north = Tile(water=10, tall=False)
center.S_adj = [south, True]
center.E_adj = [east, False]
center.W_adj = [west, False]
center.N_adj = [north, False]
res = center.water_flow()
return result(center=center, res=res)
test_flow()
It should work