--- /dev/null
+
+enum e_topology
+{
+ plane,
+ loop,
+ mobius,
+ sphere,
+ torus,
+ projective_plane,
+ klein_bottle,
+}
+typedef enum e_topology t_topology;
+
+typedef int t_cell_t;
+
+/*
+ * ---------------> y / columns / j
+ * |
+ * |
+ * |
+ * |
+ * |
+ * \/
+ * x / rows / i
+ */
+struct s_matrix
+{
+ int cols;
+ int rows;
+ t_cell_t *array;
+}
+typedef struct s_matrix t_matrix;
+
+struct s_world
+{
+ t_matrix grid;
+ t_topology topology;
+}
+typedef struct s_world t_world;
+
+t_cell_t *get_element(t_matrix *matrix, int row, int col)
+{
+ if (0 > row || row > matrix->rows || 0 > col || col > matrix->cols)
+ {
+ return (NULL);
+ }
+ return (&(matrix->array[matrix->cols * row + col]));
+}
+
+t_cell_t *get_cell(world, int x, int y)
+{
+ if (out_of_world(world, x, y))
+ {
+ return (NULL);
+ }
+ x = (pow(orientation(world->topology.x), y / world->grid.cols) * x) % world->grid.rows;
+ y = (pow(orientation(world->topology.y), x / world->grid.rows) * y) % world->grid.cols;
+ if ((((y / world->grid.cols + x / world->grid.rows) % 2) == 1) && world->topology.scheme == aabb)
+ return (get_element(&(world->grid), y, x));
+ return (get_element(&(world->grid), x, y));
+}
+
+t_cell_t apply_kernel_at_point(t_world *world, t_matrix *kernel, int x, int y)
+{
+ int i;
+ int j;
+ t_cell_t result;
+
+ result = 0;
+ i = -(kernel->rows / 2);
+ while (i < kernel->rows / 2)
+ {
+ j = -(kernel->cols / 2);
+ while (j < kernel->cols / 2)
+ {
+ cell = *get_neighboring_cell(world, x + i, y + j);
+ if (cell)
+ {
+ result += *get_element(kernel, i, j) * *cell;
+ }
+ ++j;
+ }
+ ++i;
+ }
+ return (result);
+}
+
+void apply_kernel(t_world *world, t_matrix *kernel, t_matrix *result)
+{
+ int i;
+ int j;
+
+ i = 0;
+ while (i < world->rows)
+ {
+ j = 0;
+ while (j < world->cols)
+ {
+ *get_element(result, i, j) = apply_kernel_at_point(world, kernel, i, j);
+ ++j;
+ }
+ ++i;
+ }
+ return ;
+}
+
+void apply_rule(t_grid *grid, t_cell_t (*rule)(t_cell_t))
+{
+ int i;
+
+ i = 0;
+ while (i < grid->cols * grid->rows)
+ {
+ grid->array[i] = rule(grid->array[i]);
+ ++i;
+ }
+ return ;
+}