Calling a class function outside of the function it was declared - python

I'm trying to call a class function player.Decide() in another function where it wasn't declared. Im getting the error 'player is not defined. How would I go about fixing this?
def BattleLogic():
global enemy, enemy_race, name, level, strength, dexterity, cunning, enemy_speed, player_speed, type_speed
global move, turn, prefix
if enemy in ['deer']:
enemy_race = 'animal'
if enemy_race == 'animal':
chance = random.randint(1,1000)
if chance <= 10:
prefix = 'crippled'
elif chance > 10 and chance <= 50:
prefix = 'old'
elif chance >50 and chance <= 250:
prefix = 'young'
elif chance > 250 and chance <= 750:
prefix = None
elif chance > 750 and chance <= 950:
prefix = 'strong'
elif chance > 950 and chance <= 990:
prefix = 'alpha'
elif chance > 990 and chance <= 999:
prefix = 'possessed'
elif chance == 1000:
prefix = '*CONVERTED*'
else:
prefix = 'error'
opponent = Enemy(str(prefix),str(enemy),str(enemy_race))
player = Player(str(name),level,strength,dexterity,cunning)
player.Initiative()
opponent.Initiative()
if enemy_speed > player_speed:
move = 0
elif player_speed > enemy_speed:
move = 1
else:
move = random.randint(0,1)
turn = 0
Battle()
def Battle():
global turn, move, prefix, enemy, type_speed, enemy_title
if turn == 0:
print('\n\n')
if prefix == None:
enemy_title = enemy.capitalize()
else:
enemy_title = prefix.capitalize()+' '+enemy.capitalize()
SlowPrint('A '+enemy_title+' gets into position for battle',type_speed,0.5)
if move == 1:
SlowPrint(enemy_title+' makes the first move',type_speed,0.25)
else:
SlowPrint('You make the first move',type_speed,0.25)
if move == 0:
turn += 1
move = 1
player.Decide()
else:
turn += 1
move = 0
opponent.Decide()

Just pass a player object into the function. The you are free to use player.Decide().
The major problems with your coding, which is my personal opinion, is that you do not have the habit of passing something into the function, which as a result forces you to declare too many global variables.
A simple example (in your case, you want the object to be a player)
def Battle(obj):
return obj.Decide()

Related

Implementing an aima-python agent

I am using aima-python to implement a covid cleaning agent, this agent will go to each square and spray. If there is a an object present in the cell it will still spray such as table, chair etc. However, if there is a person in the next cell the robot cannot cross paths with the cell and must avoid entering a cell with a human. I have implemented most of the code and I think the code does as described above, I am however getting a 'TypeError: 'chair' object is not callable'. I can't see why I would be getting this, this is the same for all object present in my environment. I would really appreciate some assistance with this issue.(This program runs on jupyter notebook)
from agents import *
from random import choice
class DisinfectingRobot(Agent):
location = [0,1]
direction = Direction("down")
def moveforward(self, success=True):
'''moveforward possible only if success (i.e. valid destination location)'''
if not success:
return
if self.direction.direction == Direction.R:
self.location[0] += 1
elif self.direction.direction == Direction.L:
self.location[0] -= 1
elif self.direction.direction == Direction.D:
self.location[1] += 1
elif self.direction.direction == Direction.U:
self.location[1] -= 1
def turn(self, d):
if isinstance(thing,person):
self.direction = self.direction + d
return True
return False
def spray(self, thing):
'''returns True upon success or False otherwise'''
if isinstance(thing, Food):
return True
return False
def program(percepts):
'''Returns an action based on it's percepts'''
for p in percepts:
if isinstance(p, chair):
return 'spray'
elif isinstance(p, table):
return 'spray'
elif isinstance(p,person):
turn = False
choice = random.choice((1,2))
else:
choice = random.choice((1,2,3,4))
if isinstance(p,Bump): # then check if you are at an edge and have to turn
turn = False
choice = random.choice((1,2));
else:
choice = random.choice((1,2,3,4)) # 1-right, 2-left, others-forward
if choice == 1:
return 'turnright'
elif choice == 2:
return 'turnleft'
else:
return 'moveforward'
class chair(Thing):
pass
class table(Thing):
pass
class person(Thing):
pass
class lab2D(GraphicEnvironment):
def percept(self, agent):
'''return a list of things that are in our agent's location'''
things = self.list_things_at(agent.location)
loc = copy.deepcopy(agent.location) # find out the target location
#Check if agent is about to bump into a wall
if agent.direction.direction == Direction.R:
loc[0] += 1
elif agent.direction.direction == Direction.L:
loc[0] -= 1
elif agent.direction.direction == Direction.D:
loc[1] += 1
elif agent.direction.direction == Direction.U:
loc[1] -= 1
if not self.is_inbounds(loc):
things.append(Bump())
return things
def execute_action(self, agent, action):
'''changes the state of the environment based on what the agent does.'''
if action == 'turnright':
print('{} decided to {} at location: {}'.format(str(agent)[1:-1], action, agent.location))
agent.turn(Direction.R)
elif action == 'turnleft':
print('{} decided to {} at location: {}'.format(str(agent)[1:-1], action, agent.location))
agent.turn(Direction.L)
elif action == 'moveforward':
print('{} decided to move {}wards at location: {}'.format(str(agent)[1:-1], agent.direction.direction, agent.location))
agent.moveforward()
elif action == "spray":
items = self.list_things_at(agent.location, tclass=chair)
if len(items) != 0:
if agent.spray(items[0]):
print('{} sprayed {} at location: {}'
.format(str(agent)[1:-1], str(items[0])[1:-1], agent.location))
elif action == "turn":
items = self.list_things_at(agent.location, tclass=person)
if len(items) != 0:
if agent.turn(items[0]):
print('{} turned because {} at location: {}'
.format(str(agent)[1:-1], str(items[0])[1:-1], agent.location))
lab = lab2D(5,5, color={'DisinfectingRobot': (128,128,128), 'chair': (153, 76, 0),
'table': (230, 115, 40), 'person': (51,25,0)})
robot = DisinfectingRobot(program)
lab.add_thing(robot, [0,0])
chair = chair()
table = table()
person = person()
lab.add_thing(robot, [0,0])
lab.add_thing(table, [1,2])
lab.add_thing(chair, [0,1])
lab.add_thing(person,[5,1])
moretable = table()
morechair = chair()
moreperson = person
lab.add_thing(moretable, [2,4])
lab.add_thing(morechair, [4,3])
lab.add_thing(moreperson,[3,3])
print("robot started at [0,0], facing down. Time to disinfect!")
lab.run(100)

