tenebris_lumen tenebris_lumen - 9 months ago 34
Python Question

Bank Robbery Simulator

A bit of background to this program before I get into my issue:

I am attempting to create a program that simulates a robbery. The robber, guard, and door all have hard-coded values.

The robber moves closer to the door to escape with each iteration of the while loop. Also, the guard is moving closer to the robber with each loop iteration. Both of these actions are handled by the computeChanges function.

If the robber makes it to the door at (0, 0) before the guard gets to him, then the robber escapes and the last position of the guard is printed.

If the guard catches the robber before he makes it to the door, the last position of both the robber and the guard is printed.

The problem that I am running into at execution is that the values of the robber and guard are not changing after being passed into the computeChanges function. This results in an infinite loop.

What am I missing? Reassignment of the X and Y positions should be occurring at the last two lines within the computeChanges function.

Any and all help is appreciated.





Code:

from numpy import arctan, sin, cos
from math import pi, copysign, sqrt

# Used to prevent objects from overshooting one another
def normalizeSpeed(speed1, speed2, maxSpeed):
if speed1 > speed2:
larger = speed1
elif speed2 > speed1:
larger = speed2
speed1 = speed1 / larger * maxSpeed
speed2 = speed2 / larger * maxSpeed

# Used to compute the change in position for given object
def computeChanges(movingX, movingY, speed, targetX, targetY):
bigTriangleWidth = movingX - targetX
bigTriangleHeight = movingY - targetY
bigTriangleRatio = bigTriangleWidth / bigTriangleHeight
bigTriangleAngle = arctan(bigTriangleRatio)

ratioX = sin(bigTriangleAngle)
changeX = ratioX * speed
ratioY = cos(bigTriangleAngle)
changeY = ratioY * speed

movingX += copysign(changeX, bigTriangleWidth * -1)
movingY += copysign(changeY, bigTriangleHeight * -1)


# Used to calculate the absolute distance between two objects to be compared to the closeEnough variable
def absDistance(object1X, object1Y, object2X, object2Y):
diffX = object2X - object1X
diffY = object2Y - object1Y
d = sqrt(diffX ** 2 + diffY ** 2)
return abs(d)

#------------------------------------------------------------------------#
#------------------------------------------------------------------------#

robberX = -10.0
robberY = 100.0
robberSpeed = 11

guardX = -5.0
guardY = 140.0
guardSpeed = 13

normalizeSpeed(robberSpeed, guardSpeed, 0.1)

doorX = 0.0
doorY = 0.0

closeEnough = 0.2

while ((absDistance(robberX, robberY, guardX, guardY) > closeEnough) and (absDistance(robberX, robberY, doorX, doorY) > closeEnough)):
computeChanges(robberX, robberY, robberSpeed, doorX, doorY)
print("Robber position: ({0}, {1})".format(robberX, robberY))
computeChanges(guardX, guardY, guardSpeed, robberX, robberY)
print("Guard position: ({0}, {1})".format(guardX, guardY))

if (absDistance(robberX, robberY, doorX, doorY) <= closeEnough):
print("The robber escapes!\nguardX = {0}\nguardY = {1}".format(guardX, guardY))
elif (absDistance(robberX, robberY, guardX, guardY) <= closeEnough):
print("The guard catches the robber!\nrobberX = {0}\nrobberY = {1}\nguardX = {2}\nguardY = {3}".format(robberX, robberY, guardX, guardY))

Answer Source

Your issue lays in the way python handles variable scope. Yes, on the last lines of computeChanges your are changing movingX and movingY. However, you are only changing those variables in the scope of that function body for that one call. Once the function finishes, those local variables are thrown away.

You should return those two variables out and update the robber and guards positions in the while loop.

def computeChanges(movingX, movingY, speed, targetX, targetY):
    ...
    return movingX, movingY

...

while ((absDistance(robberX, robberY, guardX, guardY) > closeEnough) and (absDistance(robberX, robberY, doorX, doorY) > closeEnough)):
    robberX, robberY = computeChanges(robberX, robberY, robberSpeed, doorX, doorY)
    print("Robber position: ({0}, {1})".format(robberX, robberY))
    gaurdX, gaurdY = computeChanges(guardX, guardY, guardSpeed, robberX, robberY)
    print("Guard position: ({0}, {1})".format(guardX, guardY))