LWJGL Pong paddle AI boundary detection fails with random movement

I’m working on a Pong game using Java and LWJGL and having trouble with my AI paddle logic. When I use fixed movement speed, everything works perfectly and the paddle respects screen boundaries. But as soon as I add random speed variation, the boundary checking breaks.

Working version with fixed speed:

public void movePaddle(int ballPosition, int screenHeight, int paddleSize) {
    if (ballPosition < this.position + height / 2) {
        if (this.position <= 0) {
            System.out.println("Hit top wall");
            position = 0;
        } else {
            position -= 2;
        }
    }
    if (ballPosition > this.position + height / 2) {
        if (this.position >= screenHeight - paddleSize) {
            System.out.println("Hit bottom wall");
            position = screenHeight - paddleSize;
        } else {
            position += 2;
        }
    }
}

Broken version with random speed:

public void movePaddle(int ballPosition, int screenHeight, int paddleSize) {
    if (ballPosition < this.position + height / 2) {
        if (this.position <= 0) {
            System.out.println("Hit top wall");
            position = 0;
        } else {
            if(random.nextInt(2) + 1 == 1){
                position -= 2;
            } else {
                position -= 3;
            }
        }
    }
    // bottom movement logic stays the same
}

The random version works once but then the paddle goes off-screen and ignores boundaries completely. The console still shows the correct position values though. I want to make the AI sometimes move faster or slower for variety. What am I doing wrong here?

Your boundary checks run first, but then the random movement pushes the paddle past those boundaries in the same frame. I hit this exact issue in a breakout clone when I added variable speeds - the paddle kept clipping through walls. Here’s what fixed it: calculate the new position first, then check if it’s valid before moving. Store your random speed in a variable, figure out where you’d end up (currentPosition + speed), then check if that spot is within bounds. Only move there if it passes the test, otherwise clamp it to the screen edge. Your console shows correct values because the boundary code runs and prints first, but the random movement overwrites the position right after the check happens.