Why does this run-time error keep poping up?

So here's my code, and "name 'player' is not defined" pops up when playing the game. This is only a practice project so the entire code is attached. I've been trying to finish the code posted in 100 Days of Complete Python Pro Boot Camp, and got stuck on day 11. Someone plz help me XD.
......
def main():
player = [random.choice(cards), random.choice(cards)]
comp = [random.choice(cards), random.choice(cards)]
player_total = player[0] + player[1]
comp_total = comp[0] + comp[1]
ace_count = 0
ace_position = []
comp_ace = 0
comp_ace_position = []
no = False
print_deck(player, comp, player_total)
if player_total == 21:
print_final(player, comp, player_total, comp_total)
print("Win with a Blackjack 😎")
return
elif comp_total == 21:
print_final(player, comp, player_total, comp_total)
print("Lose, opponent has Blackjack 😱")
return
def deal():
global player, player_total, comp, comp_total, ace_count, ace_position, comp_ace, comp_ace_position, no
deal = input("Type 'y' to get another card, type 'n' to pass: ")
if deal == 'y':
new_card = random.choice(cards)
player.append(new_card)
player_total += new_card
if new_card == 11:
ace_count += 1
ace_position.append(len(player - 1))
while player_total > 21:
if ace_count > 0:
player_total -= 10
player[ace_position[0]] -= 10
ace_position.remove(ace_position[0])
else:
print_deck(player, comp, player_total)
comp_move()
print("You went over. You lose 😭")
break
print_deck(player, comp, player_total)
else:
comp_move()
if player_total == comp_total:
print("Draw πŸ™ƒ")
elif player_total > comp_total:
print("You win πŸ˜ƒ")
else:
print("You lose 😀")
no = True
......
This is to do with the scope of where player exist. Notice the nested function definition. - When you nest a function inside another all the local variable of the parent function are global of the child.
What you have done here is declared a global variable within deal() which is not needed, this raises the error as python is expecting a value to be assigned to that new global variable.
To fix: simply remove the variable that declares them all as globals.
p.s. I feel this may not be the best explanation feel free to ask questons.

Simulation task, I'm stuck with producing correct output

