// implement basic life rules, with a fast implementation
#ifndef FAST_LIFE_H
#define FAST_LIFE_H

#include <vector>
#include "Life.h"

class FastLife : public LifeSimulator
	{
public:
	__int64 CountPopulation(void)
		{
		population_ = 0;
		for (int j = 0; j < height_; ++j)
			for (int i = 0; i < width_; ++i)
				if (0 != GetValue(i,j))
					++population_;
		return population_;
		}

	__int64 GetGeneration(void)
		{
		return generation_;
		}
	void Reset(void)
		{
		population_ = 0;
		generation_ = 0;
		for (unsigned int pos = 0; pos < data_.size(); ++pos)
			data_[pos] = 0;
		}
	// get value at cell (i,j)
	unsigned char GetValue(int i, int j) const
		{
		++i; // note we have a top and bottom row extra for speed
		++j; // note we keep a left and right extra column for speed
		uint32 val = data_[i/32+j*span_];
		i &= 31;
		return static_cast<unsigned char>((val>>i)&1);
		}
	void SetValue(int i, int j, unsigned char value)
		{
		SetValue(i, j, value, data_);
		}

	void NextGeneration(void);

	__int64 GetPopulation(void) const
		{
		return population_;
		}
	void SetPopulation(__int64 pop)
		{
		population_ = pop;
		}

	void SetSize(int width, int height)
		{
		width_  = width;
		height_ = height;

		// note we have a top and bottom row extra for speed
		// note we keep a left and right extra column for speed
		span_ = (width_ + 2 +31)/32;
		data_.resize(span_*(height_+2));
		}
	void GetSize(int & width, int & height) const
		{
		width = width_;
		height = height_;
		}
	bool GetWraparound(void) const
		{
		return wraps_;
		}
	void SetWraparound(bool wrap)
		{
		wraps_ = wrap;
		}

	// takes RGB buffer, stride, image width, height, and color to draw r,g,b
	// and viewport
	void DrawBuffer(Viewport & vp, unsigned char * buffer, int stride, int width, int height,
					unsigned char r, unsigned char g, unsigned char b);

	FastLife(void);
private:
	typedef unsigned long uint32; // basic storage type

	void SetValue(int i, int j, unsigned char value, std::vector<uint32> & data)
		{
		++i; // note we have a top and bottom row extra for speed
		++j; // note we keep a left and right extra column for speed

		uint32 mask = 1<<(i&31);
		if (0 != value)
			data[i/32+j*span_] |= mask;
		else
			data[i/32+j*span_] &= ~mask;
		}


	std::vector<uint32> data_;    // data 0 = blank, 1 = alive, with extra border cells
	int width_, height_;          // size of board
	int span_;                    // width of board in uint32's
	bool wraps_;                  // do we wrap around?
	__int64 population_;
	__int64 generation_;
	}; // FastLife 

#endif // FAST_LIFE_H
// end - FastLife.h