0

I can't seem to know a solution to how my_damage can create a new random value.

That's because while keeps the random.randrange the same.


So let's say:

my_damage = random.randrange(40, 45)

Then we add the combat formula:

jack_health = (jack_health + jack_defense) - my_damage
print(deskemon + " HAVE INFLICTED " + str(my_damage) + " TO CHIPHEAD")

Then this comes out:

LILWILLY HAVE INFLICTED 41 TO CHIPHEAD
CHIPHEAD HAS 261 HITPOINTS LEFT!
...
...
...
CHIPHEAD HAVE INFLICTED 5 TO LILWILLY
LILWILLY HAS 261 HITPOINTS LEFT!
BATTLE MENU:

(1) ATTACK
(2) SPECIAL ATTACK
> 1
LILWILLY HAVE INFLICTED 41 TO CHIPHEAD
CHIPHEAD HAS 222 HITPOINTS LEFT!
...
...
...
CHIPHEAD HAVE INFLICTED 5 TO LILWILLY
LILWILLY HAS 222 HITPOINTS LEFT!

Everytime, I use the code, the random value stays the same, it doesn't change.

I know a solution but because my_damage can be changed via input to 4 other random values earlier in my program, I cannot use this:

jack_health = (jack_health + jack_defense) - random.randrange(20, 25)
print(deskemon + " HAVE INFLICTED " + str(random.randrange(20, 25)) + " TO CHIPHEAD")

Notes:

