How to bind enter key to a function using turtle - python

I'm trying to make a tic tac toe game where you use arrow keys to move a turtle around the board, and when you press the enter key it draws a circle (nought in the code) or a cross.
I've tried using similar code to what I used for the movement keys but replace it for the enter key and C key (for cross) but they don't work and automatically draw the cross when it starts up. I've also tried using monkey but that doesn't work.
import turtle
sc = turtle.Screen()
bo = turtle.Turtle()
#screen
sc.bgcolor("black")
sc.title("tic tac toe")
#board
bo.color("white")
bo.penup()
bo.speed(0)
bo.setposition(-100, -300)
bo.pendown()
bo.setposition(-100, 300)
bo.penup()
bo.setposition(100, 300)
bo.pendown()
bo.setposition(100, -300)
bo.penup()
bo.setposition(-300, 100)
bo.pendown()
bo.setposition(300, 100)
bo.penup()
bo.setposition(300, -100)
bo.pendown()
bo.setposition(-300,-100)
bo.penup()
bo.setposition(0,0)
#naught and cross function
def c() :
bo.pendown()
x = bo.xcor()-80
y = bo.ycor()+80
bo.penup()
bo.setposition(x,y)
bo.pendown()
x = bo.xcor()+160
y = bo.ycor()-160
bo.setposition(x,y)
bo.penup()
x = bo.xcor()-160
bo.setposition(x,y)
bo.pendown()
x = bo.xcor()+160
y = bo.ycor()+160
bo.setposition(x,y)
bo.penup()
bo.setposition(0,0)
def n() :
y = bo.ycor()-80
x = bo.xcor()
bo.setposition(x, y)
bo.pendown()
bo.circle(80)
bo.penup()
bo.setposition(0,0)
#movment
def move_left(event):
x = bo.xcor()
x -= 200
if x < -300:
x = -200
bo.setx(x)
def move_right(event):
x = bo.xcor()
x += 200
if x > 300:
x = 200
bo.setx(x)
def move_down(event):
y = bo.ycor()
y -= 200
if y < -300:
y = -200
bo.sety(y)
def move_up(event):
y = bo.ycor()
y += 200
if y > 300:
y = 200
bo.sety(y)
#Keybinding
turtle.listen()
turtle.getcanvas().bind("<Left>", move_left)
turtle.getcanvas().bind("<Right>", move_right)
turtle.getcanvas().bind("<Up>", move_up)
turtle.getcanvas().bind("<Down>", move_down)
I'd eventually like to have it where once you draw a cross, and press enter, it draws a circle where there isn't a cross.

There's no need to drop down to the Tk Canvas to configure your key events:
turtle.getcanvas().bind("<Left>", move_left)
You can do the same from turtle itself:
sc.onkey(move_left, "Left")
I've reworked your code below, adding a key event for "Return" that draws the naughts and crosses. Since you don't have an underlying data structure for your game, I set it up to simply alternate between the two:
from turtle import Screen, Turtle
# naught and cross functions
def cross():
x, y = board.position()
board.penup()
board.setposition(x - 80, y - 80)
board.pendown()
board.setposition(x + 80, y + 80)
board.penup()
board.setx(x - 80)
board.pendown()
board.setposition(x + 80, y - 80)
board.penup()
board.home()
def naught():
board.sety(board.ycor() - 80)
board.pendown()
board.circle(80)
board.penup()
board.home()
first_player = True
def choose():
global first_player
if first_player:
naught()
else:
cross()
first_player = not first_player
# movement
def move_left():
x = board.xcor() - 200
if x < -300:
x = -200
board.setx(x)
def move_right():
x = board.xcor() + 200
if x > 300:
x = 200
board.setx(x)
def move_down():
y = board.ycor() - 200
if y < -300:
y = -200
board.sety(y)
def move_up():
y = board.ycor() + 200
if y > 300:
y = 200
board.sety(y)
# screen
screen = Screen()
screen.bgcolor("black")
screen.title("tic tac toe")
# board
board = Turtle()
board.color("white")
board.speed('fastest')
# vertical lines
board.penup()
board.setposition(-100, -300)
board.pendown()
board.sety(300)
board.penup()
board.setx(100)
board.pendown()
board.sety(-300)
board.penup()
# horizontal lines
board.setposition(-300, 100)
board.pendown()
board.setx(300)
board.penup()
board.sety(-100)
board.pendown()
board.setx(-300)
board.penup()
board.home()
# Keybinding
screen.onkey(move_left, "Left")
screen.onkey(move_right, "Right")
screen.onkey(move_up, "Up")
screen.onkey(move_down, "Down")
screen.onkey(choose, "Return")
screen.listen()
screen.mainloop()
This allows two people to play the game and should be something you can build upon.

