generate mouse velocity when only integer steps are allowed - python

I write a simple program in python which includes moving my mouse (I do his with PyUserInput).
However: It is only allowed to move the mouse in integer steps (say pixels).
So mouse.move(250.3,300.2) won't work.
I call the move function about 30 times in a second and move the mouse a few pixels. The speed with which I move the mouse varies from 0.5-2.5px/call. Rounding gives me 1-3 (move only want ints) which does not really represent the speed.
I search for a solution (maybe generator?) which takes my current speed (e.g. 0.7px) and gives me back a pattern (like a PWM Signal) out of 0 and 1 (e.g. 1,1,0,1,1,0...) which yields the 0.7px in average.
However this generator has to be adaptive because speed is constantly changing.
I am quite new to python and stuck with the last point: The variability of the generator function.
Here is what I have so far:
# for 0.75px/call
def getPWM(n):
nums = [1,0,1,1]
yield nums[n%4]

What you need to do is keep track of the previous position and the desired current position, and hand out the rounded coordinate. You could track the previous position in a function but it's much easier to do it in a class.
class pwm:
def __init__(self):
self.desired_position = 0.0
self.actual_position = 0
def nextPWM(self, speed):
self.desired_position += speed
movement = round(self.desired_position - self.actual_position)
self.actual_position += movement
return movement

Related

Problem With Collision Detection In Turtle [Python]

