1
\$\begingroup\$

I know my code is ugly and unreadable. I originally had the game working without class functions but when I had to implement class function it all went downhill.

TennisMaster.py

import random
import time
import pygame
import Menu
from RunningGame import *
class TennisMaster(RunningGame):
    def __init__(self):
        self.screen_height_and_width=TennisMaster.sizeCheck()
        self.imagesDirectory="images/"
        self.screen=pygame.display.set_mode((self.screen_height_and_width,self.screen_height_and_width))
        TennisMaster.setUp(self)
    def setUp(self):
        screen=self.screen
        screen_height_and_width=self.screen_height_and_width
        pygame.font.init()
        
        screen.fill((255,255,255))
        Menu.startAnimation(self,screen,screen_height_and_width)

        TennisMaster.clearBackground(self)
        map=Menu.mapSelection(self,screen,screen_height_and_width)
        print(str(map)+".png <====")

        bg = pygame.image.load(self.imagesDirectory+str(map)+".png")
        screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
        pygame.display.update()
        powerUps=Menu.powerUpSelection(self)
        score=0
        RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)

    def clearBackground(self):
        screen=self.screen
        screen_height_and_width=self.screen_height_and_width
        bg = pygame.image.load(self.imagesDirectory+"whiteImage.png")
        screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
        pygame.display.update()
    def sizeCheck():
        return(800)
TennisMaster()

Menu.py

import random
import time
import pygame
class Menu():
    def __init__(screen,screen_height_and_width):
        self.screen=screen
        self.screen_height_and_width=screen_height_and_width
        self.imagesDirectory="images/"
    def powerUpSelection(self):
        screen=self.screen
        screen_height_and_width=self.screen_height_and_width
        with open("score.txt","r") as scoreFile:
            scoreText=scoreFile.read()
        highScore=max(Menu.Convert_To_List(self,scoreText))
        print(highScore,'<---')
        clear = pygame.image.load(self.imagesDirectory+"whiteImage.png")
        screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
        if highScore<20:
            powerUpSelection = pygame.image.load(self.imagesDirectory+"powerUp-1.png")
        elif highScore<30 and highScore>=20:
            powerUpSelection = pygame.image.load(self.imagesDirectory+"powerUp-2.png")
        elif highScore<40 and highScore>=30:
            powerUpSelection = pygame.image.load(self.imagesDirectory+"powerUp-3.png")
        elif highScore<60 and highScore>=40:
            powerUpSelection = pygame.image.load(self.imagesDirectory+"powerUp-4.png")
        elif highScore>=60 or highScore==60:
            powerUpSelection = pygame.image.load(self.imagesDirectory+"powerUp-5.png")
        
        screen.blit(pygame.transform.scale(powerUpSelection,(screen_height_and_width,screen_height_and_width)), (0, 0))
        pygame.display.update()
        working=True
        while working:
            for event in pygame.event.get():  
                if event.type == pygame.KEYDOWN:
                    if event.key==49:#49 for 1
                        print("scoreBoost")
                        return("scoreBoost")
                    elif event.key==50 and highScore>=15:#50 for 2
                        print("biggerHitbox")
                        return("biggerHitbox")
                    elif event.key==51 and highScore>=25:#51 for 3
                        print("ballSlow")
                        return("ballSlow")
                    elif event.key==52 and highScore>=35:#51 for 3
                        print("directionHint")
                        return("directionHint")
                    elif event.key==53 and highScore>=50:#51 for 3
                        print("extraLife")
                        return("extraLife")
                    else:
                        print("fail")
                elif event.type == pygame.QUIT:
                        pygame.quit()
                        exit()

        #bigger hitbox
        #slow down
        #extra life
        # score boost   every 5 balls you gain an extra point
        #direction hint
        #if you get a highscore of 75 you have an option to level up a power boost
        
    def mapSelection(self,screen,screen_height_and_width):
        screen=self.screen
        screen_height_and_width=self.screen_height_and_width
        with open("score.txt","r") as scoreFile:
            scoreText=scoreFile.read()
        totalScore=int(Menu.totalScores(Menu.Convert_To_List(self,scoreText)))
        clear = pygame.image.load(self.imagesDirectory+"whiteImage.png")
        screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
        if totalScore<250:
            mapSelectionBG = pygame.image.load(self.imagesDirectory+"mapselection-1.png")
        elif totalScore<500:
            mapSelectionBG = pygame.image.load(self.imagesDirectory+"mapselection-2.png")
        else:
            mapSelectionBG = pygame.image.load(self.imagesDirectory+"mapselection-3.png")

        screen.blit(pygame.transform.scale(mapSelectionBG,(screen_height_and_width,screen_height_and_width)), (0, 0))
        pygame.display.update()
        working=True
        while working:
            for event in pygame.event.get():  
                if event.type == pygame.KEYDOWN:
                    totalScore=int(totalScore)
                    print(totalScore,"\n",event.key)
                    if event.key==49:#49 for 1
                        print("test map 1")
                        return("map1")
                    elif event.key==50 and totalScore>=250:#50 for 2
                        print("test map 2")
                        return("map2")
                    elif event.key==51 and totalScore>=500:#51 for 3
                        print("test map 3")
                        return("map3")
                    else:
                        print("failed")
                elif event.type == pygame.QUIT:
                        pygame.quit()
                        exit()
    def Convert_To_List(self, scoreText):
        newList=[]
        eachScore=""
        for letter in list(scoreText):
            if letter == ",":
                if eachScore!="":
                    newList.append(int(eachScore))
                eachScore=""
            else:
                eachScore=eachScore+str(int(letter))
        return(newList)
    def totalScores(scoreFile):
        totalScoreNumber=0
        for number in scoreFile:
            if number!=1:
                totalScoreNumber+=number
        return(totalScoreNumber)
    def startAnimation(self,screen,screen_height_and_width):
        screen=self.screen
        screen_height_and_width=self.screen_height_and_width
        bg = pygame.image.load(self.imagesDirectory+"startAnimation.png")
        screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
        working=0
        pygame.display.update()
        while working==0:
            for event in pygame.event.get():

                if event.type == pygame.KEYDOWN:
                    print("key hit")
                    working=1
                elif event.type == pygame.QUIT:
                    pygame.quit()
                    exit()

