Python Python Collections Dungeon Game Hit points

Donald Bell
Donald Bell
4,494 Points

I need help with this code challenge.

There must be some subtle nuance I'm not getting right in my code.

movement.py
# EXAMPLES:
# move((1, 1, 10), (-1, 0)) => (0, 1, 10)
# move((0, 1, 10), (-1, 0)) => (0, 1, 5)
# move((0, 9, 5), (0, 1)) => (0, 9, 0)

```python
def move(player, direction):
    x, y, hp = player
    xd, yd = direction
    if ((x, y, hp == (0, 9, hp)) and (xd, yd == ((0, 1) || (-1, 0)))):
        hp -= 5
        return x, y, hp = (0, 9, hp)

    elif ((x, y, hp == (0, 0, hp)) and (xd, yd == ((0, -1) || (-1, 0)))):
        hp -= 5
        return x, y, hp = (0, 0, hp)

    elif ((x, y, hp == (9, 0, hp)) and (xd, yd == ((1, 0) || (0, -1)))):
        hp -= 5
        return x, y, hp = (9, 0, hp)

    elif ((x, y, hp == (9, 9, hp)) and (xd, yd == ((0, 1) || (1, 0)))):
        hp -= 5
        return x, y, hp = (9, 9, hp)
    else:
        return (x, y, hp)
    ```

1 Answer

Alex Koumparos
MOD
Alex Koumparos
Python Web Development Treehouse Moderator 32,442 Points

Hi Donald,

Firstly, you have markdown inside your Python code. This will cause a syntax error.

Secondly, you have a number of errors and issues with your conditional logic. Let's take the first if statement as an example:

if ((x, y, hp == (0, 9, hp)) and (xd, yd == ((0, 1) || (-1, 0)))):

I'm going to reformat your code to make it easier to see what's going on. These reformatting changes are purely aesthetic and don't change the syntax of your code:

if (
    x, y, hp == (0, 9, hp) and
    (
        xd, yd == (
            (0, 1) ||
            (1, 0)
        )
    )
):

We'll look at the first conditional test. Let's fire up the Python interpreter and see what we get when we evaluate this (Assume we've set x to 1 and y to 4):

>>> x, y, hp == (0, 9, hp)
(1, 4, False)

This is probably not what you expected. You probably expected this to come back with False. Instead you are defining a three-tuple where the first element is x, the second element is y and third element is the result of comparing hp to the tuple (0, 9, hp).

Note, this bug is especially pernicious because any non-empty tuple is truthy in Python:

>>> if (1, 4, False):
...     print("I'm True!")
...
I'm True!

So this particular clause in your if statement will always evaluate to True.

What you probably meant to do was:

>>> (x, y, hp) == (0, 9, hp)
False

This compares the tuple on the left to the tuple on the right, and comes back with the False that you were expecting.

It's probably worth a little digression here to ask, what's the point of comparing hp == hp? That's always going to be True. You could shave off a few characters and get the same result by replacing (x, y, hp) == (0, 9, hp) with (x, y) == (0, 9).

Let's move on to the second clause in your if statement. I'm going to assume that we've gone ahead and applied the same correction to this clause as we need to make to the previous clause. So instead of xd, xy == ... it now looks like this:

(xd, yd) == (
    (0, 1) ||
    (1, 0)
)

When we try this out in the Python interpreter we get:

>>> (xd, yd) == ((0, 1) || (1, 0))
  File "<stdin>", line 1
    (xd, yd) == ((0, 1) || (1, 0))
                         ^
SyntaxError: invalid syntax

Python doesn't use the || sequence to represent boolean OR. Instead it uses the keyword or (the same way that Python uses and instead of && to represent AND).

We'll fix this and see what we get from the Interpreter now (assume we've set xd to 0 and yd to 1):

>>> (xd, yd) == ( (0, 1) or (1, 0) )
True

Ok, that looks like what we were expecting. But just to be sure, let's try setting xd to 1 and yd to 0, then running the same code:

>>> (xd, yd) == ( (0, 1) or (1, 0) )
False

Huh? Let's look again at the right side of your comparison. When you compare two values using OR, Python will return the first value that is truthy.

For example:

>>> 1 or 2
1
>>> 0 or 5
5
>>> "hello" or "world"
'hello'
>>> "" or "foo"
'foo'

Since (0, 1) is truthy, the right side of the comparison gets reduced to (0, 1) and the comparison is effectively:

>>> (xd, yd) == (0, 1)

Thirdly, you have a conceptual error: you are only testing player objects in the corners of the grid and assuming all other locations freeze the player in place.

Suppose player was on the bottom edge of the board, in the middle (with 10 hit points): (5, 0, 10) and tried to move straight down (0, -1). The player should lose 5 hit points and remain in place. But in your code the player would stay in their position with no hp changes.

Alternatively, suppose the player was somewhere in the middle of the board, say (5, 4, 10) and moved diagonally up and to the right (1, 1). You should end up with (6, 5, 10). But your code will end up with (5, 4, 10).

Hope these observations point you in the right direction. Let me know if you are still stuck and I'll give you some more hints.

Cheers

Alex