Im using an if statement to detect whether the player's coordinates after moving up (y coordinate increases) are equal to an open space's coordinates.
Ex:
player_coordinate = player.pos() # We can say that the coordinate returned is (-10.00,10.00)
space_coordinate = space.pos() # And the coordinate returned is (-10.00,20.00)
movement = 10 # How far the player can move at once
if (player_coordinate[0], player_coordinate[1] + movement) == space_coordinate:
player can move
Now, I used this same method, however when the player's position has a negative y value, the statement is false.
For example:
# Works:
if (-90.0, 30.0) == (-90.00,30.00)
# Doesn't Work
if (-90.0, -10.0) == (-90.00,-10.00)
(By the way the first tuple uses the vales stated previously, player_coordinate[0], player_coordinate[1] + movement, so i have no clue why it returns with one decimal place instead of two like in the original .pos() tuple but it shouldn't matter because the problem only occurs when the y-value is negative)
It looks like it is saying that -10.0 is not equal to -10.00. Any ideas on why this might not be working?
Here is the actual code too if it helps. I use 'in' because Im storing all of the space coordinates in a dictionary:
def player_movement(player, total, direction):
current = player.pos()
if direction == 'up':
if (current[0], current[1] + total) in space_coordinates.values():
player.shape('Player_Up.gif') # Changes player sprite
player.goto(current[0], current[1] + total) # Moves player
I already checked if the coordinate I needed was in the dictionary and it was
Turtles wander a floating point plane so exact comparisons are to be avoided. Instead of asking:
turtle_1.position() == turtle_2.position()
you should consider asking:
turtle_1.distance(turtle_2) < 10
That is, are they in close proximity to each other, not on the exact same coordinate.

Saving valid moves in Negamax makes little to no difference in speed

I have a normal Negamax algorithm with alpha-beta pruning which is initiated with iterative deepening (ID). I thought that to really get use of ID I save the calculated valid moves from depth 1 in a table, so next time I go for depth 2 and the same original position arrives I can just grab the valid moves from the table instead to save time. However, I find that this idea doesn't save any time at all really which makes me think:
I have never seen anyone do this, is it not worth it for some reason?
My implementation of this is wrong?
I am confused by how Negamax works and maybe this is impossible to do in the first place?
Here is the original iterative call, along with a snippet of the Negamax function itself:
self.valid_moves_history = []
for depth in range(1, s.max_search_depth):
move, evaluation = self.negamax(gamestate, depth, -math.inf, math.inf, s.start_color)
# ----------------------------------------------------------------------------
def negamax(self, gamestate, depth, alpha, beta, color):
if self.zobrist_key in self.valid_moves_history:
children = self.valid_moves_history[self.zobrist_key]
else:
children = gamestate.get_valid_moves()
self.valid_moves_history[key] = children
if depth == 0 or gamestate.is_check_mate or gamestate.is_stale_mate:
return None, e.evaluate(gamestate, depth) * color
# Negamax loop
max_eval = -math.inf
for child in reversed(children):
gamestate.make_move(child[0], child[1])
score = -self.negamax(gamestate, depth - 1, -beta, -alpha, -color)[1]
gamestate.unmake_move()
if score > max_eval:
max_eval = score
best_move = child
alpha = max(alpha, max_eval)
if beta <= alpha:
break
The most time consuming tasks of my complete program are distributed something like this (% of total runtime for a game):
Calculate valid moves: 60%
Evaluation function (medium complexity at the moment): 25%
Negamax itself with lookups, table saves etc: 5%
Make/unmake moves: 4%
Is it normal/reasonable for the calculating move time to be this high? This is the main reason why I thought to save valid moves in a list in the first place.
Or can someone please explain why this is a good/bad idea and what I should do instead? Thank you for any input.
I know this thread is quite old at this point but I think that this could still be useful to some people. The whole topic which you are talking about is called transposition tables in Minimax and you can find many links to the topic. Negamax is the same as Minimax except you do not have separate functions for the Max and Min players, and instead you just call a max function and turn it into a negative. I think it is probably more useful for you to implement move ordering first as it can double the speed of your program. You can also find a more efficient way to find valid moves to speed up the program.

ODE Event Location in python

Is there any similar function in python to ODE Event Location function? For example, how can I write a code similar to
function [value,isterminal,direction] = event(~,x)
value = x(1); % detect x(1)=0
isterminal = true; % Stop the integration
direction = -1; % positive direction=1, negative =-1, all=0
I mean I want to detect the time at which a bouncing ball hit the ground and then it jumps back . At that time initial conditions change.
Look at the documentation of solve_ivp. I think the bouncing ball is even an example there.
The equivalent is
def event(t,x): return x[0]
event.terminal=True
event.direction=-1
The difference is in multiple events, where matlab can use one vector valued event function, solve_ivp uses a vector of scalar valued functions.

Weighted Traversal Algorithm (Breadth first is better?)

I'm having trouble designing an algorithm for a traversal problem.
I have a Ship that I control on a 2D grid and it starts on the very bottom of the grid. Each tile of the grid has a value (between 0 and 1000) equal to how much 'resource' is in that tile.
The Ship can go_left(), go_up(), go_right() or stay_still()
If the ship stay_still() it collects 25% of it's current tile's resource (rounded up to the nearest int).
If the ship uses a move command, it needs to spend 10% of it's current tile resource value rounded down. Moves that cost more than the ship has collected are illegal. (So if a ship is on a 100, it costs 10 to move off the 100, if it's on a 9 or less, moving is free).
The goal is to find a relatively short path that legally collects 1000 resource. Returning a list of the move order to corresponds to the path.
I naturally tried a recursive approach:
In sudo-code the algorithm is:
alg(position, collected, best_path):
if ship has 1000:
return best_path
alg(stay still)
if ship has enough to move:
alg(try left)
alg(try up)
alg(try right)
If you want a closer look at the actual syntax in python3 here it is:
def get_path_to_1000(self, current_position, collected_resource, path, game_map):
if collected_resource >= 1000:
return path
path_stay = path.copy().append(stay_still())
self.get_path_to_1000(current_position, collected_resource +
math.ceil(0.25 * game_map[current_position].value),
path_stay, game_map.copy().collect(current_position))
cost = math.floor(0.1 * game_map[current_position].value)
if collected_resource >= cost:
direction_list = [Direction.West, Direction.North, Direction.East]
move_list = [go_left(), go_up(), go_right()]
for i in range(3):
new_path = path.copy().append(move_list[i])
self.get_path_to_1000(
current_position.offset(direction_list[i]),
collected_resource - cost, new_path, game_map)
The problem with my approach is that the algorithm never completes because it keeps trying longer and longer lists of the ship staying still.
How can I alter my algorithm so it actually tries more than one option, returning a relatively short (or shortest) path to 1000?
The nature of this problem (ignoring the exact mechanics of the rounding down/variable cost of moving) is to find the shortest number of nodes in order to acquire 1,000 resources. Another way to look at this goal is that the ship is trying to find the most efficient move with each turn.
This issue can be solved with a slightly modified version of Dijksta's algorithm. Instead of greedily choosing the move with the least weight, we will choose the move with the most weight (greatest number of resources), and add this value to a running counter that will make sure that we reach 1000 resources total. By greedily adding the most efficient edge weights (while below 1000), we'll find the least number of moves to get a total 1000 resources.
Simply keep a list of the moves made with the algorithm and return that list when the resource counter reaches 1000.
Here's a helpful resource on how to best implement Dijkstra's algorithm:
https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/
With the few modifications, it should be your best bet!