I have been tasked with producing a simple program that simulates the actions of a vehicle from a list of command stored & accessed within a text file.
The expected output would look something like this;
Loading simulation...
Accelerating...
Speed = 5, Gear = 1, Direction = 0
Accelerating...
Speed = 10, Gear = 1, Direction = 0
Accelerating...
Changing up...
Current gear = 2
Speed = 15, Gear = 2, Direction = 0
Accelerating...
Speed = 20, Gear = 2, Direction = 0
Accelerating...
Yet my output looks like this;
Loading Simulation....
Car Gear is First (1)
Accelerating...
Car Gear is First (1)
Speed = 5, Gear = 1, Direction = [-1, 0, 1]
Braking...
Car Gear is First (1)
Speed = 0, Gear = 1, Direction = [-1, 0, 1]
Car Gear is First (1)
Accelerating...
Car Gear is First (1)
Speed = 5, Gear = 1, Direction = [-1, 0, 1]
Braking...
Car Gear is First (1)
Speed = 0, Gear = 1, Direction = [-1, 0, 1]
Car Gear is First (1)
When I run my code in Idle, i get no errors of any kind, when i use Thonny, it gives me the folloing error when it analyses the code:
Line 113 : Either all return statements in a function should return an expression, or none of them should.
Line 113 : Unused argument 'selected_gear'
Below is a copy of my code also:
RIGHT = 1
LEFT = -1
FORWARD = 1
REVERSE = 0
STRAIGHT = 0
#gears and allowable speeds are as follows:
#zero (reverse) (speed -1 to -10). Max reverse speed of car is -10
#one (speed 0 to 10)
#two (speed 10 to 20)
#three (speed 20 to 30)
#four (speed 30 to 45)
#five (speed 45 to 80). Max speed of car is 80
#gears change automatically, one gear at a time
#direction values are similar to numbers on clock face
#0 = 12 = straight on. All other directions = 1-11
class Car:
def __init__(self):
self.speed = 0
self.gear = [0,1,2,3,4,5]
self.direction = [-1,0,1]
self.broken = False #indicates whether car is broken
self.simulation = []
self.simulation_loaded = False
def accelerate(self):
if self.broken:
print("Car is broken!")
return
print("Accelerating...")
if self.gear == REVERSE:
self.speed -= 5
else:
self.speed += 5
if self.speed > 80:
self.speed = 80
if self.speed < -10:
self.speed = -10
self.change_gear(self.gear)
self.display_stats()
def brake(self):
if self.broken:
print("Car is broken...")
return
print("Braking...")
if self.speed < 0:
self.speed += 5
if self.speed > 0:
self.speed = 0
elif self.speed > 0:
self.speed -= 5
if self.speed < 0:
self.speed = 0
self.change_gear(self.gear)
self.display_stats()
def turn_steering_wheel(self, direction_change):
if self.broken:
print("Car is broken...")
return
if self.gear == REVERSE:
print ("Car is in reverse...")
if direction_change == RIGHT:
self.direction = -1
print("Reversing Right")
elif direction_change == REVERSE:
self.direction = 12
print("Reversing")
elif direction_change == LEFT:
self.direction = 1
print("Reversing Left")
elif self.gear == FORWARD:
if direction_change == LEFT:
self.direction = -1
print("Turning Left")
elif direction_change == STRAIGHT:
self.direction = 0
print("Moving Forward")
elif direction_change == RIGHT:
self.direction = 1
print("Turning Right")
self.display_stats()
def change_gear(self, selected_gear = FORWARD):
if self.broken:
print("Car is broken...")
return self.broken
# if self.gear == 0 and self.speed >= 0:
# print("you are going forward while in reverse gear...")
# return self.broken
# elif self.gear >= 1 and self.speed <= -1:
# print("you are going reverse while in foward gear...")
# return self.broken
if self.speed <= -1:
self.gear = 0
print("Car Gear is Neutral (0)")
return self.gear
elif self.speed <= 10:
self.gear = 1
print("Car Gear is First (1)")
return
elif self.speed <= 20:
self.gear = 2
print("Car Gear is Second (2)")
return
elif self.speed <= 30:
self.gear = 3
print("Car Gear is Third (3)")
return
elif self.speed <= 40:
self.gear = 4
print("Car Gear is Fourth (4)")
return
elif self.speed <= 50:
self.gear = 5
print("Car Gear is Fifth (5)")
return
self.display_stats()
self.change_gear(self.gear)
#check to see if car is going forward when reverse is selected and vice versa
#work out what gear you need to be in based on car’s speed
#Loop one gear at a time, either changing up or down, to get to required gear
print("Changing up...")
def display_stats(self):
print(f"Speed = {self.speed}, Gear = {self.gear}, Direction = {self.direction}")
def load_simulation(self, filename):
file = open(filename)
line = file.readline()
while line !='':
self.simulation.append(line.strip())
line = file.readline()
file.close()
self.simulation_loaded = True
return self.simulation
def run_simulation(self):
if self.simulation_loaded == False:
print("Error - Simulation.txt file is present")
else:
print("Loading Simulation....")
for action in self.simulation:
if action == "FORWARD":
self.change_gear (FORWARD)
elif action == "ACCELERATE":
self.accelerate()
elif action == "LEFT":
#self.direction(LEFT)
print("TURNING LEFT")
elif action == "RIGHT":
#self.direction(RIGHT)
print("TURNING RIGHT")
'''***WHEN USING SELF.DIRECTION(LEFT)/(RIGHT) the following error is given:
Traceback (most recent call last):
File "C:\Users\lenovo\Desktop\Bsc Computer Forensics - Laptop\Software-Dev\car-temp-2.py", line 207, in <module>
my_car.run_simulation()
File "C:\Users\lenovo\Desktop\Bsc Computer Forensics - Laptop\Software-Dev\car-temp-2.py", line 183, in run_simulation
self.direction(LEFT)
TypeError: 'list' object is not callable*** '''
elif action == "BRAKE":
self.brake()
else:
self.change_gear (REVERSE)
if __name__ == '__main__':
my_car = Car()
my_car.load_simulation("simulation.txt")
my_car.run_simulation()
Would I please be able to ask if anyone could explain what the errors im getting mean and where in my code I need to be looking, its got me feeling a little lost now - I've tried to research them, fix them but anyhting I try either seems to have no impact or gives errors that otherwise don't exist.
The errors occur in your change_gear() function, although they are more like warnings and should not pose serious problems:
Line 113 : Either all return statements in a function should return an expression, or none of them should.
The first two return statements return a value while the others don't. This is inconsistent and makes the code harder to understand. Since you don't actually use the returned values anywhere, you can remove them (i.e. use plain return).
Line 113 : Unused argument 'selected_gear'
You don't use the selected_gear argument anywhere inside change_gear(). You can remove it to get rid of the warning/error.