RunningGame.py

import random
import time
import pygame
import TennisMaster #if i have this it breaks
from Menu import *
class RunningGame:
    def __init__(direction,screen,screen_height_and_width,score,map,powerUps):
        self.direction=direction
        self.screen=screen
        self.screen_height_and_width=screen_height_and_width
        self.score=score
        self.map=map 
        self.powerUps=powerUps
    def imagesDirectory():
        return("images/")
    def tennisBall(direction,screen,screen_height_and_width,score,map,powerUps):
        backwards=False
        working=True
        slowdown=0
        speed=12-slowdown+score*0.5
        speed=int(speed)
        if powerUps=="scoreBoost" and speed%4==0:
            score+=1
        elif powerUps=="ballSlow":
            slowdown=2
        score+=1
        if powerUps=="biggerHitbox":
            biggerHitbox=True
        else:
            biggerHitbox=False
        if direction=="left":
            x=int(screen_height_and_width/160)
            y=int(screen_height_and_width/2-int(screen_height_and_width/22))
            ball = pygame.image.load(RunningGame.imagesDirectory()+"tennisball.png")
            clear = pygame.image.load(RunningGame.imagesDirectory()+"whiteImage.png")
            bg = pygame.image.load(RunningGame.imagesDirectory()+str(map)+"-left.png")
            start=int(screen_height_and_width/160)
            while working:
                screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
                screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
                screen.blit(pygame.transform.scale(ball,(int(screen_height_and_width/10),int(screen_height_and_width/10))), (x,y))
                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                pygame.display.update()
                time.sleep(0.005)
                x+=speed

                for event in pygame.event.get():  
                    if event.type == pygame.KEYDOWN:
                        if event.key==pygame.K_a or event.key==1073741904: #97 = a
                            if x>200 and x<400: 
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            elif powerUps=="extraLife":
                                powerUps=""
                                time.sleep(0.5)
                                print("extra life over")
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            elif biggerHitbox and x>150 and x<450:
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            else:
                                
                                RunningGame.failScreen(screen,screen_height_and_width,score)

                        else:
                            RunningGame.failScreen(screen,screen_height_and_width,score)
                    elif event.type == pygame.QUIT:
                        pygame.quit()
                        exit()
                    if x<screen_height_and_width/160:
                        screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
                        screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
                        working=False
                    if backwards:
                        if speed>0:
                            speed=(speed*-1)*2
        if direction=="right":
            x=int(screen_height_and_width-screen_height_and_width/160)
            y=int(screen_height_and_width/2-int(screen_height_and_width/22))
            ball = pygame.image.load(RunningGame.imagesDirectory()+"tennisball.png")
            clear = pygame.image.load(RunningGame.imagesDirectory()+"whiteImage.png")
            bg = pygame.image.load(RunningGame.imagesDirectory()+str(map)+"-right.png")
            start=int(screen_height_and_width/160)
            while working:
                screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
                screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))

                screen.blit(pygame.transform.scale(ball,(int(screen_height_and_width/10),int(screen_height_and_width/10))), (x,y))
                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                pygame.display.update()
                time.sleep(0.005)
                x-=speed
                for event in pygame.event.get():  
                    if event.type == pygame.KEYDOWN:
                        if event.key==100 or event.key==1073741903:#100 = d
                            if x<600 and x>400: 
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            elif powerUps=="extraLife":
                                powerUps=""
                                time.sleep(0.5)
                                print("extra life over")
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            elif biggerHitbox and x<650 and x<350:
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            else:
                                
                                RunningGame.failScreen(screen,screen_height_and_width,score)
                        else:
                            RunningGame.failScreen(screen,screen_height_and_width,score)
                    elif event.type == pygame.QUIT:
                        pygame.quit()
                        exit()
                    if x<screen_height_and_width/160:
                        screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
                        screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
                        working=False
                    if backwards:
                        if speed>0:
                            speed=(speed*-1)*2

        if direction=="up":
            x=int(screen_height_and_width/2-screen_height_and_width/20)
            y=int(int(screen_height_and_width/80))
            ball = pygame.image.load(RunningGame.imagesDirectory()+"tennisball.png")
            clear = pygame.image.load(RunningGame.imagesDirectory()+"whiteImage.png")

            bg = pygame.image.load(RunningGame.imagesDirectory()+str(map)+"-up.png")
            start=int(screen_height_and_width/160)
            while working:
                screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
                screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
                screen.blit(pygame.transform.scale(ball,(int(screen_height_and_width/10),int(screen_height_and_width/10))), (x,y))
                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                pygame.display.update()
                time.sleep(0.005)
                y+=speed

                for event in pygame.event.get():  
                    if event.type == pygame.KEYDOWN:
                        if event.key==119 or event.key == 1073741906:#199 = w
                            if y>200 and y<400: 
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            elif powerUps=="extraLife":
                                powerUps=""
                                time.sleep(0.5)
                                print("extra life over")
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            elif biggerHitbox and y>150 and y<450:
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            else:
                                RunningGame.failScreen(screen,screen_height_and_width,score)
                        else:
                            RunningGame.failScreen(screen,screen_height_and_width,score)
                    elif event.type == pygame.QUIT:
                        pygame.quit()
                        exit()
                    if x<screen_height_and_width/160:
                        screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
                        screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
                        working=False
                    if backwards:
                        if speed>0:
                            speed=(speed*-1)*2
        if direction=="down":
            x=int(screen_height_and_width/2-screen_height_and_width/20)
            y=int(int(screen_height_and_width-screen_height_and_width/80))
            ball = pygame.image.load(RunningGame.imagesDirectory()+"tennisball.png")
            clear = pygame.image.load(RunningGame.imagesDirectory()+"whiteImage.png")
            bg = pygame.image.load(RunningGame.imagesDirectory()+str(map)+"-down.png")
            start=int(screen_height_and_width/160)
            while working:
                screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
                screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
                screen.blit(pygame.transform.scale(ball,(int(screen_height_and_width/10),int(screen_height_and_width/10))), (x,y))
                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                pygame.display.update()
                time.sleep(0.005)
                y-=speed
                for event in pygame.event.get():  
                    if event.type == pygame.KEYDOWN:
                        if event.key==115 or event.key==1073741905:#115 = a
                            if y<600 and y>400: 
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            elif powerUps=="extraLife":
                                time.sleep(0.5)
                                powerUps=""
                                print("extra life over")
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            elif biggerHitbox and y<650 and y>350:
                                backwards=True
                                RunningGame.scoreBoard(screen,screen_height_and_width,score)
                                RunningGame.NextBall(screen,screen_height_and_width,score,map,powerUps)
                            else:
                                RunningGame.failScreen(screen,screen_height_and_width,score)
                        else:
                            RunningGame.failScreen(screen,screen_height_and_width,score)
                    elif event.type == pygame.QUIT:
                            pygame.quit()
                            exit()
                    if x<screen_height_and_width/160:
                        screen.blit(pygame.transform.scale(clear,(screen_height_and_width,screen_height_and_width)), (0, 0))
                        screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
                        working=False
                    if backwards:
                        if speed>0:
                            speed=(speed*-1)*2


    def NextBall(screen,screen_height_and_width,score,map,powerUps):
        newDirection=random.randint(1,4)
        #2 and 4 dont work
        if powerUps=="directionHint":
            if newDirection==1:
                x=int(screen_height_and_width/160)
                y=int(screen_height_and_width/2-int(screen_height_and_width/22))
                arrow=pygame.image.load(RunningGame.imagesDirectory()+"leftArrow.png")
            if newDirection==2:
                x=int(screen_height_and_width-screen_height_and_width/160-82)
                y=int(screen_height_and_width/2-int(screen_height_and_width/22))
                arrow=pygame.image.load(RunningGame.imagesDirectory()+"rightArrow.png")
                print(arrow)
            if newDirection==3:
                x=int(screen_height_and_width/2-screen_height_and_width/20)
                y=int(int(screen_height_and_width/80))
                arrow=pygame.image.load(RunningGame.imagesDirectory()+"upArrow.png")
                
            if newDirection==4:
                x=int(screen_height_and_width/2-screen_height_and_width/20)
                y=int(int(screen_height_and_width-screen_height_and_width/80)-82)
                arrow=pygame.image.load(RunningGame.imagesDirectory()+"downArrow.png")
                pygame.display.update()
            screen.blit(pygame.transform.scale(arrow,(int(screen_height_and_width/10),int(screen_height_and_width/10))), (x,y))
            pygame.display.update()
            time.sleep(0.05)
        if newDirection==1:
            RunningGame.tennisBall("left",screen,screen_height_and_width,score,map,powerUps)
        elif newDirection==2:
            RunningGame.tennisBall("right",screen,screen_height_and_width,score,map,powerUps)
        
        elif newDirection==3:
            RunningGame.tennisBall("up",screen,screen_height_and_width,score,map,powerUps)

        elif newDirection==4:
            RunningGame.tennisBall("down",screen,screen_height_and_width,score,map,powerUps)
    def Convert_To_List(scoreText):
        newList=[]
        eachScore=""
        for letter in list(scoreText):
            if letter == ",":
                if eachScore!="":
                    newList.append(int(eachScore))
                eachScore=""
            else:
                eachScore=eachScore+str(int(letter))
        return(newList)
    def scoreBoard(screen,screen_height_and_width,score):
        if score>100000000000000000000000000000000000000000000:
            score-=100000000000000000000000000000000000000000000
            myfont = pygame.font.SysFont('Comic Sans MS', 100)
            bigfont = pygame.font.SysFont('They definitely dont have this installed Gothic', 120)
            textsurface = myfont.render(str(score), False, (0, 0, 0))
            if score>=10:
                screen.blit(textsurface,(145,270))
            else:
                screen.blit(textsurface,(179,270))
                
            with open("score.txt","r") as scoreFile:
                scoreText=scoreFile.read()
                highScore=max(RunningGame.Convert_To_List(scoreText))
                textsurface = myfont.render(''+str(highScore), False, (0, 0, 0))
                if highScore>=10:
                    screen.blit(textsurface,(541,270))
                else:
                    screen.blit(textsurface,(570,270))
                if highScore<score:
                    textsurface = bigfont.render("New Highscore", False, (0, 0, 0))
                    screen.blit(pygame.transform.scale(textsurface,(600,110)), (100, 415))
        else:
            myfont = pygame.font.SysFont('Comic Sans MS', 50)
            textsurface = myfont.render("Score: "+str(score), False, (0, 0, 0))
            if score>=10:
                screen.blit(textsurface,(10,10))
            else:
                screen.blit(textsurface,(10,10))

        
        pygame.display.update()
    def clearBackground(screen,screen_height_and_width):
        bg = pygame.image.load(RunningGame.imagesDirectory()+"whiteImage.png")
        screen.blit(pygame.transform.scale(bg,(screen_height_and_width,screen_height_and_width)), (0, 0))
        pygame.display.update()
    def failScreen(screen,screen_height_and_width,score):
        score+=100000000000000000000000000000000000000000000
        failPanel = pygame.image.load(RunningGame.imagesDirectory()+"failScreen.png")
        screen.blit(pygame.transform.scale(failPanel,(screen_height_and_width,screen_height_and_width)), (0, 0))
        
        with open("score.txt", "a") as scoreFile:
            scoreFile.write(","+str(score-100000000000000000000000000000000000000000000))
        RunningGame.scoreBoard(screen,screen_height_and_width,score)
        pygame.display.update() 
        time.sleep(2.5)
        TennisMaster.setUp()
    def totalScores(scoreFile):
        totalScoreNumber=0
        for number in scoreFile:
            if number!=1:
                totalScoreNumber+=number
        return(totalScoreNumber)
    def sizeCheck():
        '''
        sizeOptions=int(input("Pick your resolution\n1 for 1080p\n2 for 2k\n4 for 4k\n"))
        if sizeOptions==1:
            return(800)
        elif sizeOptions==2:
            return(1400)
        elif sizeOptions==4:
            return(1900)
        else:
            print("You Failed Basic Directions")
            return(1)
        '''
        return(800)
