This is my first question ever, and I am a complete and utter beginner, so please don't eat me :) What I am trying to to is to draw a fibonacci sequence using the Python turtle module. My code is as follows:
import turtle
zuf = turtle.Turtle()
while True:
zuf.forward(10)
zuf.left(3.1415)
This, however, drives around in circles only. I have tried to create a variable, say X, and assign a fibonacci rule to it xn = xn-1 + xn-2 then I'd put it in here zuf.forward(x) but it doesn't work. I tried multiple variations of that, but none seems to work. Please don't give a whole solution, only some hint, thanks a lot.
I think I can get you from where you are to where you want to be. First, your invocation of:
zuf.left(3.1415)
seems to indicate you're thinking in radians, which is fine. But you need to tell your turtle that:
zuf = turtle.Turtle()
zuf.radians()
this will still make your code go in circles, but very different circles. Next, we want to replace 10 with our fibonacci value. Before the while loop, initialize your fibonacci counters:
previous, current = 0, 1
as the last statement in the while loop, bump them up:
previous, current = current, current + previous
and in your forward() call, replace 10 with current. Next, we need to turn the line that it's drawing into a square. To do this, we need to do two things. First, loop the drawing code four times:
for i in range(4):
zuf.forward(current)
zuf.left(3.1415)
And second, replace your angle with pi/2 instead:
zuf.left(3.1415 / 2)
If you assemble this all correctly, you should end up with a figure like:
showing the increasing size of the fibonacci values. Not the greatest looking image, you'll still have to do some work on it to clean it up to look nice.
Finally, I was impressed with the fibonacci drawing code that #IvanS95 linked to in his comment, that I wrote a high speed version of it that uses stamping instead of drawing:
from turtle import Screen, Turtle
SCALE = 5
CURSOR_SIZE = 20
square = Turtle('square', visible=False)
square.fillcolor('white')
square.speed('fastest')
square.right(90)
square.penup()
previous_scaled, previous, current = 0, 0, 1
for _ in range(10):
current_scaled = current * SCALE
square.forward(current_scaled/2 + previous_scaled/2)
square.shapesize(current_scaled / CURSOR_SIZE)
square.left(90)
square.forward(current_scaled/2 - previous_scaled/2)
square.stamp()
previous_scaled, previous, current = current_scaled, current, current + previous
screen = Screen()
screen.exitonclick()
This is not a whole solution for you, only a hint of what can be done as you're drawing your squares and this is a stamp-based solution which plays by different rules.
Related
At first I must say I am from Mathematics background and I have a very little knowledge about programming in Python. I am working on drawing complete bipartite graph with minimum number of crossings. For example: K(4,4) the complete bipartite graph with 8 vertices (grouped in 4 - 4) given in the following diagram.
The graph has crossing number = 4. I would like to draw graphs like this with higher number of vertices for example K(9,9), complete bipartite graph with 18 vertices. I have searched for different coding and theories. I found that Python has turtle package that can help me in this matter. I have planned to use an algorithm: I will start the turtle's journey from one vertex and stop on other vertex, in between the journey I will collect the coordinates of the path where it traveled and then repeat the process under the condition that It must not coincide with any other edge, if this happens then take the path which has minimum number of intersections.
Currently I am working on turtle and its commands. Any idea on how solve this problem, any recommendations on using more suitable software (paid or open source), help on algorithm, recommendations on books or research papers is highly appreciated.
I have made this diagram using yED (freely available) but for higher number of vertices manual work is very laborious.
Thanks in advance!
Sorry I'm not exactly answering the question re turtle graphics. Since you are a mathematician, don't you use LaTeX? If so, here's a little program to get you started:
from string import Template
DOC = Template("""
\\documentclass{article}
\\usepackage{tikz}
\\begin{document}
\\begin{tikzpicture}
$drawing\\end{tikzpicture}
\\end{document}
""")
class GraphDrawing(object):
def __init__(self, node_count: int):
self.node_count = node_count;
def Coord(self, i: int):
c = self.node_count
offset = 1 - c if c % 2 == 0 else - c
return offset + 2 * i
def Draw(self):
r = ''
for i in range(self.node_count):
for j in range(self.node_count):
r += f'\\draw ({self.Coord(i)},0) -- (0,{self.Coord(j)});\n'
for i in range(self.node_count):
r += f'\\filldraw ({self.Coord(i)},0) circle (3pt);\n'
r += f'\\filldraw (0,{self.Coord(i)}) circle (3pt);\n'
print(DOC.substitute({'drawing' : r}))
GraphDrawing(8).Draw()
Run through pdflatex, this produces:
If you really need turtle graphics, it should be pretty straightforward to replace the string construction in this program with turtle moves.
As http://garden.irmacs.sfu.ca/op/the_crossing_number_of_the_complete_bipartite_graph says, it is believed that the diagram you provided is always optimal. Put the one set on a vertical axis and the other on the horizontal, split close to evenly top/bottom, left/right. Then connect by straight lines. It is highly unlikely that you will find better than that.
You can see https://mathworld.wolfram.com/ZarankiewiczsConjecture.html for more, including various small n cases where it has been confirmed.
i have this simple game where there is a ball bouncing on the screen and the player can move left and right of the screen and shoot an arrow up to pop the ball, every time the player hits a ball, the ball bursts and splits into two smaller balls until they reach a minimum size and disappear.
I am trying to solve this game with a genetic algorithm based on the python neat library and on this tutorial on flappy bird https://www.youtube.com/watch?v=MMxFDaIOHsE&list=PLzMcBGfZo4-lwGZWXz5Qgta_YNX3_vLS2, so I have a configuration file in which I have to specify how many input nodes must be in the network, I had thought to give as input the player's x coordinate, the distance between the player's x-coordinate and the ball's x-coordinate and the distance between the player's y-coordinate and the ball's y-coordinate.
My problem is that at the beginning of the game I have only one ball but after a few moves I could have more balls in the screen so I should have a greater number of input nodes,the more balls there are on the screen the more input coordinates I have to provide to the network.
So how to set the number of input nodes in a variable way?
config-feedforward.txt file
"""
# network parameters
num_hidden = 0
num_inputs = 3 #this needs to be variable
num_outputs = 3
"""
python file
for index,player in enumerate(game.players):
balls_array_x = []
balls_array_y = []
for ball in game.balls:
balls_array_x.append(ball.x)
balls_array_x.append(ball.y)
output = np.argmax(nets[index].activate(("there may be a number of variable arguments here")))
#other...
final code
for index,player in enumerate(game.players):
balls_array_x = []
balls_array_y = []
for ball in game.balls:
balls_array_x.append(ball.x)
balls_array_y.append(ball.y)
distance_list = []
player_x = player.x
player_y = player.y
i = 0
while i < len(balls_array_x):
dist = math.sqrt((balls_array_x[i] - player_x) ** 2 + (balls_array_y[i] - player_y) ** 2)
distance_list.append(dist)
i+=1
i = 0
if len(distance_list) > 0:
nearest_ball = min(distance_list)
output = np.argmax(nets[index].activate((player.x,player.y,nearest_ball)))
This is a good question and as far as I can tell from a quick Google search hasn't been addressed for simple ML algorithms like NEAT.
Traditionally resizing methods of Deep NN (padding, cropping, RNNs, middle-layers, etc) can obviously not be applied here since NEAT explicitly encodes each single neuron and connection.
I am also not aware of any general method/trick to make the input size mutable for the traditional NEAT algorithm and frankly don't think there is one. Though I can think of a couple of changes to the algorithm that would make this possible, but that's of no help to you I suppose.
In my opinion you therefore have 3 options:
You increase the input size to the maximum number of balls the algorithm should track and set the x-diff/y-diff value of non-existent balls to an otherwise impossible number (e.g. -1). If balls come into existence you actually set the values for those x-diff/y-diff input neurons and set them to -1 again when they are gone. Then you let NEAT figure it out. Also worth thinking about concatenating 2 separate NEAT NNs, with the first NN having 2 inputs, 1 output and the second NN having 1 (player pos) + x (max number of balls) inputs and 2 outputs (left, right). The first NN produces an output for each ball position (and is identical for each ball) and the second NN takes the first NNs output and turns it into an action. Also: The maximum number of balls doesn't have to be the maximum number of displayable balls, but can also be limited to 10 and only considering the 10 closest balls.
You only consider 1 ball for each action side (making your input 1 + 2*2). This could be the consideration of the lowest ball on each side or the closest ball on each side. Such preprocessing can make such simple NN tasks however quite easy to solve. Maybe you can add inertia into your test environment and thereby add a non-linearity that makes it not so straightforward to always teleport/hurry to the lowest ball.
You input the whole observation space into NEAT (or a uniformly downsampled fraction), e.g. the whole game at whatever resolution is lowest but still sensible. I know that this observation space is huge, but NEAT works quite well in handling such spaces.
I know that this is not the variable input size option of NEAT that you might have hoped for, but I don't know about any such general option/trick without changing the underlying NEAT algorithm significantly.
However, I am very happy to be corrected if someone knows a better option!
stuck on a simple task any help would be much appreciated. It creates a graphic window, and depending on where the user clicks it will draw a different colour circle. Right hand = Yellow and the left hand will be red depending on where the user clicks. However i cant get my if statement to work, and all its returning is 10 yellow circles. Any help would be appreciated , thanks
def circles():
win = GraphWin ("circles", 400,100)
for i in range (10):
point = win.getMouse()
circleFill = Circle(point, 10)
circleFill.draw(win)
if str(point) >= str(200):
circleFill = Circle (point, 10)
circleFill.setFill("Yellow")
circleFill.draw(win)
else:
circleFill = Circle (point, 10)
circleFill.setFill("Red")
circleFill.draw(win)
You're trying to compare a point to a number. This doesn't make any sense. Is the upper-right corner of your screen more than 200? What about the lower-right? Or the upper-left?
Of course you can convert them both to strings, then compare those, because you can always compare strings—but then you're just asking whether something like 'Point(1600, 0)' would comes before or after '200' in the dictionary, which doesn't tell you anything useful.
Your next attempt, trying to compare a point to a point, still doesn't make any sense. Is (1600, 20) more or less than (100, 1280)? Of course there are various ways you could answer that (e.g., you could treat them as vectors rather than points and ask for their norms), but nothing that seems relevant to your question.
I think what you might want to do here is to compare the X coordinate of the point to a number:
if point.getX() >= 200:
That makes sense. That covers the whole right part of the screen, whether way up at the top or way down at the bottom, because whether you're at (1600, 0) or (1600, 1200), that 1600 part is bigger than 200.
That may not actually be what you want, but hopefully if it isn't, it gives you the idea to get unstuck.
I'm making a PONG game for a school project using Kivy in Python. So far thanks to this forum I've made myself some AI for the NPC paddle.
This is the code:
if self.ball.y < self.player2.center_y:
self.player2.center_y = self.player2.center_y - 4
if self.ball.y > self.player2.center_y:
self.player2.center_y = self.player2.center_y + 4
This is in a method of PongGame() class called ArtificialIntelligence().
I use this to call it:
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
This allows me to call it once every 1/300th of a second. However, anything more than 1/300, I seem to have no difference. I.e. 1/9001 does not call it once every 1/9001th of a second.
The way it works is that it increases the y coordinate 4 pixels relative to the balls position, and it does this once every 1/300th of a second, hence why it doesn't "lag" at this rate. This is basically an "easy" mode for the player. If I want to do a "hard" mode, I need to make the NPC more accurate. I can do this by doing
self.player2.center_y = self.player2.center_y + 20
Something like this. This would be extremely accurate. HOWEVER, it does NOT look "fluid", it looks "laggy". I assume I could get the same amount of movement by calling the method more often instead of changing the amount it moves via altering the pixel movement. However, I don't know how to do this, because, as I said, changing it from anywhere above 1/300 seems to make no difference.
This is how I use my paddle:
if touch.x < self.width/3:
self.player1.center_y = touch.y
and I can move it as fast as I want because this updates as I move the mouse. And it looks fluid because it updates as often as it needs to update. I don't know how to do this with my AI.
Does anyone know how I could basically make the NPC paddle more accurate, allowing me to do Easy-Normal-Hard, etc, while retaining fluidity and no lag? I see only one way I could do it: Increase the amount the method is called.
However I bet there is a better way and I don't know how to do it. Does anyone have any Idea how I could do this? Thanks.
Edit: it looks like I can do it like this:
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
But that seems REALLY ugly and REALLY inefficient... I'd MUCH prefer a cleaner way.
At 300 frames per second, the problem is not in the rate of updates because you are exceeding the human eye's capacity to perceive movement by a factor of 50 or more.
The jerky movement comes because the ball is following a linear trajectory while your paddle is just hopping to where the ball is now. Ideally, your computer player could compute where the ball will be when it hits the plane of the computer paddle and then take a very smooth course to that location at 30 frames per second or less. Sure, the prediction math requires a tiny amount of trigonometry but it is the "right" way to do it in the sense of that is how a good player would play, by anticipating.
It would be far easier to just increase the size of the computer's paddle which would also give a visual indication to the human player of just how much harder the game is. When the computer's paddle has become a wall, the player would see that there is no winning to be done. The larger paddle would have the side effect of being less jerky, but whether this is a "good" way is your decision.
My advice is to use trig to work out where the ball will be, and have the paddle move there to intercept it.
Animation will be smooth at 30 frames per second.
When making a game AI is quite important these days that the player does not see it 'cheating' and giving it a larger paddle, or the ability to teleport, would be obvious signs of this. It should play in the same manner as a human, just better - not using some mechanism the player has no access to. "This game sucks because the CPU cheats" is a very common negative comment on videogame forums.
So if you need the computer to miss, make sure its trig calculations are off by a random factor, so the player cna't distinguish its play from a human's.
edit: For example: If random (X) <= speed of ball, then intercept correctly, otherwise miss by random (Y) units.
Thanks for your help guys, I was able to work it out with my teacher based on your help and his.
He developed this algorithm (tbh he did it so fast that I wasn't really able to comprehend it!) but this essentially uses trig to generate where the paddle will go (Note, I don't use the angle as I have other values that can be used)
def AIController(self, *args):
ballsFuturePos = self.ball.center_y + ((self.width - self.ball.center_x) / self.ball.velocity_x) * self.ball.velocity_y
numIterations = ((self.width - self.ball.center_x) / self.ball.velocity_x)
#print ballsFuturePos
#print numIterations
if numIterations > 0:
self.wantedPos = self.player2.center_y +(ballsFuturePos - self.player2.center_y) / numIterations
#print wantedPos
#self.player2.center_y = wantedPos + (error / wantedPos) * 100
if self.player2.center_y < self.wantedPos:
self.player2.center_y = self.player2.center_y + 9
if self.player2.center_y > self.wantedPos:
self.player2.center_y = self.player2.center_y - 9
So I generate where the ball is going to hit the rightmost part of the screen by getting the balls y position, adding the (width - the x position of the ball) (which gives me how far until the rightmost part of the screen is in x pixels), then I didivde that by the x velocity, and times the whole thing by the y velocity, which gives me the slope (I think), and as such now that the slope is calculated it also means It has the trajectory and as such can predict where the ball will hit the screen.
I calculate the number of iterations needed to get to the ball by taking the width of screen and minusing it by the balls x position, which calculates how far it is until the rightmost part of the screen, and divide that by the velocity. This gives me a number that I can use to iterate.
now I iterate with this, and create a variable called wantedPos which is where I want my paddle to go. This uses the paddles y position, adding (where the ball will be - where the paddle is), which gives me the distance between the ball and the paddle, divided by the number of iterations, which gives me the position the paddle will be to be at the same position at the ball. As numIterations decreases in each call, so does the wantedPos, meaning the gap gets smaller. I then iterate the paddle closer to the ball, using 9 as a speed, which allows me to increase or decrease difficulty.
Thanks. If I messed up any of my logic in trying to describe his actions, please tell! I think I understand it but a confirmation would be nice :)
First of all, I'm fairly sure snapping to grid is fairly easy, however I've run into some odd trouble in this situation and my maths are too weak to work out specifically what is wrong.
Here's the situation
I have an abstract concept of a grid, with Y steps exactly Y_STEP apart (the x steps are working fine so ignore them for now)
The grid is in an abstract coordinate space, and to get things to line up I've got a magic offset in there, let's call it Y_OFFSET
to snap to the grid I've got the following code (python)
def snapToGrid(originalPos, offset, step):
index = int((originalPos - offset) / step) #truncates the remainder away
return index * gap + offset
so I pass the cursor position, Y_OFFSET and Y_STEP into that function and it returns me the nearest floored y position on the grid
That appears to work fine in the original scenario, however when I take into account the fact that the view is scrollable things get a little weird.
Scrolling is made as basic as I can get it, I've got a viewPort that keeps count of the distance scrolled along the Y Axis and just offsets everything that goes through it.
Here's a snippet of the cursor's mouseMotion code:
def mouseMotion(self, event):
pixelPos = event.pos[Y]
odePos = Scroll.pixelPosToOdePos(pixelPos)
self.tool.positionChanged(odePos)
So there's two things to look at there, first the Scroll module's translation from pixel position to the abstract coordinate space, then the tool's positionChanged function which takes the abstract coordinate space value and snaps to the nearest Y step.
Here's the relevant Scroll code
def pixelPosToOdePos(pixelPos):
offsetPixelPos = pixelPos - self.viewPortOffset
return pixelsToOde(offsetPixelPos)
def pixelsToOde(pixels):
return float(pixels) / float(pixels_in_an_ode_unit)
And the tools update code
def positionChanged(self, newPos):
self.snappedPos = snapToGrid(originalPos, Y_OFFSET, Y_STEP)
The last relevant chunk is when the tool goes to render itself. It goes through the Scroll object, which transforms the tool's snapped coordinate space position into an onscreen pixel position, here's the code:
#in Tool
def render(self, screen):
Scroll.render(screen, self.image, self.snappedPos)
#in Scroll
def render(self, screen, image, odePos):
pixelPos = self.odePosToPixelPos(odePos)
screen.blit(image, pixelPos) # screen is a surface from pygame for the curious
def odePosToPixelPos(self.odePos):
offsetPos = odePos + self.viewPortOffset
return odeToPixels(offsetPos)
def odeToPixels(odeUnits):
return int(odeUnits * pixels_in_an_ode_unit)
Whew, that was a long explanation. Hope you're still with me...
The problem I'm now getting is that when I scroll up the drawn image loses alignment with the cursor.
It starts snapping to the Y step exactly 1 step below the cursor.
Additionally it appears to phase in and out of allignment.
At some scrolls it is out by 1 and other scrolls it is spot on.
It's never out by more than 1 and it's always snapping to a valid grid location.
Best guess I can come up with is that somewhere I'm truncating some data in the wrong spot, but no idea where or how it ends up with this behavior.
Anyone familiar with coordinate spaces, scrolling and snapping?
Ok, I'm answering my own question here, as alexk mentioned, using int to truncate was my mistake.
The behaviour I'm after is best modeled by math.floor().
Apologies, the original question does not contain enough information to really work out what the problem is. I didn't have the extra bit of information at that point.
With regards to the typo note, I think I may be using the context in a confusing manner... From the perspective of the positionChanged() function, the parameter is a new position coming in.
From the perspective of the snapToGrid() function the parameter is an original position which is being changed to a snapped position.
The language is like that because part of it is in my event handling code and the other part is in my general services code. I should have changed it for the example
Do you have a typo in positionChanged() ?
def positionChanged(self, newPos):
self.snappedPos = snapToGrid(newPos, Y_OFFSET, Y_STEP)
I guess you are off by one pixel because of the accuracy problems during float division. Try changing your snapToGrid() to this:
def snapToGrid(originalPos, offset, step):
EPS = 1e-6
index = int((originalPos - offset) / step + EPS) #truncates the remainder away
return index * gap + offset
Thanks for the answer, there may be a typo, but I can't see it...
Unfortunately the change to snapToGrid didn't make a difference, so I don't think that's the issue.
It's not off by one pixel, but rather it's off by Y_STEP. Playing around with it some more I've found that I can't get it to be exact at any point that the screen is scrolled up and also that it happens towards the top of the screen, which I suspect is ODE position zero, so I'm guessing my problem is around small or negative values.