0

I have the following loop:

    for tile_id, tile in corner_tiles.items():
        for neighbour in tile["neighbours"]:
            if not (neighbour in enemy_tiles) and tile["player"] == None:
                return tile_id

where: tile is a dictionary in the form of

{'counters': <number of counters on tile or None>, 
 'player': <player id of the player who holds the tile or None>,
 'neighbours': <list of ids of neighbouring tile>
}

and corner_tiles and enemy_tiles are dictionaries in the form of {<tile_id> : <tile>, ... }.

 

The loop always returns tile_id regardless of whether neighbour is in enemy_tiles or not, but doesn't if tile["player"] is not None. I have been trying to figure this out for quite a while but cannot seem to spot where I have gone wrong.

EDIT:

I have also tried:

for tile_id, tile in corner_tiles.items():
    if tile["player"] is None:
        for neighbour in tile["neighbours"]:
            if neighbour not in enemy_tiles:
                return tile_id

which acts the same way.

KOB
  • 4,084
  • 9
  • 44
  • 88
  • 3
    When in doubt, add parentheses. – Mark Ransom Jan 12 '16 at 19:35
  • 2
    Try `if neighbour not in enemy_tiles and tile["player"] is None:` - Idiomatic Python FTW. – thefourtheye Jan 12 '16 at 19:35
  • @thefourtheye I know `is None` is more pythonic than `== None`, but is there any reason why `==` wouldn't work? – Mark Ransom Jan 12 '16 at 19:36
  • 2
    Try `tile["player"] is None`. Do not use `==` to evaluate agains `None`. – Nelewout Jan 12 '16 at 19:37
  • precedence may be involved https://docs.python.org/3/reference/expressions.html#operator-precedence – njzk2 Jan 12 '16 at 19:38
  • also this answer is good: http://stackoverflow.com/questions/14247373/python-none-comparison-should-i-use-is-or – Paul H Jan 12 '16 at 19:39
  • All of the suggestions have had the same result. I have even tried moving `if tile["player"] is None` before the `for neighbour...` loop. However, I am new to Python and never realised the difference between `==` and `is`, so thank you for that. – KOB Jan 12 '16 at 19:42
  • Can you show us an example of both `neighbour` and `enemy_tiles`? What is their type? I simply cannot reproduce from this. – Nelewout Jan 12 '16 at 19:44
  • @KeithHall `neighbour` is a `tile_id` (`tile["neighbours"]` is a list of `tile_id`s) and `enemy_tiles` is a dictionary whose keys, not values, are `tile_id`s – KOB Jan 12 '16 at 19:48
  • This might be a data problem. You should add print functions at every step to explicitly tell you what data are being compared to what. – reynoldsnlp Jan 12 '16 at 19:55
  • `if neighbour is not in enemy_tiles`: Did you mean `if neighbour not in enemy_tiles`? – SethMMorton Jan 12 '16 at 19:55
  • @SethMMorton yes thank you, only made that typo here and not in my code – KOB Jan 12 '16 at 19:57
  • have you tried rearranging the parantheses to `if (not (neighbor in enemy_tiles)) and ...`? – Jeremy Fisher Jan 12 '16 at 20:38
  • if enemy_tiles is an empty or garbage list, then `if neighbour not in enemy_tiles` will always be true. ADD SOME PRINT STATEMENTS before the if statement, e.g. `print neighbour` `print enemy_tiles` `print (neighbour not in enemy_tiles)` – DisappointedByUnaccountableMod Jan 12 '16 at 20:52
  • @barny I am writing an algorithm which plays a board game in an app. I do not own, or cannot see the source code to the game. I am just writing the algorithm in a function which takes as a parameter the current state of the board and so my code can only be run in the app - therefore I cannot print anything. All I can return to the game is the tile_id for my next move. It is also impossible for `enemy_tiles` to be empty when this loop is executed – KOB Jan 12 '16 at 20:58
  • You don't need the source code of the game to print those values in the code you show. You __must__ have some actual data if you are running this code and it is giving an error. Print that actual data. It is the data that is making the code behave the way it does - for the code you show to always return tile_id, the if statement expression must evaluate to true, and as it is two tests and-ed together they must both be true. Or are you wasting everyone's time? – DisappointedByUnaccountableMod Jan 12 '16 at 21:03

1 Answers1

0

After much stress, I found the simple reason behind my error and I am kicking myself for missing it...

What my loop was supposed to be doing is making sure that ALL neighbours are not in enemy_tiles. Of course, it was evaluating as true nearly every time because there was a much higher probability that the first neighbour checked was not in enemy_tiles and so the statement is true and tile_id is returned after only checking one neighbour.

KOB
  • 4,084
  • 9
  • 44
  • 88