```
\$\endgroup\$
4

1 Answer 1

3
\$\begingroup\$

I took a preliminary look at your code. Here are some basic tips:

1. Include a link to a repo hosting site.

You've got multiple files. You've got image resources. You've got code that computes the names of the images it wants to load!

This is all smooth and sophisticated, but not if I can't play along...

I want to be able to see your code the way you have it structured. It won't hurt to show me setting for things like what version of python you are using, etc., which may be in the various config files.

2. Black it.

There are a lot of code reformatting tools out there. Right now, you are obviously not using one. So install black and run it on your code.

Why black? Because it works directly and doesn't mess around with too much configuration. You won't spend a week "tweaking my style." Just run the program, and save the result.

3. Reorganize your classes.

You have a RunningGame and a TennisMaster class. I assume this is a tennis game. That would make RunningGame the parent and TennisMaster the child class.

As such, there should be nothing "low level" in Tennis Master. Try to eliminate references to pygame from TennisMaster -- if you have to talk to the support library, that should be a task for the base class. (This may not work if there is some amazing thing that the support library does for the specific subclass. But it's the right attitude to start with - be suspicious of any need to reach too far down. Try to put it in a class or a standalone function.)

Similarly, there should not be a tennisBall method on Running Game. That is either a method in the wrong place, or a method with the wrong name. In this case, I think wrong place.

4. Eliminate magic numbers.

You write:

x = int(screen_height_and_width / 160)                            
y = int(screen_height_and_width / 2 - int(screen_height_and_width / 22))

What do those numbers mean?

Either use named constants, or use named functions (or methods) to describe what you are doing.

x = height // NUM_CELLS_HORIZONTAL

# -OR-

y = self.centerline_bottom()  

5. Stop repeating yourself!

You have (what I hope is) duplicated code in your tennisBall method. In fact, you've got a few copies of a pygame event loop.

First, the loop should be in the top-level function and it should call other things.

Second, don't repeat yourself. If you have multiple copies of code, make a function or method out of them and give it a name. That way, when you add a powerup, you won't have a powerup that only works when the ball is moving right to left.

Edit:

6. Use lowercase file names.

Your python files are named the same as the classes they contain. This is irksome but understandable.

However, you are also using mixed-case file names for your resource files, but you have not actually given the resource files the identically-cased names. For example, 'powerup-3.png' versus "powerUp-3.png".

I suspect you are coding under windows, because under Linux those differences actually matter.

The easiest way to address this is to make yourself a simple rule: always use lowercase filenames unless there is a compelling reason not to. (Example: Java requires matching case.)

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.