0

I'm writing a function for a small game in which a list of jobs is populated each turn. The jobs themselves are objects with a route, time, and pay attribute.

I want the list to be 5 items total and randomly populated by picking from a list of routes and pay grades.

I have a for loop to iterate 5 times, and I'm wanting the pay grade selected to be 5 only if a certain two routes are selected. Otherwise, the pay grades will be a random number between 1 and 4.

When I set the pay grade to 5 in the IF clause, it never makes it to the else clause even if the conditions of the IF are not true. I'm not sure what I'm doing wrong here.

for pick in range(5):
    job = random.choice(random_routes)
    if job == 'Military Base' or 'Raiders':
        pay_key = 5
    else:
        pay_key = random.randint(1, 4)
    pay = pay_grades[pay_key]

    job_postings.append(Job(job, routes[job], pay))

printing the first index attributes from the new job_postings list always returns level 5 pay numbers even if the route picked was not Military Base or Raiders.

Here are the route and pay dictionaries:

routes = {'Boneyard': 5, 'Brotherhood': 6, 'Cathedral': 6, 'Junktown': 4,
          'Military Base': 14, 'Necropolis': 5, 'Raiders': 10, 'Shady Sands': 11}

pay_grades = {
    1: random.randrange(200, 401, 50),
    2: random.randrange(300, 501, 50),
    3: random.randrange(400, 601, 50),
    4: random.randrange(500, 701, 50),
    5: random.randrange(900, 1600, 50),
}
martineau
  • 119,623
  • 25
  • 170
  • 301
madmonkey
  • 83
  • 8
  • 4
    `if job == 'Military Base' or 'Raiders':` should probably be `if job == 'Military Base' or job == 'Raiders':`. – 9769953 Jan 24 '21 at 19:09
  • 2
    `job == 'Military Base' or 'Raiders'` will always be true, because `'Raiders'` is a truthy value and you've `or`ed it with `job == 'Military Base'`. – Samwise Jan 24 '21 at 19:09
  • 2
    With your current if-clause, the second half after the `or`, `'Raiders'` always evaluates to `True` (since a non-empty string is always `True` in Python), and thus the `else` will never be entered. – 9769953 Jan 24 '21 at 19:10
  • @Samwise wow thanks, should've seen that – madmonkey Jan 24 '21 at 19:12
  • Since this question is so common it would be nice to know what is the canonical answer – Asocia Jan 24 '21 at 19:13
  • 1
    Does this answer your question? [How to test multiple variables against a value?](https://stackoverflow.com/questions/15112125/how-to-test-multiple-variables-against-a-value) – Robin Zigmond Jan 24 '21 at 19:15
  • @RobinZigmond yes it does, thank you. – madmonkey Jan 24 '21 at 19:23

2 Answers2

2

The problem lies on this line:

if job == 'Military Base' or 'Raiders':

The == operator takes precedence over the or operator, which means it's evaluating the same as,

if (job == 'Military Base') or ('Raiders'):

Any non-empty string evaluates to true (compare not '' and not 'abc' in the REPL) and therefore 'Raiders' and this entire conditional expression will always evaluate to true.

What you actually seem to want is,

if job == 'Military Base' or job == 'Raiders':
  • 2
    Another, possibly preferable approach would be `if job in ( 'Military Base', 'Raiders'):` The advantage is that this scales out nicely as we add options, and it allows you to make the choices more dynamic (they are no longer hard-coded, so we can pass them around, etc) – Jon Kiparsky Jan 24 '21 at 19:18
  • And if we talk about performance we use a set: `if job in {'Military Base', 'Raiders'}:`. But of course with just two entries that's not important. – Matthias Jan 24 '21 at 20:54
0

when you say

    if job == 'Military Base' or 'Raiders':

second condition means: if 'Raiders' == True and it does not mean Raiders equals 'Military Base'.

corrected: if job == 'Military Base' or job == 'Raiders':