<commit_before>//
// breakout.c
//
// Computer Science 50
// Problem Set 4
//

// standard libraries
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// Stanford Portable Library
#include "gevents.h"
#include "gobjects.h"
#include "gwindow.h"

// height and width of game's window in pixels
#define HEIGHT 600
#define WIDTH 400

// number of rows of bricks
#define ROWS 5

// number of columns of bricks
#define COLS 10

// radius of ball in pixels
#define RADIUS 10

// lives
#define LIVES 3

// prototypes
void initBricks(GWindow window);
GOval initBall(GWindow window);
GRect initPaddle(GWindow window);
GLabel initScoreboard(GWindow window);
void updateScoreboard(GWindow window, GLabel label, int points);
GObject detectCollision(GWindow window, GOval ball);

int main(void)
{
    // seed pseudorandom number generator
    srand48(time(NULL));

    // instantiate window
    GWindow window = newGWindow(WIDTH, HEIGHT);

    // instantiate bricks
    initBricks(window);

    // instantiate ball, centered in middle of window
    GOval ball = initBall(window);

    // instantiate paddle, centered at bottom of window
    GRect paddle = initPaddle(window);

    // instantiate scoreboard, centered in middle of window, just above ball
    GLabel label = initScoreboard(window);

    // number of bricks initially
    int bricks = COLS * ROWS;

    // number of lives initially
    int lives = LIVES;

    // number of points initially
    int points = 0;

    // keep playing until game over
    while (lives > 0 && bricks > 0)
    {
        // TODO
    }

    // wait for click before exiting
    waitForClick();

    // game over
    closeGWindow(window);
    return 0;
}

/**
 * Initializes window with a grid of bricks.
 */
void initBricks(GWindow window)
{
    // TODO
}

/**
 * Instantiates ball in center of window.  Returns ball.
 */
GOval initBall(GWindow window)
{
    // TODO
    return NULL;
}

/**
 * Instantiates paddle in bottom-middle of window.
 */
GRect initPaddle(GWindow window)
{
    // TODO
    return NULL;
}

/**
 * Instantiates, configures, and returns label for scoreboard.
 */
GLabel initScoreboard(GWindow window)
{
    // TODO
    return NULL;
}

/**
 * Updates scoreboard's label, keeping it centered in window.
 */
void updateScoreboard(GWindow window, GLabel label, int points)
{
    // update label
    char s[12];
    sprintf(s, "%i", points);
    setLabel(label, s);

    // center label in window
    double x = (getWidth(window) - getWidth(label)) / 2;
    double y = (getHeight(window) - getHeight(label)) / 2;
    setLocation(label, x, y);
}

