How to prevent time delay/racing in python? - python

I'm trying to implement a script which will play the game snake using the a* algorithm. The game was given to me by someone else (my teacher) and I have to write an working script that plays the game as good as possible, using this exact algorithm or some variation of it.
Now, I have written the algorithm and tried various simulations of it and it turns out that it works just fine, however since the game is an .exe I have to take a screenshot of the game screen and transform that into input data for my algorithm from that I construct a path and give commands to the snake using pyautogui.
So to summarize, the algorithm:
Take screenshot
Calculate path and moves
Move towards goal
Repeat until snake dies or certain score is reached.
The problem which I face is that the snake has a certain time which it takes to make 1 move and I delay the key press accordingly to that time, however when I reach the goal I have to repeat all the steps and steps 1-2 always take about 45-55ms to complete and in that time my snake will end up dying because it didn't react quick enough. So what would be a good way to prevent this?
The solution I came up with, works sometimes, but a time delay will form and the snake will either make one move too early or too late at some point which might be deadly:
def simulate_movement(moves, speed):
for move in moves:
text, pause = move
interval1 = round(pause * speed, 1)
if move == moves[-1]:
interval1 = 0.05 # I speed up the final move because steps 1 and 2 take about 0.05ms
pyautogui.press(text, interval=interval1)
Example of what the delay might cause:
The snake in the image has died, however the path which was correct was provided for it, but because it didn't react in time (because of mentioned delay) it bumped into the corner. Is there a way to for example make some code block which takes between 50-60ms to make it run 100ms so that is do nothing until that time passes, because that way I could get rid of the delay by subtracting 100ms from the final move and waiting 100ms until next moves are calculated.

Related

Pygame window freezes sometimes

I created A star algorithm visualization in pygame, and pygame window freezes sometimes (when algorithm is working), I know that this algorithm is not the most optimized one, but I think that the algorithm isnt causing this issue. Please help me, because its quite annoying, and i dont know what causes this issue.
Link to code -> https://github.com/DeathEyeXD/PythonProjects/blob/master/aStarVisualization.py
Please paste relevant part of the code here and show us what you have tried so far.
I assume that you have a main pygame loop running at a certain frequency. When you have a function calculating things in the main loop that takes a considerable amount of time, it will cause the game window to freeze. This is because it cannot reach other things (like your event function) at the same time as it is calculating the path.
With A* algorithm you can make it nicer by drawing the progress (draw the neighbors and checked cells for example). I did a project like this previously which works nicely. You then call your draw function within the A* function at relevant places and you won't get the freeze issue.

Is there a function or a piece of code that will make it so turret can predict where will target be and shoot at the place? (Linear Prediction)

I'm making a game with turrets and bots included and I wanted to make some SmartAim() function that will make them "smarter" and they will predict the position and shoot so they will almost never miss.
I tried to search and code my own program but there is still one thing missing: the bullet and target SPEED. i am moving bullets trough Sin() and Cos() but i never managed to get it right

How much time should the mouse left button be held?

