function life(varargin)
   args = getArgs2(varargin);
   showColony(args.colony, 0);
   for gen = 1:args.gens
      args = nextGen(args);
      showColony(args.colony, gen);
      pause(args.delay)
   end
end

% ------------------- Get Command Line Arguments -------------------
% --- colony file, border size, pause time, generations ------------
function args = getArgs(vargs)
   border = 5;
   args.delay = 0.5;
   args.gens = 5;
   colony = ['oo.o';'.oo.';'...o'];
   args.count = length(vargs);
   if args.count >= 1 && exist(vargs{1}) == 2
      colony = getColony(vargs{1})
   end
   [rows cols] = size(colony);
   if args.count >= 2
      border = vargs{2};
   end
   if args.count >= 3
      args.delay = vargs{3};
   end
   if args.count >= 4
      args.gens = vargs{4};
   end
   args.colony = repmat('.', rows + 2*border, cols + 2*border);
   args.colony(border+1:border+rows, border+1:border+cols) = colony;
end
 
function args = getArgs2(vargs)
   border = 5;
   args.delay = 0.5;
   args.gens = 5;
   colony = ['oo.o';'.oo.';'...o'];
   args.count = length(vargs);
   for ii = 1:nargin/2
      switch vargs{ii*2-1}
         case 'colony'
            if exist(vargs{ii*2})
               colony = getColony(vargs{ii*2});
            end
         case 'border'
            border = vargs{ii*2};
         case 'delay'
            args.delay = vargs{ii*2};
         case 'count'
            args.gens = vargs{ii*2};
         otherwise
            fprintf('invalid arg: %s\n', vargs{ii*2-1})
      end
   end
   [rows cols] = size(colony);
   args.colony = repmat('.', rows + 2*border, cols + 2*border);
   args.colony(border+1:border+rows, border+1:border+cols) = colony;
end

% ---------------------- Load Initial Colony ---------------------
function colony = getColony(fileName)
   colony = [];
   fid = fopen(fileName);
   while ~feof(fid)
      colony = [colony; fgetl(fid)];
   end
end

% --------------------- Display Colony ------------------------
function showColony(colony, gen)
   fprintf('\n\n Generation: %d\n', gen)
   disp(colony)
end

% ---------------- Calculate Next Generation -------------------
function args = nextGen(args)
   nextColony = args.colony;
   neighbors = getNeighbors(args.colony);
   [rows cols] = size(args.colony);
   for ii = 1:rows
      for jj = 1:cols
         if neighbors(ii,jj) < 2 || neighbors(ii,jj) > 3
            nextColony(ii,jj) = '.';
         end
         if neighbors(ii,jj) == 3 && args.colony(ii,jj) == '.'
            nextColony(ii,jj) = 'o';
         end
      end
   end
   args.colony = nextColony;
end

% --------- Calculate Number of Neighbors of all Cells ----------
function neighbors = getNeighbors(colony)
   [rows cols] = size(colony);
   xColony = repmat('.', rows+2, cols+2);
   xColony(2:end-1, 2:end-1) = colony;
   neighbors = repmat(0, rows+2, cols+2);
   for ii = 2:rows+1
      for jj = 2:cols+1
         neighbors(ii,jj) = neighborCount(xColony(ii-1:ii+1, jj-1:jj+1));
      end
   end
   neighbors = neighbors(2:end-1, 2:end-1);
end

% ------------- Calculate Number of Neighbors of Given Cell -----
function count = neighborCount(neighborCells)
   count = -(neighborCells(2,2) == 'o');
   for ii = 1:3
      for jj = 1:3
         count = count + (neighborCells(ii,jj) == 'o');
      end
   end
end
 