Issue with variable defining

When I execute the following code, I get the error "player_normal_defense is not defined". I get what the issue is but if I had to define the variable inside the Defense function, it would be totally pointless since the variable stores the initial defense value for further usage. How should I solve this?
import random
import sys
import os
import time
from Entity import *
class Battle():
def Attack(self, attacker, defender):
damage = attacker.atk - defender.dif
defender.hp -= damage
def Defense(self, owner, defending, entity_id):
defense_boost = 10
if defending:
owner.dif += defense_boost
elif not defending:
if entity_id == 1:
owner.dif = player_normal_defense
elif entity_id == 2:
owner.dif = enemy_normal_defense
def Turn_Generator(self, pl, en):
turns_list = []
speed_product = pl.speed / en.speed
first_speed_product = speed_product
if speed_product >= 1:
turns_list.append("P")
elif speed_product < 1:
turns_list.append("E")
while len(turns_list) < 100:
if speed_product >= 2:
turns_list.append("P")
turns_list.append("P")
speed_product = 0.6
elif speed_product < 2 and speed_product >= 1:
turns_list.append("P")
if first_speed_product <= 0.5:
speed_product = first_speed_product
else:
speed_product = 0.6
elif speed_product <= 0.5:
turns_list.append("E")
turns_list.append("E")
speed_product = 1
elif speed_product > 0.5 and speed_product < 1:
turns_list.append("E")
if first_speed_product >= 2:
speed_product = first_speed_product
else:
speed_product = 1
return turns_list
def Combat(self, player, enemy):
turn_counter = 1
player_normal_defense = player.dif
enemy_normal_defense = enemy.dif
fighting = True
while fighting:
print(f"Turn {turn_counter}")
turns = self.Turn_Generator(player, enemy)
for current_turn in turns:
print(f"""
======================
YOUR HPs: ENEMY HPs:
{player.hp} {enemy.hp}
======================""")
print(f"""
================
Current turn: {current_turn}
================
===========
Next turns:
{turns[1]}
{turns[2]}
{turns[3]}
{turns[4]}
===========
""")
if current_turn == "P":
choice = input("1. Attack\n2. Defend\n")
if choice == "1":
self.Attack(player, enemy)
self.Defense(player, False, 1)
elif choice == "2":
self.Defense(player, True, 1)
else:
print("Lost your chance!")
elif current_turn == "E":
enemy_choice = random.randint(1, 2)
if enemy_choice == 2:
print("He attacks you!")
self.Attack(enemy, player)
self.Defense(enemy, False, 2)
else:
print("He defends himself.")
self.Defense(enemy, True, 2)
time.sleep(3)
os.system("clear")
turns.pop(0)
if player.hp <= 0:
print("You died!")
sys.exit(0)
elif enemy.hp <= 0:
print("YOU WON!")
fighting = False
break
turn_counter += 1
When entity is defending, instead of running a Defence function to add a bonus to entitys Defence score only if it is true, I would just not run the Defence function when attacking. When entity is defending then you can run the Defense (Bonus) function as;
def Defending():
defence_boost = 10
in the decision check;
if choice == "2":
self.dif += Defending()
One issue I believe you will have with the code is that you are raising the entitys .dif stat with each occurrence of defending. This means that when this has cycled multiple times the base dif may be too high for any attackers damage to do anything to the opponents health.