Related

How to prevent Python Turtle from going through lines it has drawn?

I'm making a game using Turtle in Python 3.
My main problem is that the turtle can move through the "drawn" lines in the game. It's basically a randomized "flappy-bird" game, different each time you run the program.
Is it possible to prevent the Turtle from going through lines it has drawn?
The program creates both walls and holes the player should be able to get through, like flappy bird where it's a pipe-hole-pipe with different lengths on the pipes.
And if I run print(hole) at the end of the program it returns None. Why is this?
Here is my program:
import turtle
import random
GameOver=False
import math
import time
board = turtle.Screen()
board.screensize(50.50)
board.bgcolor("black")
board.title("Labyrinten")
Hast_på_ritande_av_bana= 0
TURTLE_SIZE = 20
playerspeed = 50
n=1 #variabeler som gör att den hoppar ett steg åt höger när den gör raderna t.ex. ((930/8)*n)
b=2 #
global player
#SÄTTER UPP SKÄRM
border = turtle.Turtle()
border.speed(Hast_på_ritande_av_bana)
border.hideturtle()
border.color("white")
border.shape("triangle")
border.penup()
border.goto(TURTLE_SIZE/2 - board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
border.pendown()
border.showturtle()
border.rt(90)
border.fd(780)
border.penup()
#ritar banan
for rader in range(4): #creating the maze
border.lt(90)
border.fd(930/8)
border.pendown()
border.lt(90)
wall_ett = border.fd(random.randint(50,630)) #lower wall on row 1
border.penup()
hole=border.fd(random.randint(30,70)) #hole on row 1
border.pendown()
wall_ett_ett = border.goto (TURTLE_SIZE/2 - board.window_width()/2 + (930/8*n), board.window_height()/2 - TURTLE_SIZE/2) #higher wall on row 1
border.rt(90)
border.fd(930/8)
border.rt(90)
wall_två_ett = border.fd(random.randint(50, 630)) #lower wall on row 2
border.penup()
hole2 = border.fd(random.randint(30, 70)) #hole on row 2
border.pendown()
wall_två_två = border.goto(TURTLE_SIZE/2 - board.window_width()/2 + (930/8*b), + TURTLE_SIZE/2 - board.window_height()/2 ) # higher wall on row 2
n = n + 2
b = b + 2
border.goto(TURTLE_SIZE/2 - board.window_width()/2 , TURTLE_SIZE/2 - board.window_height()/2 )
border.goto(TURTLE_SIZE/2 - board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
border.penup()
border.lt(90)
border.fd(930/8)
border.pendown()
border.goto(-TURTLE_SIZE + board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
border.hideturtle()
player=turtle.Turtle()
player.color("green")
player.shape("turtle")
player.hideturtle()
player.penup()
player.goto(TURTLE_SIZE/2 - board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
player.rt(90)
player.fd(30)
player.lt(90)
player.fd((930/8)/2)
player.rt(90)
player.showturtle()
coordinates = player.pos()
#Skapa spelaren (som går igenom banan)
def spawna_spelare():
spawn = turtle.Turtle()
spawn.color("green")
spawn.shape("turtle")
spawn.hideturtle()
spawn.penup()
spawn.goto(TURTLE_SIZE/2 - board.window_width()/2, board.window_height()/2 - TURTLE_SIZE/2)
spawn.rt(90)
spawn.fd(30)
spawn.lt(90)
spawn.fd((930/8)*(random.randint(1,8)))
spawn.rt(90)
spawn.showturtle()
#Gå med spelaren
def move_left():
x = player.xcor()
x -= playerspeed
if x < -460:
x = -460
player.setx(x)
def move_right():
x = player.xcor()
x += playerspeed
if x > 450:
x = 450
player.setx(x)
if x.distance(wall_ett) >20: #or wall_ett_ett or wall_två_ett or wall_två_två) == 1: #
player.shape("triangle")
def move_down():
y = player.ycor()
y -= playerspeed
if y < -375:
y = -375
player.sety(y)
def move_up():
y = player.ycor()
y += playerspeed
if y > 380:
y = 380
player.sety(y)
turtle.listen()
turtle.onkey(spawna_spelare, "space")
turtle.onkey(move_left, "Left")
turtle.onkey(move_right, "Right")
turtle.onkey(move_down, "Down")
turtle.onkey(move_up, "Up")
wall_ett = border.xcor()
wall_två_ett=border.xcor()
print(wall_ett)
print(wall_ett)
print(hole)
board.mainloop()
So you need to draw the walls in a way you can check afterwards if the move the player requested is crossing any wall (or border).
here is a suggestion:
SCREEN_WIDTH = 800
HOLE_HEIGHT = 50
SCREEN_HEIGHT = 600
NUM_WALLS = 8
board = turtle.Screen()
board.setup(SCREEN_WIDTH+10, SCREEN_HEIGHT+10)
board.screensize(SCREEN_WIDTH, SCREEN_HEIGHT)
board.setworldcoordinates(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)
border = turtle.Turtle()
border.speed(10) # draw walls as fast as possible
border.color('white')
border.hideturtle()
# list of the drawn walls, each wall is represented by a tuple:
# (wall_x, wall_hole_lower_y, wall_hole_upper_y)
walls = []
for wall_ix in range(NUM_WALLS):
# compute coordinates of wall and store them
wall_x = int((1+wall_ix) * SCREEN_WIDTH / (1+NUM_WALLS))
wall_ybottom = random.randint(0, SCREEN_HEIGHT - HOLE_HEIGHT)
wall_ytop = wall_ybottom + HOLE_HEIGHT
walls.append((wall_x, wall_ytop, wall_ybottom))
# draw wall
border.penup()
border.goto(wall_x, 0)
border.pendown()
border.goto(wall_x, wall_ybottom)
border.penup()
border.goto(wall_x, wall_ytop)
border.pendown()
border.goto(wall_x, SCREEN_HEIGHT)
def move_right():
old_x = player.xcor()
new_x = old_x + playerspeed
y = player.ycor()
for wall_x, wall_ytop, wall_ybottom in walls:
if old_x <= wall_x <= new_x:
# player is possibly moving across the wall, check that y is valid
if wall_ybottom < y < wall_ytop:
# OK ! player moves through the hole
player.setx(new_x)
else:
# invalid, player is crossing a wall line
# resetting to old position, but you might want to stop the game
player.setx(old_x)

set mouse cursor position as objects heading

I want to set object u1's heading by the mouse cursors position inside the window.
import turtle
import pygame
import time
win = turtle.Screen()#window
win.title("eagle.py")
win.setup(1920,1080)
win.bgcolor("black")
win.bgpic("triangle")
c1 = turtle.Turtle()#cloud1
c1.speed(0)
c1.penup()
c1.setposition(-1075, 256)
c1.color("white")
c1.shape("triangle")
c_speed = 1 #cloudspeed
u1 = turtle.Turtle()#user1
mouse_pos = pygame.mouse.get_pos()
u1.shape("triangle")
u1.color("red")
u1.speed(0)
u1.setposition(0,0)
u1.setheading(mouse_pos)
u1.penup()
u_speed = 10 #playerspeed
def u1_r():
x = u1.xcor()
x += u_speed
u1.setx(x)
def u1_l():
x = u1.xcor()
x -= u_speed
u1.setx(x)
def u1_up():
y = u1.ycor()
y += u_speed
u1.sety(y)
def u1_down():
y = u1.ycor()
y -= u_speed
u1.sety(y)
while True:
win.update()
time.sleep(1/160)
c1.setx(c1.xcor() + c_speed)
if c1.xcor() > 1075:
c1.goto(-1075, 256)
win.listen()
win.onkeypress(u1_r, "d")
win.onkeypress(u1_l, "a")
win.onkeypress(u1_up, "w")
win.onkeypress(u1_down, "s")
The program keeps shutting down immediately after running. What have I done wrong?
The fact that you have the following:
win.listen()
win.onkeypress(u1_r, "d")
win.onkeypress(u1_l, "a")
win.onkeypress(u1_up, "w")
win.onkeypress(u1_down, "s")
inside a loop indicates that you don't have a basic understanding of the environment in which you're working. Let's start over, tossing pygame and time and just work within the turtle framework:
from turtle import Screen, Turtle
def player_r():
player.setheading(0)
player.setx(player.xcor() + player_speed)
def player_l():
player.setheading(180)
player.setx(player.xcor() - player_speed)
def player_up():
player.setheading(90)
player.sety(player.ycor() + player_speed)
def player_down():
player.setheading(270)
player.sety(player.ycor() - player_speed)
def move():
cloud.setx(cloud.xcor() + cloud_speed)
if cloud.xcor() > 940:
cloud.goto(-940, 256)
screen.update()
screen.ontimer(move)
screen = Screen()
screen.setup(1920, 1080)
screen.bgcolor('black')
screen.tracer(False)
cloud = Turtle()
cloud.shape('circle')
cloud.shapesize(1, 3)
cloud.color('white')
cloud.penup()
cloud.setposition(-940, 256)
cloud_speed = 1
player = Turtle()
player.shape('turtle')
player.color('red')
player.penup()
player_speed = 10
screen.onkeypress(player_r, 'd')
screen.onkeypress(player_l, 'a')
screen.onkeypress(player_up, 'w')
screen.onkeypress(player_down, 's')
screen.listen()
move()
screen.mainloop()
In your code, string is in heading. Instead, put variable.
u1 = turtle.Turtle()
mouse_pos = pygame.mouse.get_pos()
u1.heading(mouse_pos) # variable
Edit: This worked for me, triangle moving..
It seems pygame.init() is need at first.
u1.setheading has a number inside, not tuple. This is for angle. (man turtle)
import turtle
import pygame
import time
pygame.init()
win = turtle.Screen()#window
win.title("eagle.py")
win.setup(1920,1080)
win.bgcolor("black")
win.bgpic() # changed
c1 = turtle.Turtle()#cloud1
c1.speed(0)
c1.penup()
c1.setposition(-1075, 256)
c1.color("white")
c1.shape("triangle")
c_speed = 1 #cloudspeed
u1 = turtle.Turtle()#user1
mouse_pos = pygame.mouse.get_pos()
u1.shape("triangle")
u1.color("red")
u1.speed(0)
u1.setposition(0,0)
u1.setheading(0) # to be changed, setheading(int)
u1.penup()
u_speed = 10 #playerspeed
def u1_r():
x = u1.xcor()
x += u_speed
u1.setx(x)
def u1_l():
x = u1.xcor()
x -= u_speed
u1.setx(x)
def u1_up():
y = u1.ycor()
y += u_speed
u1.sety(y)
def u1_down():
y = u1.ycor()
y -= u_speed
u1.sety(y)
while True:
win.update()
time.sleep(1/160)
c1.setx(c1.xcor() + c_speed)
if c1.xcor() > 1075:
c1.goto(-1075, 256)
win.listen()
win.onkeypress(u1_r, "d")
win.onkeypress(u1_l, "a")
win.onkeypress(u1_up, "w")
win.onkeypress(u1_down, "s")
turtle.heading() expects a numeric argument specifying the heading in degrees.
I don't think you can use the pygame and turtle modules at the same time. Both have their own way of drawing graphics and getting the mouse's current position, so theoretically you can use either.
Regardless, of which one you're using, you'll need to compute the heading's angle from the mouse's x, y position.
Here's how to measure the angle to the origin of an x, y position (assuming its x value isn't zero):
import math
x, y = ... # Mouse position.
print(math.degrees(math.atan(y/x)))

Alternative to using turtle.goto() in Python

This program creates a bouncing ball using turtle.goto(), is there an alternative?
from random import *
from turtle import *
from base import vector
# The ball is drawn, the actions are used from the base file
def draw():
ball.move(aim)
x = ball.x
y = ball.y
if x < -200 or x > 200:
aim.x = -aim.x
if y < -200 or y > 200:
aim.y = -aim.y
clear()
# Can this program serve a purpose without it?
goto(x, y)
dot(10, 'blue')
ontimer(draw,50)
Generally, what is the point of having a goto() function?
Yes, you can create a bouncing ball without using turtle.goto(), here's a rough example:
from turtle import Screen, Turtle
def draw():
ball.forward(10)
x, y = ball.position()
if not (-200 < x < 200 and -200 < y < 200):
ball.undo() # undo 'forward()'
ball.setheading(ball.heading() + 90)
ball.forward(10)
screen.update()
screen.ontimer(draw, 50)
screen = Screen()
screen.tracer(False)
box = Turtle('square')
box.hideturtle()
box.fillcolor('white')
box.shapesize(20)
box.stamp()
ball = Turtle('circle')
ball.color('blue')
ball.setheading(30)
ball.penup()
draw()
screen.exitonclick()

Ball bounce in pong

I have written some code but can't get the ball to bounce on the floor or the ceiling naturally. Please help!
I've already tried getting the ball heading with ball_heading = ball.heading, but that didn't work
#Python 3.6.3
from turtle import *
import math
import random
#Screen Setup
bgcolor("black")
wn = Screen()
wn.title("Pong")
#Drawing Border
bd = Turtle()
bd.pencolor("white")
bd.pensize(3)
bd.hideturtle()
bd.penup()
bd.setposition(-400, -300)
bd.pendown()
bd.speed(0)
bd.pendown()
for line in range(2):
bd.forward(800)
bd.left(90)
bd.forward(600)
bd.left(90)
bd.penup()
bd.setposition(0, 300)
bd.setheading(270)
bd.pendown()
for dash in range(30):
bd.forward(10)
bd.penup()
bd.forward(10)
bd.pendown()
#Creating Paddles
#Paddle 1
player1 = Turtle()
player1.color("white")
player1.shape("square")
player1.shapesize(stretch_wid=5, stretch_len=1)
player1.penup()
player1.setposition(-370, 0)
#Paddle 2
player2 = Turtle()
player2.color("white")
player2.shape("square")
player2.shapesize(stretch_wid=5, stretch_len=1)
player2.penup()
player2.setposition(370, 0)
#Creating the ball
ball = Turtle()
ball.color("white")
ball.shape("square")
ball.speed(0)
ball.penup()
ball.setposition(0, 0)
ball.setheading(random.randint(0, 360))
#Moving the player
playerspeed = 15
#p1
def move_up():
y = player1.ycor()
y += playerspeed
#Setting the boundries
if y > 245:
y = 245
player1.sety(y)
def move_down():
y = player1.ycor()
y -= playerspeed
#Setting the boundries
if y < -245:
y = -245
player1.sety(y)
#p2
def move_up2():
y = player2.ycor()
y += playerspeed
#Setting the boundries
if y > 245:
y = 245
player2.sety(y)
def move_down2():
y = player2.ycor()
y -= playerspeed
#Setting the boundries
if y < -245:
y = -245
player2.sety(y)
#Ball movement
def ball_fd():
ball.forward(3)
#Ball ceiling / floor bounce
def ball_bounce():
by = ball.ycor()
if by > 279:
by = 279
ball.sety(by)
bx = ball.ycor()
if bx < -279:
bx = -279
ball.setx(bx)
#binding
listen()
onkey(move_up, "Up")
onkey(move_down, "Down")
onkey(move_up2, "w")
onkey(move_down2, "s")
#Making the ball move / main game loop
while True:
ball_fd()
ball_bounce()
Sorry the code is kind of long, but feel free to copy + paste it into IDLE or whatever.
Thank you
You didn't turn the ball when it hit the floor or ceiling.
while True:
ball.fd(3)
by = ball.ycor()
if abs(by) > 279:
ball.setheading(-ball.heading())

When I make 2 turtles collide, Python freezes and crashes

import turtle
import os
import math
ms = turtle.Screen()
ms.bgcolor("grey")
ms.title("ok")
ground = turtle.Turtle()
ground.speed(0)
ground.color("black")
ground.penup()
ground.setposition(-500, -500)
ground.shape("square")
ground.shapesize(20, 200)
player = turtle.Turtle()
player.shape("square")
player.color("blue")
player.penup()
player.speed(0)
player.setposition(-450, -280)
playerspeed = 15
prop = turtle.Turtle()
prop.speed(0)
prop.shape("square")
prop.penup()
prop.color("red")
prop.setposition(-200, -50)
def move_left():
x = player.xcor()
x-= playerspeed
if x <-460:
x = - 460
player.setx(x)
def move_right():
x = player.xcor()
x+= playerspeed
if x >460:
x = 460
player.setx(x)
def move_down():
y = player.ycor()
y-= playerspeed
if y <-290:
y = - 290
player.sety(y)
def move_up():
y = player.ycor()
y+= playerspeed
if y >290:
y = 290
player.sety(y)
turtle.listen()
turtle.onkey(move_left, "Left")
turtle.onkey(move_right, "Right")
turtle.onkey(move_up, "Up")
turtle.onkey(move_down, "Down")
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor() - t2.xcor(), 2) + math.pow(t1.ycor() - t2.ycor(), 2))
if distance < 10:
return True
else:
return False
while True:
if isCollision(player, prop):
player.setposition(100, 100)
If I change the distance to > 10
it works but not as I want it to.
I want it to change the position of the player when prop and player are 10 pixels or less away from each other.
I've tried most things I know about, but I am still new to Python, or any programming language.
But I don't know what would cause it to freeze and crash -- any help is appreciated.
The primary issue I see with your code is while True: which shouldn't be used in an event-based environment. By creating a tight loop, you can keep events (key pressed, cursor movements, window closing) from being processed.
Below is a rework of your code using a timer event instead of while True:. I've also parameterized it as every turtle user sees a different size default window based on the dimensions of their screen. So you either need to use setup() to force a fixed size window or have your code adust to the window size. Now it adjusts to the window size. I've also made prop move to a random location upon collision, just to make the game more fun for me to play. And I've tossed your distance code in favor of turtle's own implementation:
from turtle import Screen, Turtle, mainloop
from random import randint
PLAYER_SPEED = 15
GROUND_HEIGHT = 100
PROXIMITY = 10
CURSOR_SIZE = 20
def move_left():
x = player.xcor() - PLAYER_SPEED
if x < CURSOR_SIZE - width/2:
x = CURSOR_SIZE - width/2
player.setx(x)
def move_right():
x = player.xcor() + PLAYER_SPEED
if x > width/2 - CURSOR_SIZE:
x = width/2 - CURSOR_SIZE
player.setx(x)
def move_down():
y = player.ycor() - PLAYER_SPEED
if y < CURSOR_SIZE/2 + GROUND_HEIGHT - height/2:
y = CURSOR_SIZE/2 + GROUND_HEIGHT - height/2
player.sety(y)
def move_up():
y = player.ycor() + PLAYER_SPEED
if y > height/2 - CURSOR_SIZE:
y = height/2 - CURSOR_SIZE
player.sety(y)
def isCollision(t1, t2):
return t1.distance(t2) < PROXIMITY
def random_position():
x = randint(CURSOR_SIZE - width//2, width//2 - CURSOR_SIZE)
y = randint(CURSOR_SIZE + GROUND_HEIGHT - height//2, height//2 - CURSOR_SIZE)
return x, y
def check():
if isCollision(player, prop):
prop.setposition(random_position())
ms.ontimer(check, 100)
ms = Screen()
ms.bgcolor('grey')
ms.title("ok")
width, height = ms.window_width(), ms.window_height()
ground = Turtle('square')
ground.shapesize(GROUND_HEIGHT / CURSOR_SIZE, width / CURSOR_SIZE)
ground.speed('fastest')
ground.penup()
ground.sety(GROUND_HEIGHT/2 - height/2)
player = Turtle('square')
player.speed('fastest')
player.color('blue')
player.penup()
player.setposition(CURSOR_SIZE/2 - width/2, GROUND_HEIGHT + CURSOR_SIZE/2 - height/2)
prop = Turtle('square')
prop.speed('fastest')
prop.color('red')
prop.penup()
prop.setposition(random_position())
ms.onkey(move_left, 'Left')
ms.onkey(move_right, 'Right')
ms.onkey(move_up, 'Up')
ms.onkey(move_down, 'Down')
ms.listen()
check()
mainloop()

Categories