main
  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <string.h>
  4#include "world.h"
  5
  6int west_of(World *world, int index) {
  7  return (index % world->width == 0) ? index + (world->width-1) : index - 1;
  8}
  9
 10int east_of(World *world, int index) {
 11  return (index % world->width == (world->width-1)) ? index - (world->width-1) : index + 1;
 12}
 13
 14int north_of(World *world, int index) {
 15  return (index % world->width == index) ? world_number_of_cells(world) - world->width : index - world->width;
 16}
 17
 18int south_of(World *world, int index) {
 19  return (index >= (world_number_of_cells(world) - world->width)) ? index - (world_number_of_cells(world) - world->height) : index + world->width;
 20}
 21
 22int north_west_of(World *world, int index) {
 23  return west_of(world, north_of(world, index));
 24}
 25
 26int north_east_of(World *world, int index) {
 27  return east_of(world, north_of(world, index));
 28}
 29
 30int south_west_of(World *world, int index) {
 31  return west_of(world, south_of(world, index));
 32}
 33
 34int south_east_of(World *world, int index) {
 35  return east_of(world, south_of(world, index));
 36}
 37
 38int world_number_of_cells(World *world) {
 39  return world->width * world->height;
 40}
 41
 42Cell* world_cell_at(World *world, int index) {
 43  return &world->cells[sizeof(Cell) * index];
 44}
 45
 46int world_neighbours(World *world, int index) {
 47  Cell *west_cell = world_cell_at(world, west_of(world, index));
 48  Cell *east_cell = world_cell_at(world, east_of(world, index));
 49  Cell *north_cell = world_cell_at(world, north_of(world, index));
 50  Cell *south_cell = world_cell_at(world, south_of(world, index));
 51  Cell *north_west_cell = world_cell_at(world, north_west_of(world, index));
 52  Cell *north_east_cell = world_cell_at(world, north_east_of(world, index));
 53  Cell *south_west_cell = world_cell_at(world, south_west_of(world, index));
 54  Cell *south_east_cell = world_cell_at(world, south_east_of(world, index));
 55
 56  return cell_alive(west_cell)
 57    + cell_alive(east_cell)
 58    + cell_alive(north_cell)
 59    + cell_alive(south_cell)
 60    + cell_alive(north_west_cell)
 61    + cell_alive(north_east_cell)
 62    + cell_alive(south_west_cell)
 63    + cell_alive(south_east_cell);
 64}
 65
 66World* world_create(int width, int height) {
 67  int number_of_cells = width*height;
 68  World *world = (World *)malloc(sizeof(World));
 69
 70  memset(world, 0, sizeof(World));
 71
 72  world->width = width;
 73  world->height = height;
 74  world->cells = cell_create(number_of_cells);
 75  return world;
 76}
 77
 78void world_each(World *world, each_cell callback){
 79  for (int i = 0; i < world_number_of_cells(world); i++) {
 80    callback(&world->cells[i]);
 81  }
 82}
 83
 84void choose_random_life(Cell *cell){
 85  cell_change_life(cell, rand() % 2 == 0 ? true : false);
 86}
 87
 88World* world_random(int width, int height){
 89  World *world = world_create(width, height);
 90  world_each(world, choose_random_life);
 91  return world;
 92}
 93
 94World* world_evolve(World *old_world) {
 95  World *new_world = world_create(old_world->width, old_world->height);
 96
 97  for (int i = 0; i < world_number_of_cells(old_world); i++) {
 98    int neighbours = world_neighbours(old_world, i);
 99    bool lives = (world_cell_at(old_world, i)->alive && neighbours == 2) || neighbours == 3;
100    cell_change_life(world_cell_at(new_world, i), lives);
101  }
102
103  return new_world;
104}
105
106void world_print(World *world) {
107  for (int i = 0; i < world_number_of_cells(world); i++) {
108    if (i % world->width == 0) { printf("\n"); }
109    cell_print(&world->cells[i]);
110  }
111  printf("\n");
112}
113
114void world_destroy(World *world) {
115  free(world);
116}