diff --git a/game_of_life.hpp b/game_of_life.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..495fdc3eea5981cd25470fceab77cd7aa5d25da8
--- /dev/null
+++ b/game_of_life.hpp
@@ -0,0 +1,259 @@
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <tuple>
+#include <sstream>
+#include <functional>
+#include "gif.h"
+#include "gif_config.hpp"
+
+namespace gol {
+
+  int num_of_neigbours(int x, int y);
+  bool get_cell(int x, int y);
+  void set_cell(int x, int y, bool value);
+
+namespace internal{
+
+  GifWriter g;
+  //std::vector< std::vector<bool> > grid(GRID_X + 2, std::vector<bool>(GRID_Y + 2,false));
+  //std::vector< std::vector<bool> > prev_grid(GRID_X + 2, std::vector<bool>(GRID_Y + 2,false));
+
+  bool grid[GRID_X + 2][GRID_Y + 2];
+  bool prev_grid[GRID_X + 2][GRID_Y + 2];
+
+  std::tuple<int, int> parse_line(std::string line){
+    
+    std::stringstream ss(line);
+    std::string s;
+    std::vector<int> nums;
+
+    while (getline(ss, s,' ')) {
+        nums.push_back(stoi(s));
+    }
+    return std::make_tuple(nums[0],nums[1]);
+  }
+
+  void seed_ascii(int x, int y, std::string file_path){
+
+  std::string line;
+  std::ifstream seed_pattern("patterns/"+file_path);
+  
+  int line_count = y;
+  if(seed_pattern.is_open()){
+    while( getline(seed_pattern,line)){
+      if(line.length() < GRID_X)
+        for (size_t i = 0; i < line.length(); i++){
+          if(line[i] == 'O'){
+            internal::grid[x+i][line_count] = true;
+          }
+        }
+      if(line_count < GRID_Y)
+        line_count++;
+    }
+    seed_pattern.close();
+  } else std::cout << "Unable to open pattern file:" << file_path << '\n';
+
+  }
+
+  void add_preset(std::string line){
+    
+    std::stringstream ss(line);
+    std::string s;
+    std::vector<std::string> command;
+
+    while (getline(ss, s,' ')) {
+        command.push_back(s);
+    }
+    
+    if(command.size() != 3 && command.size() != 4)
+      return;
+
+    if(command[0] == "pattern"){
+      seed_ascii(stoi(command[1]),stoi(command[2]),command[3]);
+    }else if(command[0] == "glider"){
+      seed_ascii(stoi(command[1]),stoi(command[2]),"glider.cells");
+    } else if(command[0] == "beacon"){
+      seed_ascii(stoi(command[1]),stoi(command[2]),"beacon.cells");
+    } else if(command[0] == "pulsar"){
+      seed_ascii(stoi(command[1]),stoi(command[2]),"pulsar.cells");
+    } else if(command[0] == "sauron"){
+      seed_ascii(stoi(command[1]),stoi(command[2]),"sauron.cells");
+    } else {
+      std::cout << "! >> Unknown command found in seed file << ! \n";
+    }
+  }
+
+  void clear_grid(){
+      for (size_t i = 0; i < GRID_X + 2; i++){
+      for (size_t j = 0; j < GRID_Y + 2; j++){ 
+        internal::grid[i][j] = 0;
+      }
+    }
+  }
+
+  void ex_1(int x, int y){
+    if(!gol::get_cell(x,y))
+      return;
+    if(gol::num_of_neigbours(x,y) < 2){
+      gol::set_cell(x, y, false);
+    }
+  }
+  void ex_2(int x, int y){
+    if(!gol::get_cell(x,y))
+      return;
+    if(gol::num_of_neigbours(x,y) == 2 || gol::num_of_neigbours(x,y) == 3){
+      gol::set_cell(x, y, true);
+    }
+  }
+  void ex_3(int x, int y){
+    if(!gol::get_cell(x,y))
+      return;
+    if(gol::num_of_neigbours(x,y) > 3){
+      gol::set_cell(x, y, false);
+    }
+  }
+  void ex_4(int x, int y){
+    if(!gol::get_cell(x,y)){
+      if(gol::num_of_neigbours(x,y) == 3){
+        gol::set_cell(x, y, true);
+      }
+    }
+  }
+} // end internal
+
+void init_game_of_life(std::string file_name = "gol.gif"){
+  std::cout << "Intialising Game of Life \n";
+  std::cout << "Output file name set to: " << file_name <<'\n';
+
+	GifBegin(&internal::g, file_name.c_str(), GRID_X, GRID_Y, DELAY);
+}
+
+void seed_grid(std::string file_path = "start_grid.txt"){
+  std::string line;
+  std::ifstream grid_init_file (file_path);
+  
+  if (grid_init_file.is_open()){
+    while ( getline (grid_init_file,line) ){
+      if(!line.empty()){
+        if(std::find_if(line.begin(), 
+        line.end(), [](unsigned char c) { return !std::isdigit(c) && c != ' '; }) == line.end()){
+          auto [x , y] = internal::parse_line(line);
+          if(x < GRID_X || y < GRID_Y){
+            internal::grid[x+1][y+1] = true;
+          } else {
+            std::cout << "Could not add cell: Coordinates out of bounds.\n";
+          }
+        }else{
+          internal::add_preset(line);
+        }
+      }
+    }
+    grid_init_file.close();
+  } else std::cout << "Unable to open file :" << file_path << '\n';
+
+}
+
+int num_of_neigbours(int x, int y){
+
+  x++;
+  y++;
+  int counter = 0;
+
+  if(internal::prev_grid[x-1][y-1]) counter++;
+  if(internal::prev_grid[x-1][y]) counter++;
+  if(internal::prev_grid[x-1][y+1]) counter++;
+
+  if(internal::prev_grid[x][y-1]) counter++;
+  if(internal::prev_grid[x][y+1]) counter++;
+
+  if(internal::prev_grid[x+1][y-1]) counter++;
+  if(internal::prev_grid[x+1][y]) counter++;
+  if(internal::prev_grid[x+1][y+1]) counter++; 
+
+  return counter;
+}
+
+void write_frame(){
+  std::vector<uint8_t> image((GRID_X + 2) * (GRID_Y + 2) * 4);
+  
+  for (size_t i = 1; i < GRID_X + 1; i++){
+    for (size_t j = 1; j < GRID_Y + 1; j++){ 
+      for (size_t k = 0; k < 4; k++){
+
+        const int one_d_map = i + GRID_X  * j;
+        const int index = (one_d_map * 4) + k;
+        image[index] = internal::grid[i][j] ? 255 : 0;
+      }
+    }
+  }
+	GifWriteFrame(&internal::g, image.data(), GRID_X, GRID_Y, DELAY);
+  std::swap(internal::prev_grid,internal::grid);
+  internal::clear_grid();
+}
+
+void render(){
+  GifEnd(&internal::g);
+}
+const int get_x_dimension(){
+  return GRID_X;
+}
+
+const int get_y_dimension(){
+  return GRID_Y;
+}
+
+bool get_cell(int x, int y){
+  return internal::prev_grid[x + 1][y + 1];
+}
+
+void set_cell(int x, int y, bool value){
+  internal::grid[x + 1][y + 1] = value;
+}
+
+//For Debug ...
+void print_grid(){
+  for (size_t i = 0; i < GRID_X + 2; i++){
+    for (size_t j = 0; j < GRID_Y + 2; j++){
+      std::cout << std::boolalpha << internal::grid[i][j] << ' ';
+    }
+    std::cout << '\n';
+  }
+}
+
+void print_img(std::vector<uint8_t> img){
+  for (size_t i = 0; i < GRID_X*4; i++){
+    for (size_t j = 0; j < GRID_Y*4; j++){
+      if (img[i + (GRID_X * 4) * j] == 255)
+        std::cout << 'x' << ' ';
+      else
+        std::cout << '0' << ' ';
+    }
+    std::cout << '\n';
+  }
+}
+
+void run_gol(std::function<void(int,int)> r1 = internal::ex_1,
+                    std::function<void(int,int)> r2 = internal::ex_2,
+                    std::function<void(int,int)> r3 = internal::ex_3,
+                    std::function<void(int,int)> r4 = internal::ex_4){
+  gol::init_game_of_life("Experimenting.gif");
+  gol::seed_grid();
+  gol::write_frame();
+
+  int num_frames = 100;
+  for (size_t i = 0; i < num_frames; i++){
+    for (size_t j = 0; j < gol::get_x_dimension(); j++){
+      for (size_t k = 0; k < gol::get_y_dimension(); k++){
+        r1(j,k);
+        r2(j,k);
+        r3(j,k);
+        r4(j,k);
+      }
+    } 
+    gol::write_frame();
+  }
+  gol::render();
+}
+
+}
\ No newline at end of file