commit 1a564b75ca727a47c448df67cbb6cc8ac0f93a01
Author: Hadeed Ahmad <hadeedji@gmail.com>
Date:   Wed Sep 11 22:48:22 2024 +0500

    Initial commit

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3f4bbab
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+build/
+life
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..163d034
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,28 @@
+# Written with extensive help from https://makefiletutorial.com
+
+CC = g++
+
+TARGET_EXEC = life
+
+SRC_DIR = src
+INC_DIR = include
+BUILD_DIR = build
+
+CFLAGS = -I $(INC_DIR) -MMD -MP -I c:/SDL2/include -I c:/SDL2/include/SDL2 -Dmain=SDL_main
+LDFLAGS = -L c:/SDL2/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -static-libstdc++ -static-libgcc
+
+SRC = $(wildcard $(SRC_DIR)/*.cpp)
+OBJ = $(SRC:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o)
+DEP = $(OBJ:%.o=%.d)
+
+$(TARGET_EXEC): $(OBJ)
+	$(CC) $(OBJ) -o $(TARGET_EXEC) $(LDFLAGS)
+
+$(OBJ): $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
+	@mkdir -p $(BUILD_DIR)
+	$(CC) $(CFLAGS) -c $< -o $@
+
+clean:
+	@rm -rf $(BUILD_DIR) $(TARGET_EXEC)
+
+-include $(DEP)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..279a401
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# Game of life
+
+A CS100 project. The git history is lost because the original git repository was deleted, this one was reconstructed from the files I submitted. A compiled version for windows is provided, you can compile for mac and linux using the provided makefile, minor changes to makefile might be required.
diff --git a/include/drawing.h b/include/drawing.h
new file mode 100644
index 0000000..08b0eeb
--- /dev/null
+++ b/include/drawing.h
@@ -0,0 +1,11 @@
+#ifndef DRAWING_H
+#define DRAWING_H
+
+// Public
+void draw();
+
+// Private
+static void draw_grid_lines();
+static void draw_cells();
+
+#endif
diff --git a/include/events.h b/include/events.h
new file mode 100644
index 0000000..875acbb
--- /dev/null
+++ b/include/events.h
@@ -0,0 +1,13 @@
+#ifndef EVENTS_H
+#define EVENTS_H
+
+#include <SDL_events.h>
+
+// Public
+void handle_events();
+
+//Private
+void handle_key_event(SDL_Keycode key_pressed);
+void handle_mouse_event(int x, int y);
+
+#endif
diff --git a/include/game.h b/include/game.h
new file mode 100644
index 0000000..c853edb
--- /dev/null
+++ b/include/game.h
@@ -0,0 +1,13 @@
+#ifndef GAME_H
+#define GAME_H
+
+// Public
+void start_game();
+void toggle_pause();
+
+extern bool paused;
+
+// Private
+static void game_loop();
+
+#endif
diff --git a/include/globals.h b/include/globals.h
new file mode 100644
index 0000000..4eddd18
--- /dev/null
+++ b/include/globals.h
@@ -0,0 +1,17 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#define CELL_SIZE 20
+
+#define GRID_WIDTH 64
+#define GRID_HEIGHT 48
+
+#define WINDOW_WIDTH GRID_WIDTH * CELL_SIZE
+#define WINDOW_HEIGHT GRID_HEIGHT * CELL_SIZE
+
+#define FRAMES_PER_SECOND 60
+#define UPDATES_PER_SECOND 5
+
+#define ALIVE true
+#define DEAD false
+#endif
diff --git a/include/grid.h b/include/grid.h
new file mode 100644
index 0000000..2a68185
--- /dev/null
+++ b/include/grid.h
@@ -0,0 +1,12 @@
+#ifndef GRID_H
+#define GRID_H
+
+#include "globals.h"
+
+// Public
+void clear_grid();
+void iterate_grid();
+
+extern bool grid[GRID_HEIGHT][GRID_WIDTH];
+
+#endif
diff --git a/include/main.h b/include/main.h
new file mode 100644
index 0000000..417678c
--- /dev/null
+++ b/include/main.h
@@ -0,0 +1,14 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <SDL.h>
+
+// Public
+void quit_application(int exit_code);
+
+extern SDL_Window *window;
+
+// Private
+static void init();
+
+#endif
diff --git a/include/timing.h b/include/timing.h
new file mode 100644
index 0000000..2888a47
--- /dev/null
+++ b/include/timing.h
@@ -0,0 +1,9 @@
+#ifndef TIMING_H
+#define TIMING_H
+
+// Public
+void limit_fps();
+
+extern double delta_time;
+
+#endif
diff --git a/src/drawing.cpp b/src/drawing.cpp
new file mode 100644
index 0000000..33a5803
--- /dev/null
+++ b/src/drawing.cpp
@@ -0,0 +1,93 @@
+#include <SDL.h>
+
+#include "drawing.h" // This file
+#include "game.h" // Get paused state
+#include "globals.h" // Size macros
+#include "grid.h" // Get grid state
+#include "main.h" // Get window
+
+void clear_window() {
+    SDL_Surface *surface = SDL_GetWindowSurface(window);
+
+    Uint32 background = SDL_MapRGB(surface->format, 0x2E, 0x34, 0x40);
+
+    SDL_FillRect(surface, NULL, background);
+}
+
+SDL_Surface* grid_lines_surface() {
+    Uint32 rmask, gmask, bmask, amask;
+    rmask = 0xff000000;
+    gmask = 0x00ff0000;
+    bmask = 0x0000ff00;
+    amask = 0x000000ff;
+
+    SDL_Surface *grid_lines = SDL_CreateRGBSurface(0, WINDOW_WIDTH, WINDOW_HEIGHT, 32, rmask, gmask, bmask, amask);
+
+    Uint32 lines_color = SDL_MapRGB(grid_lines->format, 0x3B, 0x42, 0x52);
+
+    SDL_Surface *vertical = SDL_CreateRGBSurface(0, 2, WINDOW_HEIGHT, 32, rmask, gmask, bmask, amask);
+    SDL_FillRect(vertical, NULL, lines_color);
+    for (int i = 0; i <= GRID_WIDTH; i++) {
+        SDL_Rect destination;
+        destination.x = i * CELL_SIZE - 1;
+        destination.y = 0;
+
+        SDL_BlitSurface(vertical, NULL, grid_lines, &destination);
+    } 
+    SDL_FreeSurface(vertical);
+
+    SDL_Surface *horizontal = SDL_CreateRGBSurface(0, WINDOW_WIDTH, 2, 32, rmask, gmask, bmask, amask);
+    SDL_FillRect(horizontal, NULL, lines_color);
+    for (int i = 0; i <= GRID_HEIGHT; i++) {
+        SDL_Rect destination;
+        destination.x = 0;
+        destination.y = i * CELL_SIZE - 1;
+
+        SDL_BlitSurface(horizontal, NULL, grid_lines, &destination);
+    } 
+    SDL_FreeSurface(horizontal);
+
+    return grid_lines;
+}
+
+SDL_Surface* cell_surface() {
+    SDL_Surface *cell = SDL_CreateRGBSurface(0, CELL_SIZE, CELL_SIZE, 32, 0, 0, 0, 0);
+
+    Uint32 cell_color = SDL_MapRGB(cell->format, 0xE5, 0xE9, 0xF0);
+    SDL_FillRect(cell, NULL, cell_color);
+
+    return cell;
+}
+
+void draw() {
+    clear_window();
+
+    draw_cells();
+
+    if (paused) draw_grid_lines();
+
+    SDL_UpdateWindowSurface(window);
+}
+
+void draw_grid_lines() {
+    SDL_Surface *surface = SDL_GetWindowSurface(window);
+    static SDL_Surface *grid_lines = grid_lines_surface();
+
+    SDL_BlitSurface(grid_lines, NULL, surface, &surface->clip_rect);
+}
+
+void draw_cells() {
+    SDL_Surface *surface = SDL_GetWindowSurface(window);
+    static SDL_Surface *cell = cell_surface();
+
+    for (int i = 0; i < GRID_HEIGHT; i++)
+        for (int j = 0; j < GRID_WIDTH; j++) {
+            if (grid[i][j] == ALIVE) {
+                SDL_Rect destination;
+                destination.x = j * CELL_SIZE;
+                destination.y = i * CELL_SIZE;
+
+                SDL_BlitSurface(cell, NULL, surface, &destination);
+            }
+        }
+}
diff --git a/src/events.cpp b/src/events.cpp
new file mode 100644
index 0000000..f64fc9e
--- /dev/null
+++ b/src/events.cpp
@@ -0,0 +1,49 @@
+#include <SDL_events.h>
+
+#include "events.h" // This file
+#include "game.h" // Get and set paused state
+#include "globals.h" // Cell size macros
+#include "grid.h" // Set grid
+#include "main.h" // Quit
+
+void handle_events() {
+    SDL_Event event;
+
+    while (SDL_PollEvent(&event)) {
+        switch (event.type) {
+            case SDL_KEYDOWN:
+                handle_key_event(event.key.keysym.sym);
+                break;
+            case SDL_MOUSEBUTTONDOWN:
+                handle_mouse_event(event.button.x, event.button.y);
+                break;
+            case SDL_QUIT:
+                quit_application(0);
+                break;
+        }
+    }
+}
+
+void handle_key_event(SDL_Keycode key_pressed) {
+    switch (key_pressed) {
+        case SDLK_q:
+            quit_application(0);
+            break;
+        case SDLK_SPACE:
+        case SDLK_RETURN:
+            toggle_pause();
+            break;
+        case SDLK_r:
+              if (paused) clear_grid();
+              break;
+    }
+}
+
+void handle_mouse_event(int x, int y) {
+    if (!paused) return;
+
+    int i = y / CELL_SIZE;
+    int j = x / CELL_SIZE;
+
+    grid[i][j] = !grid[i][j];
+}
diff --git a/src/game.cpp b/src/game.cpp
new file mode 100644
index 0000000..fcdced3
--- /dev/null
+++ b/src/game.cpp
@@ -0,0 +1,43 @@
+#include <SDL.h>
+
+#include "drawing.h" // Draw in game loop
+#include "events.h" // Handle events in loop
+#include "game.h" // This file
+#include "globals.h" // Timing macros
+#include "grid.h" // Iterate the grid
+#include "timing.h" // Timings
+
+// Public
+bool paused;
+
+// Private
+const double req_update_time = 1.0 / UPDATES_PER_SECOND;
+double time_since_update;
+
+void start_game() {
+    clear_grid();
+    paused = true;
+    time_since_update = 0;
+
+    while(true) {
+        game_loop();
+
+        limit_fps();
+    }
+}
+
+void game_loop() {
+    handle_events();
+
+    if (!paused) if ((time_since_update += delta_time) >= req_update_time) {
+        iterate_grid();
+        time_since_update -= req_update_time;
+    }
+
+    draw();
+}
+
+void toggle_pause() {
+    paused = !paused;
+    time_since_update = 0;
+}
diff --git a/src/grid.cpp b/src/grid.cpp
new file mode 100644
index 0000000..b0eac8b
--- /dev/null
+++ b/src/grid.cpp
@@ -0,0 +1,46 @@
+#include "globals.h" // Grid size macros
+
+bool grid[GRID_HEIGHT][GRID_WIDTH];
+
+void clear_grid() {
+    for (int i = 0; i < GRID_HEIGHT; i++)
+        for (int j = 0; j < GRID_WIDTH; j++) grid[i][j] = DEAD;
+}
+
+int count_alive_neighbours(int x, int y) {
+    int count = 0;
+
+    for (int i = x - 1; i <= x + 1; i++)
+        for (int j = y - 1; j <= y + 1; j++){
+            if (i == x && j == y) continue;
+
+            int m = (i + GRID_HEIGHT) % GRID_HEIGHT;
+            int n = (j + GRID_WIDTH) % GRID_WIDTH;
+
+            if (grid[m][n] == ALIVE) count++;
+        }
+
+    return count;
+}
+
+void iterate_grid() {
+    bool new_grid[GRID_HEIGHT][GRID_WIDTH];
+
+    for (int i = 0; i < GRID_HEIGHT; i++)
+        for (int j = 0; j < GRID_WIDTH; j++) {
+            int neighbours = count_alive_neighbours(i, j);
+
+            if (grid[i][j] == ALIVE) {
+                if (neighbours < 2) new_grid[i][j] = DEAD;
+                else if (neighbours == 2 || neighbours == 3) new_grid[i][j] = ALIVE;
+                else new_grid[i][j] = DEAD;
+            } else {
+                if (neighbours == 3) new_grid[i][j] = ALIVE;
+                else new_grid[i][j] = DEAD;
+            }
+        }
+
+
+    for (int i = 0; i < GRID_HEIGHT; i++)
+        for (int j = 0; j < GRID_WIDTH; j++) grid[i][j] = new_grid[i][j];
+}
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..a1df726
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <SDL.h>
+
+#include "game.h" // To start the game
+#include "globals.h" // Window dimensions
+#include "main.h" // This file
+
+// Public
+SDL_Window *window;
+
+int main(int argc, char** argv) {
+    init();
+
+    start_game();
+
+    quit_application(0);
+}
+
+void init() {
+    if(SDL_Init(SDL_INIT_VIDEO) != 0) {
+        printf("Could not start SDL.\nSDL error: %s\n", SDL_GetError());
+        quit_application(1);
+    }
+
+    window = SDL_CreateWindow("Game of Life",
+            SDL_WINDOWPOS_CENTERED,
+            SDL_WINDOWPOS_CENTERED,
+            WINDOW_WIDTH, WINDOW_HEIGHT, 0);
+
+    if (window == NULL) {
+        printf("Could not create window: %s\n", SDL_GetError());
+        quit_application(1);
+    }
+}
+
+void quit_application(int exit_code) {
+    if (window != NULL) SDL_DestroyWindow(window);
+    
+    SDL_Quit();
+
+    exit(exit_code);
+}
diff --git a/src/timing.cpp b/src/timing.cpp
new file mode 100644
index 0000000..c6e28a8
--- /dev/null
+++ b/src/timing.cpp
@@ -0,0 +1,27 @@
+#include <SDL.h>
+
+#include "globals.h" // Timing macros
+#include "timing.h" // This file
+
+// Public
+double delta_time;
+
+// Private
+const double req_delta_time = 1.0 / FRAMES_PER_SECOND;
+
+int t_start = 0;
+
+void limit_fps() {
+    int t_end = SDL_GetTicks();
+    delta_time = (t_end - t_start) / 1000.0;
+
+    double extra_time = req_delta_time - delta_time;
+
+    int sleep_time = extra_time * 1000;
+    if (sleep_time > 0) SDL_Delay(sleep_time);
+
+    t_end = SDL_GetTicks();
+    delta_time = (t_end - t_start) / 1000.0;
+
+    t_start = t_end;
+}