Here's entire code in pastebin.com if you need information: http://pastebin.com/iij5C16z

  • You need to seed the random number generator – imran May 01 '14 at 16:29
  • Copy the code in the question. – devnull May 01 '14 at 16:31
  • possible duplicate of [how to query seed used by random.random()?](http://stackoverflow.com/questions/5012560/how-to-query-seed-used-by-random-random) – Tony Hopkinson May 01 '14 at 16:33
  • @TonyHopkinson - This isn't a duplicate to that question, his code structure is wrong. He's not making the connection between an assignment and a function call. He's only assigned a value once, but expects it to change on _retrieval_ afterward. A class property could do that ... but it doesn't just _happen_. – g.d.d.c May 01 '14 at 16:42
  • @g.d.d.c oops slack moment thought it was yet another seed question. – Tony Hopkinson May 01 '14 at 16:46

2 Answers2

1

When you call a random number, the function return a single value. Hence your error. You need to come up with a way of calling the function every time you want a new value.

There is something clever that you can do that requires decorators that I will show below.

def recall_last(func):
    def _inner(*args, **kwargs):
        if args:
            func.last_dealt = func(*args,**kwargs)
        else:
            func.last_dealt = getattr(func,'last_dealt',0)
        return func.last_dealt
    return _inner

@recall_last
def rand_damage(*args):
    return random.randrange(*args)

This code will return a new value every time you pass it an lower and upper bound to use in the randrange function. If nothing is passed, then it returns the last value generated. Then this would work in your code

if deskemon_selection_input == "1":
    deskemon = "TIMOSHA"
    my_health = 500
    my_damage = (20, 25)
    my_defense = random.randrange(10, 15)
    my_specialattack = 0
    print("You have selected TIMOSHA as your Deskemon")
    deskemon_selection_loop = False

   ....
jack_health = (jack_health + jack_defense) - rand_damage(*my_damage)
print(deskemon + " HAVE INFLICTED " + str(rand_damage()) + " TO CHIPHEAD")
Chris Hagmann
  • 1,086
  • 8
  • 14
  • No, this still is not right. You're still only calling `random.randrange` _once_, you've simply added a lambda expression. The result value in `my_damage` is still a static value. – g.d.d.c May 01 '14 at 16:44
  • Without seeing his could, I have no clue that he wouldn't use it right. I will edit answer to make said comment. – Chris Hagmann May 01 '14 at 16:45
  • Unfortunately, this happens: `Traceback (most recent call last): File "Deskemon.py", line 224, in jack_health = (jack_health + jack_defense) - rand_damage(my_damage) File "Deskemon.py", line 15, in rand_damage return random.randrange(values) File "C:\Program Files\Python\lib\random.py", line 178, in randrange istart = _int(start) TypeError: int() argument must be a string or a number, not 'tuple'` – Exercise To The Reader May 03 '14 at 16:41
  • You need an asterisk in front of my_damage. As is in my code. This is a splat operator if your want to research it more. I will update to clarify on Monday from a computer and not my phone. – Chris Hagmann May 04 '14 at 02:41
  • I got this now: `Traceback (most recent call last): File "Deskemon.py", line 225, in print(deskemon + " HAS INFLICTED " + str(rand_damage()) + " TO CHIPHEAD") File "Deskemon.py", line 15, in rand_damage return random.randrange(*values) TypeError: randrange() missing 1 required positional argument: 'start'` – Exercise To The Reader May 04 '14 at 12:39
  • Do you have the @recall_last directly above def rand_damage(*values) – Chris Hagmann May 04 '14 at 14:44
  • Nope, I'll get to it. – Exercise To The Reader May 04 '14 at 15:17
  • unfortunately, the `print` statement creates a new random value, like this: `TIMOSHA HAS INFLICTED 25 TO CHIPHEAD CHIPHEAD HAS 277 HITPOINTS LEFT!`. But you've fixed one half of the problem., I'll give kudos for that. – Exercise To The Reader May 04 '14 at 15:29
  • Could you put you update code on that website you posted so that I can see how you are implementing it? – Chris Hagmann May 06 '14 at 02:30
  • The print statement is not creating a new random value. What is going on is that the damage taken is the difference between damage and defense but only the damage part is being shown. – Chris Hagmann May 06 '14 at 15:21
  • Here is a version of your game using classes http://pastebin.com/YvBxRBEH. It should be a good starting point. As you can see in the code, the random value is called every attack. The surrounding code is meant only as suggestions and I tried to include some interesting things. – Chris Hagmann May 06 '14 at 16:52
1

i know this should be implemented with classes but i am still learning classes so this is not using classes:

import random

def damage( attack ):
    return random.randrange(attack*0.9, attack*1.1)

my_name = 'LILWILLY' 
my_health = 300
my_defense = 10
my_attack = 40

enemy_name = 'CHIPHEAD'
enemy_health = 100
enemy_defense = 1
enemy_attack = 40

while my_health > 0 and enemy_health > 0:
    my_damage = damage( my_attack )
    enemy_damage = damage( enemy_attack )
    my_health = (my_health + my_defense) - enemy_damage
    enemy_health = (enemy_health + enemy_defense) - my_damage
    print( '{0} HAVE INFLICTED {1} TO {2}'.format( my_name, my_damage, enemy_name ))
    print( '{0} has {1} hitpoints left'.format(enemy_name, enemy_health ) )
    print( '{0} HAVE INFLICTED {1} TO {2}'.format( enemy_name, enemy_damage, my_name ))
    print( '{0} has {1} hitpoints left'.format(my_name, my_health ) )

else:
    if my_health > 0:
        print ( '***{} has slain {}!'.format(my_name, enemy_name))
    elif enemy_health > 0:
        print ( '***{} has slain {}!'.format(enemy_name, my_name))
    else:
        print('BOTH {} and {} have died'.format(my_name, enemy_name))

the result i got:

LILWILLY HAVE INFLICTED 42 TO CHIPHEAD
CHIPHEAD has 59 hitpoints left
CHIPHEAD HAVE INFLICTED 36 TO LILWILLY
LILWILLY has 274 hitpoints left
LILWILLY HAVE INFLICTED 40 TO CHIPHEAD
CHIPHEAD has 20 hitpoints left
CHIPHEAD HAVE INFLICTED 43 TO LILWILLY
LILWILLY has 241 hitpoints left
LILWILLY HAVE INFLICTED 41 TO CHIPHEAD
CHIPHEAD has -20 hitpoints left
CHIPHEAD HAVE INFLICTED 40 TO LILWILLY
LILWILLY has 211 hitpoints left
***LILWILLY has slain CHIPHEAD!
mr.matt
  • 51
  • 3
  • Unfortunately, the `print` lines are wrong. So if the combat calculations ay that `jack_health` is deducted by 42. The `print` line will show a new `random` value, which makes this answer invalid. – Exercise To The Reader May 03 '14 at 16:35