Name 'x' is not defined / Global variable?

I'm learning to program with python and I came across this issue: I'm trying to make a Guessing Game, and while trying to check for the win condition, the function doesn't recognise the input variable, which I made sure I returned with a previous function. So i get the 'name << 'first_input' is not defined' >> error. I thought it had something to do with the variable not being global or sth like that.
import random
ran_int = random.randint(1,100)
guesses = 0
# here you input the number and it keeps asking unless you do so with 1 to 100
def ask():
first_input = 0
while first_input < 1 or first_input > 100:
first_input = int(input('Enter a number between 1 and 100: '))
return first_input
# this is just to increment the number of guesses stored for showing at the end # of the game
def guesses_inc():
global guesses
guesses += 1
return guesses
# here is where i get the error, as if my ask() function didn't return
# the value properly or as if I assigned it wrongly
def check_win_1():
if first_input == ran_int:
guesses_inc()
print(f'BINGO!\nYou guessed correctly after {guesses} times.')
elif (abs(ran_int - first_input) <= 10):
guesses_inc()
print('WARM!')
ask2()
elif first_input < 1 or first_input > 100:
print('Out of bounds!')
ask2()
else:
guesses_inc()
print('COLD!')
ask2()
ask()
check_win_1()
And here is the error
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-11-bfd5497995df> in <module>
----> 1 check_win_1()
NameError: name 'first_input' is not defined
I didn't paste the whole code because while testing it it returned the error at this stage so I didn't think the rest mattered for this particular problem. I tried making the var input global and stuff like that but i don't think I did it properly.
Your method call is not correct. You should call your functions like this
def check_win_1(first_input):
if first_input == ran_int:
guesses_inc()
print(f'BINGO!\nYou guessed correctly after {guesses} times.')
elif (abs(ran_int - first_input) <= 10):
guesses_inc()
print('WARM!')
ask2()
elif first_input < 1 or first_input > 100:
print('Out of bounds!')
ask2()
else:
guesses_inc()
print('COLD!')
ask2()
first_input = ask()
check_win_1(first_input)
The error is there because you are trying to use first_input somewhere (i.e. inside check_win_1()).
A possible, not recommended, solution is to qualify your variable as global, which should be used VERY sparingly.
Instead, it is recommended to use function parameters, so as to encapsulate your code in self-contained blocks, e.g.:
def func(a, b):
return a + b
x = func(10, 5)
rather than:
def func():
global a, b
return a + b
a = 10
b = 5
x = func()
For your that may mean doing something like:
def check_win_1(first_input, ran_int):
...
and use them accordingly, e.g.:
first_input = ask()
check_win_1(first_input, ran_int)
etc.
EDIT
Following the above principle, your code could have looked like:
import random
MIN_VAL = 1
MAX_VAL = 100
WARM_LIMIT = 10
def ask_number(
min_val=MIN_VAL,
max_val=MAX_VAL):
guess = None
while guess is None:
guess = int(input(f'Enter a number between {min_val} and {max_val}: '))
if guess < min_val or guess > max_val:
print('Out of bounds!')
guess = None
return guess
def check_guess(
guess,
target,
num_guesses,
warm_limit=WARM_LIMIT):
if guess == target:
print(f'BINGO!\nYou guessed correctly after {num_guesses} times.')
return True
else:
if (abs(guess - target) <= warm_limit):
print('WARM!')
else:
print('COLD!')
return False
# : main
target = random.randint(MIN_VAL, MAX_VAL)
num_guesses = 0
won = False
while not won:
guess = ask_number()
num_guesses += 1
won = check_guess(guess, target, num_guesses)

Categories