/**
 * Detects whether ball has collided with some object in window<commit_msg>Complete Problem Set 4<commit_after>//
// breakout.c
//
// Computer Science 50
// Problem Set 4
//

// standard libraries
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// Stanford Portable Library
#include "gevents.h"
#include "gobjects.h"
#include "gwindow.h"

// height and width of game's window in pixels
#define HEIGHT 600
#define WIDTH 400

// number of rows of bricks
#define ROWS 7

// number of columns of bricks
#define COLS 10

// radius of ball in pixels
#define RADIUS 10

// lives
#define LIVES 3

#define PADDLE_WIDTH 80
#define PADDLE_HEIGHT 10

// prototypes
void initBricks(GWindow window);
GOval initBall(GWindow window);
GRect initPaddle(GWindow window);
GLabel initScoreboard(GWindow window);
void updateScoreboard(GWindow window, GLabel label, int points);
GObject detectCollision(GWindow window, GOval ball);

double getRandomVelocity(void);

int main(void)
{
    // seed pseudorandom number generator
    srand48(time(NULL));

    // instantiate window
    GWindow window = newGWindow(WIDTH, HEIGHT);

    // instantiate bricks
    initBricks(window);

    // instantiate ball, centered in middle of window
    GOval ball = initBall(window);

    // instantiate paddle, centered at bottom of window
    GRect paddle = initPaddle(window);

    // instantiate scoreboard, centered in middle of window, just above ball
    GLabel label = initScoreboard(window);

    // number of bricks initially
    int bricks = COLS * ROWS;

    // number of lives initially
    int lives = LIVES;

    // number of points initially
    int points = 0;

    double x_velocity = getRandomVelocity();
    double y_velocity = 0.05;

    GObject collision;

    char label_text[20];
    snprintf(label_text, 20, "Score: %d", points);
    setLabel(label, label_text);

    waitForClick();

    // keep playing until game over
    while (lives > 0 && bricks > 0) {

        move(ball, x_velocity, y_velocity);

        collision = detectCollision(window, ball);

        if (getX(ball) + getWidth(ball) >= getWidth(window))
            x_velocity *= -1;
        else if (getX(ball) <= 0)
            x_velocity *= -1;

        if (collision == paddle)
            y_velocity *= -1;
        else if (collision != NULL && strcmp(getType(collision), "GRect") == 0) {
            bricks--;
            points++;
            snprintf(label_text, 10, "Score: %d", points);
            setLabel(label, label_text);
            y_velocity *= -1;
            removeGWindow(window, collision);
        }

        if (getY(ball) + getHeight(ball) >= getHeight(window)) {
            lives--;
            if (lives == 0)
                break;
            setLocation(ball, (WIDTH - RADIUS)/2, (HEIGHT - RADIUS)/2);
            x_velocity = getRandomVelocity();
            waitForClick();
        } else if (getY(ball) <= 0)
            y_velocity *= -1;

        GEvent event = getNextEvent(MOUSE_EVENT);

        if (event != NULL) {
            if (getEventType(event) == MOUSE_MOVED) {
                double x = getX(event) - PADDLE_WIDTH/2;
                double y = getY(paddle);
                if (x >= 0 && x + PADDLE_WIDTH <= WIDTH)
                    setLocation(paddle, x, y);
            }
        }
    }

    // wait for click before exiting
    waitForClick();

    // game over
    closeGWindow(window);
    return 0;
}

double getRandomVelocity(void)
{
    return (drand48()/5 - 0.1);
}

/**
 * Initializes window with a grid of bricks.
 */
void initBricks(GWindow window)
{
    int num_colors = 5;
    string colors[num_colors];
    colors[0] = "RED";
    colors[1] = "ORANGE";
    colors[2] = "YELLOW";
    colors[3] = "GREEN";
    colors[4] = "CYAN";
    int gap = 10;
    int brick_width = (WIDTH - gap*(COLS + 1))/COLS;
    int brick_height = 20;
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            GRect brick = newGRect(gap*(j + 1) + brick_width*j, gap*(i + 1) + brick_height*i, brick_width, brick_height);
            setColor(brick, colors[i%num_colors]);
            setFilled(brick, true);
            add(window, brick);
        }
    }
}

/**
 * Instantiates ball in center of window.  Returns ball.
 */
GOval initBall(GWindow window)
{
    GOval ball = newGOval((WIDTH - RADIUS)/2, (HEIGHT - RADIUS)/2, RADIUS, RADIUS);
    setColor(ball, "BLUE");
    setFilled(ball, true);
    add(window, ball);
    return ball;
}

/**
 * Instantiates paddle in bottom-middle of window.
 */
GRect initPaddle(GWindow window)
{
    GRect paddle = newGRect(WIDTH/2 - PADDLE_WIDTH/2, HEIGHT - 80, PADDLE_WIDTH, PADDLE_HEIGHT);
    setColor(paddle, "BLACK");
    setFilled(paddle, true);
    add(window, paddle);
    return paddle;
}

/**
 * Instantiates, configures, and returns label for scoreboard.
 */
GLabel initScoreboard(GWindow window)
{    
    GLabel label = newGLabel("");
    setFont(label, "SansSerif-24");
    setLocation(label, 8, HEIGHT - 10);
    add(window, label);
    return label;
}

/**
 * Updates scoreboard's label, keeping it centered in window.
 */
void updateScoreboard(GWindow window, GLabel label, int points)
{
    // update label
    char s[12];
    sprintf(s, "%i", points);
    setLabel(label, s);

    // center label in window
    double x = (getWidth(window) - getWidth(label)) / 2;
    double y = (getHeight(window) - getHeight(label)) / 2;
    setLocation(label, x, y);
}

/**
 * Detects whether ball has collided with some object in window
{'fraction_non_alphanumeric': 0.11962890625, 'fraction_numerical': 0.01318359375, 'mean_word_length': 2.6690550828481863, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3988655', 'n_tokens_mistral': 2781, 'n_tokens_neox': 2571, 'n_words': 794}