Turtle Graphics with Recursion

I need to draw a shape using recursion and turtle graphics.
I'm more of a looper and rarely ever use recursion, so some help here with this would be nice. Not even sure where to start.
The shape just needs to be cool looking.
Oh man! What a fun problem :)
As you are a self-proclaimed 'looper', I would think about recursion just as you would looping.
In a for loop, you execute the body of the loop until the for loop condition is satisfied. Now, recursion is very similar. You keep calling the function until the parameters of the function no longer hit a recursive case. They hit a base case instead which then returns a value that the recursion can then build up on.
So thinking about recursion this way, let's think about how to draw a square. You need to first identify what parts of the code get repeated (i.e. what would be in the body of a for loop trying to do the same thing). Then, identify when you want this repetition to stop (i.e. how do I know when a for loop exits).
While drawing a square, I can think of two major things that get repeated at least 4 times. The turtle goes forward a certain number of steps and the turtle turns 90 degrees (or 270 degrees depending on orientation). So this would be something we detail in our recursive case.
Now, let's think about the base case. Well, we know that a square has 4 sides, so after the turtle draws four sides, we want it to stop.
Lastly, let's think about the function declaration and how these two pieces, the recursive case and the base case, play into it. A function declaration may take the following form (in Python):
def draw_square_recursive(turn_deg=90, side_len, sides=4):
"""
Function draws a square with turtle graphics recursively
:param turn_deg: an int, the number of degrees a turtle should turn
:param side_len: an int, the length of a side of the square
:param sides: an int, the number of sides in our square
"""
turn_deg and side_len will be important for our recursive case as they define how a turtle should turn and how far it should 'walk'. sides is an interesting parameter and one we can use to dictate whether to continue recurring or stop. If we subtract 1 from sides every time we draw a side, we will know that we need to stop recurring when sides == 0, a base case!
Thus, whenever we call our function to recur again, we will call it as, draw_square_recursive(side_len, sides-1):
Overall, the structure of the function would look like:
def draw_square_recursive(turn_deg=90, side_len, sides=4):
"""
Function draws a square with turtle graphics recursively
:param turn_deg: an int, the number of degrees a turtle should turn
:param side_len: an int, the length of a side of the square
:param sides: an int, the number of sides in our square
"""
if sides == 0:
# base case!
else:
# recursive case!
Note that this function named draw_square_recursive but it can be much more generalized to other shapes. Do you see how?
Sorry if this was a long winded answer! Hope it helps ;p
Without any parametrization, here a beginning:
import time
from turtle import *
def recurse(n):
if n>0:
left(10)
forward(5)
recurse(n-1)
recurse(20)
time.sleep(5)
When you create recursive function, you need to have a stop criterion that effectively guaranties your program will exit at some point.
More editorial than answer, but recursion like this:
def recurse(n):
if n>0:
left(10)
forward(5)
recurse(n-1)
which is better written as iteration:
for n in range(2):
left(10)
forward(5)
is similar to folks who ask, "How can I count the number of elements in a list using recursion?" Ditto drawing a square using recursion.
I understand the goal is to learn about recursion, but what seems to get lost is that there are times where recursion makes wonderful things happen and times where it just slows down your program. Fractals are an opportunity to so something of wonder with recursion:
import sys
from turtle import Turtle, Screen
def hilbert_curve(n, turtle, angle=90):
if n <= 0:
return
turtle.left(angle)
hilbert_curve(n - 1, turtle, -angle)
turtle.forward(1)
turtle.right(angle)
hilbert_curve(n - 1, turtle, angle)
turtle.forward(1)
hilbert_curve(n - 1, turtle, angle)
turtle.right(angle)
turtle.forward(1)
hilbert_curve(n - 1, turtle, -angle)
turtle.left(angle)
depth = int(sys.argv[1])
size = 2 ** depth
screen = Screen()
screen.setworldcoordinates(0, 0, size, size)
yertle = Turtle('turtle')
yertle.speed('fastest')
yertle.penup()
yertle.goto(0.5, 0.5)
yertle.pendown()
hilbert_curve(depth, yertle)
yertle.hideturtle()
screen.exitonclick()
USAGE
% python3 hilbert.py 5
(PARTIAL) OUTPUT
I'm not picking on the other answers, I'm suggesting you think big (or at least beyond "just needs to be cool looking".)

Categories

Resources