Hungry ant AI: any food here? I'm working on a little AI to simulate ants (very basic). The full code can be found on Github. This function (in Ants.py) takes a list of Tuples containing coordinates and tells whether or not the ant is over one of them.

def Got_Food(self,all_foods):
    foods = []
    x,y = self.location[0],self.location[1]
    c_x,c_y = self.size[0],self.size[1]
    for food in all_foods:
          if food[1] &gt;= y-c_y and food[1] &lt;= y+c_y \
          and food[0] &gt;= c_x and food[0] &lt;=x+c_x:
            if food[1] &gt; y and food[1] &lt;y+c_y\
            and food[0] &gt; x and food[0] &lt;x+c_x:
                foods.append((food[0],food[1]))
            elif food[1] &lt; y and food[1] &gt;y-c_y\
            and food[0]  &gt; x and food[0] &gt;x-c_y:
                foods.append((food[0],food[1]))
          if food[0] &gt;= x-c_x and food[0] &lt;= x+c_x \
          and food[1] &gt;= y and food[1] &lt;=y+c_y:
                foods.append((food[0],food[1]))
    if len(foods) == 0:
        return None
    return foods


This function works exactly as I want, but it is probably one of the ugliest I've ever seen or written. Does anyone know a way around all these nested loops?
Disclaimer: Current version of the code seems to be very weirdly indented. Some comments might be wrong because of some misinterpretation of your code.

Style

Python has a style guide called PEP 8. It is usually a good idea to try to stick to it unless you have good reasons not to. In any case, it is definitly worth the read. You'll find various tools to check compliancy. In your case, the main issues would be : naming (snake_case is recommended for function names), spacing (whitespace around operators), indentation (4 spaces)

Design

Your function returns either a list of food or None is there is no food. This seems to be more complicated than it should be: it could return a list of food (empty is there is no food). It makes your function easier to use, easier to explain and more concise: you can simply remove the if len(foods) == 0: condition.

From the Zen of Python:


  Special cases aren't special enough to break the rules.


In any case, your function deserves some documentation.

Tuple unpacking

One of my favorite feature of Python is iterable unpacking. You can do something like:

a, b, c = my_list_with_3_elements


and have easy access to the different elements (and an exception if the list has the wrong number of elements).

In your case, assuming location and size have the wrong length, you could simply write:

 x, y = self.location
 c_x, c_y = self.size


This is very convenient to avoid long expressions with error-prones bracket access to a particular index.

Going further, you could do the same with food[0] and food[1].

Now, (assuming I haven't broken too many things) looks like:

def got_food(self, all_foods):
   foods = []
   x, y = self.location
   c_x, c_y = self.size
   for f_x, f_y in all_foods:
      if f_y &gt;= y - c_y and f_y &lt;= y + c_y and f_x &gt;= c_x and f_x &lt;= x + c_x:
          if f_y &gt; y and f_y &lt; y + c_y and f_x &gt; x and f_x &lt; x + c_x:
              foods.append((f_x, f_y))
          elif f_y &lt; y and f_y &gt; y - c_y and f_x  &gt; x and f_x &gt; x - c_y:
              foods.append((f_x, f_y))
      if f_x &gt;= x - c_x and f_x &lt;= x + c_x and f_y &gt;= y and f_y &lt;= y + c_y:
            foods.append((f_x, f_y))
  return foods


Chained comparisons

From the doc:


  Comparisons can be chained arbitrarily, e.g., x &lt; y &lt;= z is equivalent to x &lt; y and y &lt;= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x &lt; y is found to be false).


In your case, many things can be rewritten:

def got_food(self, all_foods):
   foods = []
   x, y = self.location
   c_x, c_y = self.size
   for f_x, f_y in all_foods:
      if y - c_y &lt;= f_y &lt;= y + c_y and c_x &lt;= f_x &lt;= x + c_x:
          if y &lt; f_y &lt; y + c_y and x &lt; f_x &lt; x + c_x:
              foods.append((f_x, f_y))
          elif y &gt; f_y &gt; y - c_y and f_x &gt; x and f_x &gt; x - c_y:
              foods.append((f_x, f_y))
      if x - c_x &lt;= f_x &lt;= x + c_x and y &lt;= f_y &lt;= y + c_y:
            foods.append((f_x, f_y))
  return foods


I do not understand enough of the intent to go any further (also I suspect the condition f_x &gt; x is wrong).