If you want to detect a Bot that is clicking on a button when he has to, could you look how long the left button stays down before being up again?
I mean a script like this one (python):
import win32api, win32con
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
Will click really fast. Probably faster than a human. And always at (really closely) the same speed. Could an anti-bot system detect that?
So you can add a time.sleep(float) instruction between the two mouse_event's. But should it be randomised? We probably have a slight difference of time between two clicks, less precise than a computed click.
So how much time should we make the sleep last (min and max of the randrange)?
It's probably too much effort for being undetected but is that possible?
So quick recap:
Can we detect a bot on the click speed and click time never changing even a bit?
How long does an average person press the button down before letting it go up? If I want to stay undetected should I randomise this time, and with which min and max?
(I'm not talking about other existing security like checking if you press the same pixel over and over.)
Yes, bots can and are detected this way.
Yes, adding a random offset to the click speed, delay, mouse path, movement speed, and many more things is the standard solution to circumvent this kind of detection. There are many other ways to detect bots though.
To get an average click speed, write a short program that logs the timestamps for mouseDown and mouseUp events and click in it.
This is an old question, but anyway, according to this paper here Transfer learning for behavioral biometrics
It shows that
the average mouse click lasts 85ms, with Q3 = 95ms, Q1= 75ms; with an upper fence of 135ms and a lower fence of 55ms.
Then you can turn this distribution into a gaussian for easy implementation.
To implement this in your code(approximately) in python, you can use NumPy normal distribution, with mean 85ms, and to calculate the standard deviation you can use the rule of thumb:
sd = IQR/1.35
And therefore, sd = 14.8148148, u=85ms

I am having trouble exiting my infinite loop in pygame

Code
This is my little game of pig. I only got it coded for 2 players. I have ran multiple scenarios and it seems to work out good.
I just can't seem to exit the while loop
I am having trouble at line #109.
I set it to break, but i believe it may be break from the small if statement, which I don't want.
I am wanting to break from the large while loop ( game loop ) line #100
I also want to use pygame to add some graphics of dice i have created.
I was wondering if I can keep my code as is and just modify it to work with pygame easily or do I have change the entire code to work with pygame?
I just want to do a simple interface
It will be similar to this : http://cs.gettysburg.edu/projects/pig/pi…
but I will add in dice, simulation of dice rolling 2d, sounds, a win state graphics and sounds, and input, mainly mouse toggle.
Any tips on how to do the pygame portion is much appreciated.
I have read many tutorials on pygame, but I just don't feel confident to get it to work with my own game.
I have made a ball bounce, but I really don't understand what some of pygame's code mean.
I am a little confused on display screen vs background
screen would be pygame.display.set_mode((some size))
then background will capture the exact size of the screen, but not really sure.
I have figured out how to put dice on the screen, and change face every half a second, but that's it.
nice little program. it seems to work fine for me (break exits for and while loops, not if).
when you play the game it's a little confusing because the check to see if someone has won comes only after the other player plays and then you enter 'hold'. perhaps that is what made you think it wasn't working? it might be better (i don't know the exact rules of pig) to put the check for winning right after the code that runs on 'hold'?
sorry can't help with pygame; just wanted to post to say it seems to work.
also, if you wanted, you could put the two players in an array:
players = [player1, player2]
and then the current player would be:
players[player_turn-1]
and you could use the same code for either player, duplicating the logic in the main loop. so the code would be more like:
if players[player_turn-1].winner():
...
#Make a Variable set it to "False".
#= means to assign something to something.
#== means equal to.
#Example in a if statement if something == to something do something.
test = False
#This is the loop.
while test == False:
#Put Code Here.
#Put a If Statement `enter code here`to stop loop.
if #Parameters:
test = True

directing a mass of enemies at once

I am working on a simple 2d game where many enemies continually spawn and chase the player or players in python + pygame. A problem I ran into, and one many people that have programmed this type of game have run into is that the enemies converge very quickly. I have made a temporary solution to this problem with a function that pushes any two enemies randomly apart if they are too close to each other. This works well but is about an O(n^2) algorithm which is run every frame and at high enemies the program starts to slow down.
When my program runs with this function the enemies seem to form round object I nicknamed a "clump". The clump seems to usually ecliptic but may actually be more complex (not symmetrical) because as the player moves the enemies are being pulled in different directions. I do like the way this clump behaves, however I am wondering if there is a more efficient way to calculate it. Currently every enemy in the clump (often >100) is first moved in the direction of the player, and then pushed apart. If there was instead a way to calculate the figure that the clump creates, and how it moves it would save a lot of computation.
I am not exactly sure how to approach the problem. It may be possible to calculate where the border of the figure moves, and then expand it to make sure the area stays the same.
Also my two functions currently being used to move enemies:
def moveEnemy(enemy, player, speed):
a = player.left-enemy.left
b = player.top-enemy.top
r = speed/math.hypot(a,b)
return enemy.move(r*a, r*b)
def clump(enemys):
for p in range(len(enemys)):
for q in range(len(enemys)-p-1):
a = enemys[p]
b = enemys[p+q+1]
if abs(a.left-b.left)+abs(a.top-b.top)<CLUMP:
xChange = (random.random()-.5)*CLUMP
yChange = ((CLUMP/2)**2-xChange**2)**.5
enemys[p] = enemys[p].move(int(xChange+.5), int(yChange + .5))
enemys[p+q+1] = enemys[p+q+1].move(-int(xChange+.5),-int(yChange+.5))
return enemys
Edit: some screen shots of how the clump looks:
http://imageshack.us/photo/my-images/651/elip.png/
http://imageshack.us/photo/my-images/832/newfni.png/
http://imageshack.us/photo/my-images/836/gamewk.png/
The clump seems to be mostly a round object just stretched (like an eclipse but may be stretched in multiple directions), however it currently has straight edges due to the rectangular enemies.
There are several ways to go about this, depending on your game. Here are some ideas for improving the performance:
Allow for some overlap.
Reduce your distance checking to be done after a fixed number of frames.
Improve your distance checking formula. If you are using the standard distance formula, this can be optimized in many ways. For one, get rid of the square root. Precision doesn't matter, only the relative distance.
Each unit can keep track of a list of nearby units. Only perform your calculations between the units in that list. Every so often, update that list by checking against all units.
Depending on how your game is setup, you can split the field up into areas, such as quadrants or cells. Units only get tested against other units in that cell.
EDIT: When the units get close to their target, it might not behave correctly. I would suggest rather than having them home-in on the exact target from far away, that they actually seek a randomized nearby target. Like an offset from their real target.
I'm sure there are many other ways to improve this, it is pretty open ended after all. I should also point out Boids and flocking which could be of interest.
You could define a clump as a separate object with a fixed number of spacial "slots" for each enemy unit in the clump. Each slot would have a set of coordinates relative to the clump center and would either be empty or would hold a reference to one unit.
A new unit trying to join the clump would move towards the innermost free slot, and once it got there it would "stay in formation", its position always being the position of the slot it occupied. Clumps would have a radius much larger than a single unit, would adjust position to avoid overlapping other clumps or loose units that weren't trying to join the clump, etc.
At some point, though, you'd need to deal with interactions for the individual units in the clump, though, so I'm not sure it's worthwhile. I think Austin Henley's suggestion of splitting the field up into cells/regions and only testing against units in nearby cells is the most practical approach.
I think you're looking for flocking.
The best intro to flocking / steering behavior movement: http://www.red3d.com/cwr/steer/ . See the attached paper red3d paper. And the related OpenSteer

Categories