Why my enemy doesn't move when moving it? (Ursina) - python

I have this code. [enemy.py].
# Enemy behaviour.
# Entities.
from ursina import Entity
# Colors.
from ursina.color import red
# 3D Vectors.
from ursina import Vec3
# Capsule model.
from ursina import Capsule
# Random.
from random import randint, choice
# Sequences and tools for it.
from ursina.sequence import Sequence, Wait, Func
# Some enemy constants.
ENEMY_MODEL = Capsule() # NOTE (TODO): Maybe later can be replaced on new enemy 3D model.
ENEMY_SCALE = (2, 2, 2)
ENEMY_COLLIDER = 'mesh'
ENEMY_COLLISION = True
ENEMY_COLOR = red
ENEMY_SPAWN_POS = (16.328, 1.500, 16.773) # XXX: Generated by console.
# Enemy class.
class Enemy(Entity):
def __init__(self) -> None:
"""Enemy class."""
super().__init__(
model=ENEMY_MODEL,
scale=Vec3(ENEMY_SCALE),
collider=ENEMY_COLLIDER,
collision=ENEMY_COLLISION,
color=ENEMY_COLOR,
position=ENEMY_SPAWN_POS
)
self.ai_enabled = False
self.friendly = False
self.move_every_secs = 5
self.sequences = [
Sequence(
Func(self.simulate_moving),
Wait(self.move_every_secs),
loop=True
)
]
self.sequences_started = False
# Enemy update function.
def update(self):
if self.ai_enabled:
if not self.sequences_started:
for sequence in self.sequences:
sequence.start()
self.sequences_started = True
elif not self.ai_enabled:
if self.sequences_started:
for sequence in self.sequences:
sequence.pause()
self.sequences_started = False
def simulate_moving(self):
"""Simulate enemy moving."""
move_by = ['x', 'z']
move_by_random = choice(move_by)
move_on = randint(5, 10)
if move_by_random == 'x':
for _ in range(int(self.position.x + move_on)):
self.position.x += 1
elif move_by_random == 'z':
for _ in range(int(self.position.z + move_on)):
self.position.z += 1
self.ai_log('Moved.')
def enable_ai(self) -> None:
"""Enable enemy AI."""
self.ai_enabled = True
def disable_ai(self) -> None:
"""Disable enemy AI."""
self.ai_enabled = False
def set_friendly(self) -> None:
"""Make enemy friendly."""
self.friendly = True
def set_not_friendly(self) -> None:
"""Make enemy not friendly."""
self.friendly = False
def update_moving_per_secs(self, new_val: int) -> None:
"""Update moving activity per seconds."""
self.move_every_secs = new_val
def ai_log(self, message) -> None:
"""Create AI log into console."""
print(f'AI (Core) : {message}')
[game.py] (Not full code, but anyway that's what we need to know).
from enemy import Enemy
enemy = Enemy()
enemy.enable_ai()
And every 5 seconds it must move, but it's doesn't move at all.
Note, that function get called.
What to do?
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

Oh, i solved it.
We need to use self.x, not self.position.x.

Related

Python automatically changing all dictionary values

I've been working on a text based adventure game, in the process of doing the skeleton for the game building system. I got the movement working by typing NESW originally but after removing the debugging code, its been broken for over a day. Thought I would reach out for help...
Here's the main issue:
A grid is automatically generated with coordinate objects containing a dictionary value of places it "canGo" corresponding for a single letter key and a bool, defaulted to False. After initializing the grid, I pass a list of coordinates I want to activate to the grid that executes the following function: (1)it activates all the grids in the list passed; (2)it runs a function that generates a list of active squares; (3)it passes that list to a function that checks one square away from each of the active coords and sees if it is active, if so then it marks that direction bool as True (example canGo["N"] = True.
Issue: (Debug below) the correctly sets the attributes when initializing, after completion the keys come back WRONG but were seemingly not set again to something else in my code. Further, it sets all of keys to the same thing (in this case all of the keys in all coords are ["S"] = True)
-SD--------
SETTING DIRECTIONG debug
(1, 1) >> N
-SD--------
(1, 1) directions = N
(1, 1){'N': True, 'S': False, 'E': False, 'W': False}
-------------------
-SD--------
SETTING DIRECTIONG debug
(1, 2) >> S
-SD--------
(1, 2) directions = S
(1, 2){'N': False, 'S': True, 'E': False, 'W': False}
-------------------
(1,1): {'N': False, 'S': True, 'E': False, 'W': False}
Which direction would you like to move? <NESW>:
Debug so far: I have debug code inside that shows me it correctly recognizes the activated grids, correctly passes them to the list, and that the list correctly sets the ["canGo"] coordinate attribute. No other code is executed after initializing and processing the activated coords and before it asks you what direction you would like to go.
Code below...
Main
from coordinates import Coordinates as Coords
from grid import Grid
from player import Player
def main():
gridSizeX = 5
gridSizeY = 5
game = Grid(gridSizeX,gridSizeY, Player("John Doe", 1, 1))
#game.setActiveGridSquares([(1,1),(1,2),(1,3)])
game.grid[1][1].active = True
game.grid[1][2].active = True
game.grid[1][1].setDirections("N")
game.grid[1][2].setDirections("S")
while(True):
x,y = game.player.getLocation()
print("({x},{y}): {canGo}".format(x=x,y=y,canGo=game.grid[x][y].canGo))
move = input("Which direction would you like to move? <NESW>: ")
if(move.upper() == "EXIT"):
break
game.movePlayer(move.upper())
if __name__ == "__main__":
main()
Grid
In here, I am passing an immutable list of tuples (x,y) that then iterates through, and breaks apart. Main processing of the directions in the error occurs under Grid class in directionsProcessing()
from coordinates import Coordinates as Coords
from player import Player
class Grid:
"""Builds Grid and takes Player Object to move along grid"""
playerLocation = None
def __init__(self, gridSizeX, gridSizeY, player):
self.grid = self.buildGrid(gridSizeX,gridSizeY)
self.player = player
def buildGrid(self, gridSizeX, gridSizeY):
"""Builds and returns a grid object as a dictionary of [x][y]
Starts at 1 and ends at gridSize(X/Y)
gridSize(X/Y) will be the (x/y) max. -> 5 would be 1 to 5
"""
Grid = {}
for x in range(1, gridSizeX+1):
Grid[x] = {}
for y in range(1, gridSizeY+1):
Grid[x][y] = Coords(x, y)
return Grid
def copyGrid(self):
"""Returns a copy of grid dictionary"""
return self.grid
def setPlayer(self, playerToSet):
"""Sets player object into grid class to allow for player tracking"""
self.player = playerToSet
def setActiveGridSquares(self, squares):
"""Sets a list of grid squares to active"""
for t in squares:
x,y = t
self.grid[x][y].isActive = True
self.solveGridDirections(self.getAllActiveSquares())
def getAllActiveSquares(self):
"""Returns list of all active grid squares"""
activeGridSquares = []
for x in self.grid:
for y in self.grid[x]:
if(self.grid[x][y].isActive):
activeGridSquares.append((self.grid[x][y].x,self.grid[x][y].y))
return activeGridSquares
def solveGridDirections(self, activeSquares):
"""Resolves all active grid squares direction components to
allow movement into nearby active squares"""
for t in activeSquares:
adjoiningDirections = []
x,y = t
#print("Evaluating ActiveSquare: ("+str(x)+","+str(y)+")")
if((x,y+1) in activeSquares):
adjoiningDirections.append("N")
if((x,y-1) in activeSquares):
adjoiningDirections.append("S")
if((x+1,y) in activeSquares):
adjoiningDirections.append("E")
if((x-1,y) in activeSquares):
adjoiningDirections.append("W")
self.grid[x][y].setDirections("".join(adjoiningDirections)) #Sets allowed move directions inside grid
def movePlayer(self, direction):
"""Moves player in direction, preforms coordinate check if player can move"""
if(len(direction) > 1):
print("Lenght must be 1 character ONLY <NESW>")
return
x,y = self.player.getLocation()
print("-MP-------------") #####
print("({x},{y})Can I move in {direction} direction? {tf}".format(x=str(x),y=str(y),direction=direction,tf=str(self.grid[x][y].canGo[direction])))
print("-MP-------------") #####
if(self.grid[x][y].canGo[direction]):
self.player.movePlayer(direction)
else:
print("Player cannot move in that direciton on this grid square.")
Coordinates
class Coordinates:
"""Set coordinates of path squards in the world"""
actionOnEnter = None
choices = {"a":None,"b":None,"c":None}
canGo = {"N": False,"S": False,"E": False,"W": False}
isActive = False
def __init__(self, x, y):
self.x = x #set x coords
self.y = y #set y coords
def directionsProcessing(self, directions):
"""Directions are processed into a specific order and canGo is amended"""
listOfDirections = ["N", "S", "E", "W"]
verifiedDirections = []
coordsDir = str(self.getCoords())
print(coordsDir+" directions = "+directions) #####
for m in listOfDirections:
if(directions.find(m) != -1):
self.canGo[m] = True
verifiedDirections.append(m)
else:
self.canGo[m] = False
print(coordsDir+str(self.canGo)) #####
print("-------------------") #####
def setDirections(self, direcitons):
"""Sets directions a player can move, updates from initialization"""
print("-SD--------")#####
coordsDir = str(self.getCoords())#####
print("SETTING DIRECTIONG debug")#####
print(coordsDir+" >> "+direcitons)#####
print("-SD--------")#####
self.directionsProcessing(direcitons)
def getCoords(self):
"""Return x,y coordinate duple"""
return self.x,self.y
Player (less important but still plays a roll in motion)
class Player:
"""Player class used to hold player data.
X and Y coords are player's starting coordinates
Control inventory, keys, etc.
"""
inventory = {"sword": False}
keys = {"rectangle": False, "half moon": False}
def __init__(self, name, x, y):
self.name = name
self.x = x
self.y = y
def movePlayer(self, direction):
"""Moves player toards certain coordinates, <NESW>"""
if (len(direction) != 1):
raise Exception("Only 1 letter may be used.")
updown = {"N": 1, "S": -1, "W": -1, "E": 1}
validDirections = ["N","S","E","W"]
if(direction.upper() in validDirections):
if (direction in ["N","S"]):
self.y += updown[direction]
if (direction in ["W","E"]):
self.x += updown[direction]
else:
Exception("Direction is invalid")
def getLocation(self):
"""Returns tuple of player location x,y"""
return self.x,self.y
def setLocation(self, locationTuple):
"""Sets location based on input tuple
Syntax -> Player.setLocation((x,y))
"""
x,y = locationTuple
self.x = x
self.y = y
def toString(self):
"""Converts player data into string"""
return "Player: {name} Location: {x},{y}".format(name=self.name, x=self.x, y=self.y)
Thanks to #barny for your help.
This can be solved in two ways after reading your comments
(1) [better] move canGo to the init() method
(2) create an empty instance of "canGoTemp" inside the directionsProcession() method and pass the values to that, then pass the dict to the canGo attribute (this is without moving canGo to init())
both of these worked but I landed on (1)...
Thanks again man, I know it was a mess

Writing a test in python

Im currently taking a python class and im new in programming. I have written the code below and want to write a code that tests if the ResilientPlayer actually does what it is supposed to. The code is from a chutes and ladders board game where the ResilientPlayer is a "special" type of player that gets a "superpower" in its next move afther falling down a chute. The next round afther he has fallen down a chute, he will add a given or a default number to the die_roll, and I want to test if my code actually does this! Hope someone can help me with this problem :)
class Player:
def __init__(self, board):
self.board = board
self.position = 0
self.n_steps = 0
def move(self):
die_roll = random.randint(1, 6)
self.position = self.get_position() + die_roll
self.board.position_adjustment(self.position)
self.n_steps += 1
def get_position(self):
return self.position
def get_steps(self):
return self.n_steps
class ResilientPlayer(Player):
default_extra_steps = 1
def __init__(self, board, extra_steps=None):
super().__init__(board)
self.extra_steps = extra_steps
if self.extra_steps is None:
self.extra_steps = self.default_extra_steps
def move(self):
if self.get_position() in self.board.chutes.values():
die_roll = random.randint(1, 6)
self.position = self.get_position() + die_roll + self.extra_steps
self.board.position_adjustment(self.position)
self.n_steps += 1
else:
super().move()
def get_position(self):
return self.position
def get_steps(self):
return self.n_steps
The best way to do this is using the unittest class, I do this as following:
import unittest
from .... import ResilientPlayer
class TestResilientPlayer(unittest.TestCase):
def setUp(self):
self.resilient_player = ResilientPlayer(....)
def test_move(self):
# Do stuff
self.assertEqual(1, 1)
if __name__ == '__main__':
unittest.main()
Here, unittest.main() will run all the tests in the file. setUp is run before each test (so you can have multiple tests with the same starting conditions).
This is an incredible useful module and I strongly suggest reading more on it, check the documentation

How to design a multithreaded elevator system and handle concurrency?

I want to write a multithreaded program for an elevator system.
The elevator system can only move if the state is running or wait state.
In the system, the instruction (which floor to go to) can be added in a multithreaded way. For managing the queue of instruction and getting the next stop for the lift, I have written a QueueManager class.
I am not able to figure out how to implement the QueueManager. The problem is I can't get my head around writing the QueueManager. Especially in figuring out how to get the next stop for the Lift from the queue.
Here's my implementation for the system in python3:
"""Implementation of a lift System"""
from enum import Enum
from typing import TypeVar
from threading import Thread
import queue
LiftType = TypeVar('LiftType', bound='Lift')
QueueManagerType = TypeVar('QueueManagerType', bound='QueueManager')
SensorNameType = TypeVar('SensorNameType', bound='SensorName')
DirectionType = TypeVar('DirectionType', bound='DirectionType')
class SensorName(Enum):
weight = 'weight'
smoke = 'smoke'
class Direction(Enum):
up = 1
down = -1
class State(Enum):
running = 'running'
wait = 'waiting'
stop = 'stop'
class Lift:
def __init__(self, num_floors: int, queue_manager: QueueManagerType):
"""
Contains all the properties of lift
"""
self.num_floors = num_floors
self.curr_direction = Direction.up
self.state = State.running
self.curr_floor = 0
self.queue_manager = queue_manager
def move(self):
"""
Moves the lift according to the instruction
"""
if self.state in [State.running, State.wait]:
if self.queue_manager.has_instruction():
self.state = State.running
stop = self.queue_manager.next_stop(self.curr_direction, self.curr_floor)
if stop:
print(stop)
else:
if self.curr_direction == Direction.up:
self.curr_direction = Direction.down
stop = self.queue_manager.next_stop(self.curr_direction,
self.curr_floor)
print(stop)
else:
self.curr_direction = Direction.up
else:
self.state = State.wait
def add_instruction(self, floor, direction=None):
"""Adds the instruction to the queue"""
if direction is None:
if self.curr_floor > floor:
direction = Direction.down
else:
direction = Direction.up
Thread(target=self.queue_manager.add_instruction, args=(floor, direction)).start()
self.move()
class QueueManager:
def __init__(self):
self.instruction_queue = queue.Queue()
def add_instruction(self, floor: int, direction: DirectionType):
"""Add an instruction to the queue. Direction is used """
self.instruction_queue.put([floor, direction])
def next_stop(self, direction: int, curr_floor: int):
"""Tells which is the next stop based on the direction provided."""
pass
def has_instruction(self):
"""If there are any instructions for the lift"""
pass
if __name__ == '__main__':
# weight_sensor = WeightSensor(SensorName.weight)
instruction_queue = QueueManager()
lift_1 = Lift(21, instruction_queue)
lift_1.add_instruction(floor=0, direction=Direction.up)
lift_1.add_instruction(floor=2)
Extension to the above program is writing a Sensor class which runs in background and sets lift to stop state if certain sensor is triggered. Which is also something I am unable to figure out.
Based on the feedback I got in the comments. Here's a multithreaded solution for an elevator system.
"""Implementation of a lift System"""
from enum import Enum
from typing import TypeVar
from threading import Lock, Thread
from heapq import heappush, heappop
import time
import random
LiftType = TypeVar('LiftType', bound='Lift')
QueueManagerType = TypeVar('QueueManagerType', bound='QueueManager')
SensorNameType = TypeVar('SensorNameType', bound='SensorName')
DirectionType = TypeVar('DirectionType', bound='DirectionType')
class SensorName(Enum):
weight = 'weight'
smoke = 'smoke'
class Direction(Enum):
up = 1
down = -1
class State(Enum):
running = 'running'
wait = 'waiting'
stop = 'stop'
class Lift:
def __init__(self, num_floors: int):
"""
Contains all the properties of lift
:param sensors: A list of sensor objects
"""
self.num_floors = num_floors
self.curr_direction = Direction.up
self.state = State.running
self.curr_floor = 0
self.instruction_queue = {Direction.up: [], Direction.down: []}
self.queue_lock = Lock()
def move(self):
"""
Moves the lift according to the instruction
"""
if self.state in [State.running, State.wait]:
if len(self.instruction_queue[Direction.up]) or len(self.instruction_queue[Direction.down]):
self.state = State.running
try:
stop = heappop(self.instruction_queue[Direction.up])
except IndexError:
stop = -1
if stop > -1:
self.curr_floor = stop
print(stop, Direction.up)
else:
if self.curr_direction == Direction.up:
self.curr_direction = Direction.down
if len(self.instruction_queue[Direction.down]):
stop = heappop(self.instruction_queue[Direction.down])
self.curr_floor = stop
print(stop, Direction.down)
else:
self.state = State.wait
else:
self.curr_direction = Direction.up
self.move()
else:
self.state = State.wait
def add_instruction(self, floor, direction=None):
if direction == Direction.up:
time.sleep(random.uniform(0,1))
else:
time.sleep(random.uniform(0,4))
if direction is None:
if self.curr_floor > floor:
direction = Direction.down
else:
direction = Direction.up
with self.queue_lock:
heappush(self.instruction_queue[direction], floor)
self.move()
if __name__ == '__main__':
lift_1 = Lift(21)
lift_1.add_instruction(0, Direction.up)
Thread(target=lift_1.add_instruction, args=(2,)).start()
Thread(target=lift_1.add_instruction, args=(5,)).start()
Thread(target=lift_1.add_instruction, args=(2,)).start()
Thread(target=lift_1.add_instruction, args=(18,)).start()
Thread(target=lift_1.add_instruction, args=(12,)).start()
Thread(target=lift_1.add_instruction, args=(21,)).start()

Traveling Salesperson with Genetic Algorithm

I am trying to visualize and solve the traveling salesperson problem with python and genetic algorithms, i was following one of Daniel Shiffman's coding challenge videos on youtube i don't know if i'm allowed to put a link here but here is the link (https://www.youtube.com/watch?v=M3KTWnTrU_c&list=PLRqwX-V7Uu6ZiZxtDDRCi6uhfTH4FilpH&index=42)
So the problem is , my genetic algorithm does not evolve. It gets stuck on just on first generation.I think i couldn't write the code that creates next generation like it's supposed to be due to my lack of knowledge on python, here is the code :
import pygame
import random
import numpy as np
import sys
size=width,height=500,500
bgColor = (0,0,0)
screen = pygame.display.set_mode(size)
vertexArray = []
fitness = []
population = []
pygame.display.set_caption("Finding the Shortest path with Genetich Algorithm")
bestEver=[]
bestDistance = 999999
def shuffle(vertexArray):
np.random.shuffle(vertexArray)
def swap(a,i,j):
temp = a[i]
a[i]=a[j]
a[j]=temp
class Vertex:
def __init__(self,x,y):
self.color = (255,255,255)
self.x = x
self.y = y
def display(self):
pygame.draw.circle(screen,self.color,(self.x,self.y),4,4)
def getPosition(self):
return [self.x,self.y]
def __str__(self):
return str(self.x+", "+self.y)
def createVertexes(numOfVertexes):
for i in range(numOfVertexes):
vertexArray.append(Vertex(random.randint(0,width),random.randint(0,height)))
createVertexes(8)
def createPopulation():
for i in range(300):
population.append(vertexArray[:])
for j in range(100):
shuffle(population[i])
createPopulation()
def drawLines(vertexArray,color):
for i in range(vertexArray.__len__()-1):
pygame.draw.line(screen,color,vertexArray[i].getPosition(),vertexArray[i+1].getPosition(),1)
def calculateDistance(vertexArray):
dist = 0
for i in range(vertexArray.__len__()-1):
dist += np.linalg.norm(np.asarray(vertexArray[i+1].getPosition())-np.asarray(vertexArray[i].getPosition()))
return dist
def displayVertexes(vertexArray):
for i in range(vertexArray.__len__()):
vertexArray[i].display()
def calculateFitness():
global bestDistance
global bestEver
for i in range(population.__len__()-1):
d = calculateDistance(population[i])
if d<bestDistance:
bestDistance = d
bestEver = population[i][:]
fitness.append(1/d)
def getProbability(fitness,population):
first = 0
sum = 0
for i in range(fitness.__len__() - 1):
sum += fitness[i]
r = random.uniform(0, sum)
for i in range(fitness.__len__() - 1):
if r<=fitness[i] and r>=first:
return population[i]
first = fitness[i]
return population[random.randint(0,2)]
def pickOne(population,fitness):
return getProbability(fitness,population)
def mutate(order):
indexA = random.randint(0,order.__len__()-1)
indexB = random.randint(0,order.__len__()-1)
swap(order,indexA,indexB)
def nextGeneration():
global population
newPopulation=[]
for i in range(population.__len__()-1):
order = pickOne(population,fitness)
mutate(order)
newPopulation.append(order)
population = newPopulation
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill(bgColor)
displayVertexes(vertexArray)
calculateFitness()
print(fitness[2])
nextGeneration()
drawLines(bestEver,(255, 0, 0))
pygame.display.flip()

Python Unbound Method Error

Can someone please correct me on the mistake I have been having trouble with! The problem is that it is not generating a random integer in the Goalie nor Player class. This issue isn't allowing me to actually get both "players" to move.
Error:
import random
def main():
name = raw_input("Name: ")
kick = raw_input("\nWelcome " +name+ " to soccer shootout! Pick a corner to fire at! Type: TR, BR, TL, or BL! T = TOP B = BOTTOM L = LEFT R = RIGHT: ")
if Player.Shot == Goalie.Block:
print("\nThe goalie dives and blocks the shot!")
if Player.Shot != Goalie.Block:
print("\nThe ball spirals into the net!")
print(Player.Shot)
print(Goalie.Block)
class Player():
def __init__(self):
self.Shot()
def Shot(self):
shot = random.randint(0,3)
self.Shot = shot
class Goalie():
def __init__(self):
self.Block()
def Block(self):
block = random.randint(0,3)
self.Block = block
main()
you need to instantiate the class first::
try:
import random
def main():
name = raw_input("Name: ")
kick = raw_input("\nWelcome " +name+ " to soccer shootout! Pick a corner to fire at! Type: TR, BR, TL, or BL! T = TOP B = BOTTOM L = LEFT R = RIGHT: ")
player=Player() #error fixed:<-- called the class
goalie=Goalie() #error fixed:<-- called the class
if player.shot == goalie.block:#error fixed:<-- used that initiated class
print("\nThe goalie dives and blocks the shot!")
if player.shot != goalie.block:
print("\nThe ball spirals into the net!")
print(player.shot)
print(goalie.block)
class Player:
def __init__(self):
self.Shot()
def Shot(self):
shot = random.randint(0,3)
self.shot = shot #error fixed:<-- attribute and method are same
class Goalie:
def __init__(self):
self.Block()
def Block(self):
block = random.randint(0,3)
self.block = block #error fixed:<-- attribute and method are same
main()

Categories