/*
	LifeClass.h
*/
// 定数定義

#define	MAX_WIDTH	50		// 世界の最大幅
#define	MAX_HEIGHT	50		// 世界の最大高さ
#define	INTERVAL	100		// Generation(世代)表示の長さ
#define	ALIVE		1
#define	DEAD		0
#define	TRUE		1
#define	FALSE		0

// Lifeクラス定義
class Life {
private:
	int		Width;
	int		Height;
	int*	Cells;
	int*	NewGen;
public:
	// サイズ無指定コンストラクター
	Life() {
		// 乱数の初期化
		srand((unsigned int)time(NULL));
		// 世界と次世代
		Cells = 0;
		NewGen = 0;
		// 世界の規模
		Width = rand() % (MAX_WIDTH - 2) + 3;	// Min 3が必要
		Height = rand() % (MAX_HEIGHT - 2) + 3;	// Min 3が必要
		// 生命体（Cells）の初期化
		if(!Cells)	Cells = new int[Width * Height];
		if(!NewGen)	NewGen = new int[Width * Height];
		// 世界の初期化（誕生する生命体数は1/3）
		for(int y = 0; y < Height; y++) {
			for(int x = 0; x < Width; x++) {
				if(rand() % 3 == 0)	// Cellを増やす場合、2(50%) → 3(66%)にする
					Cells[x + Width * y] = ALIVE;
				else
					Cells[x + Width * y] = DEAD;
			}
		}
	}
	// サイズ指定コンストラクター
	Life(int w, int h) {
		// 乱数の初期化
		srand((unsigned int)time(NULL));
		// 世界と次世代
		Cells = 0;
		NewGen = 0;
		// 世界の規模
		w = (w < 3 ? 3 : w);				// 幅はMin 3
		h = (h < 3 ? 3 : h);				// 高さもMin 3
		Width = (w > MAX_WIDTH ? MAX_WIDTH : w);	// 幅はMAX_WIDTH限度
		Height = (h > MAX_HEIGHT ? MAX_HEIGHT : h);	// 高さはMAX_HEIGHT限度
		// 生命体（Cells）の初期化
		if(!Cells)	Cells = new int[Width * Height];
		if(!NewGen)	NewGen = new int[Width * Height];
		// 世界の初期化（誕生する生命体数は1/3）
		for(int y = 0; y < Height; y++) {
			for(int x = 0; x < Width; x++) {
				if(rand() % 3  == 0)	// Cellを増やす場合、2(50%) → 3(66%)にする
					Cells[x + Width * y] = ALIVE;
				else
					Cells[x + Width * y] = DEAD;
			}
		}
	}
	// デストラクター
	~Life() {
		delete [] Cells;
		delete [] NewGen;
	}
	// 次世代（NewGen）の世界の評価
	void Eval() {
		// 上下左右の状況確認
		for(int y = 0; y < Height; y++) {		// 高さ
			for(int x = 0; x < Width; x++) {	// 幅
				int count = 0;	// 周囲の生存（ALIVE）生命体（Cell）数
				if(x == 0) {											// 左は無い
					if(y == 0) {											// 上は無い
						if(Cells[(x + 1) + Width * y] == ALIVE)					// 右
							count++;
						if(Cells[(x + 1) + Width * (y + 1)] == ALIVE)			// 右下
							count++;
						if(Cells[x + Width * (y + 1)] == ALIVE)					// 下
							count++;
					}
					else {
						if(y == Height -1) {								// 下は無い
							if(Cells[x + Width * (y - 1)] == ALIVE)				// 上
								count++;
							if(Cells[(x + 1) + Width * (y - 1)] == ALIVE)		// 右上
								count++;
							if(Cells[(x + 1) + Width * y] == ALIVE)				// 右
								count++;
						}
						else {	// 上下あり
							if(Cells[x + Width * (y - 1)] == ALIVE)				// 上
								count++;
							if(Cells[(x + 1) + Width * (y - 1)] == ALIVE)		// 右上
								count++;
							if(Cells[(x + 1) + Width * y] == ALIVE)				// 右
								count++;
							if(Cells[(x + 1) + Width * (y + 1)] == ALIVE)		// 右下
								count++;
							if(Cells[x + Width * (y + 1)] == ALIVE)				// 下
								count++;
						}
					}
				}
				else {
					if(x == Width - 1) {								// 右は無い
						if(y == 0) {										// 上は無い
							if(Cells[x + Width * (y + 1)] == ALIVE)				// 下
								count++;
							if(Cells[(x - 1) + Width * (y + 1)] == ALIVE)		// 左下
								count++;
							if(Cells[(x - 1) + Width * y] == ALIVE)				// 左
								count++;
						}
						else {
							if(y == Height -1) {							// 下は無い
								if(Cells[(x - 1) + Width * y] == ALIVE)			// 左
									count++;
								if(Cells[(x - 1) + Width * (y - 1)] == ALIVE)	// 左上
									count++;
								if(Cells[x + Width * (y - 1)] == ALIVE)			// 上
									count++;
							}
							else {											// 上下あり
								if(Cells[x + Width * (y + 1)] == ALIVE)			// 下
									count++;
								if(Cells[(x - 1) + Width * (y + 1)] == ALIVE)	// 左下
									count++;
								if(Cells[(x - 1) + Width * y] == ALIVE)			// 左
									count++;
								if(Cells[(x - 1) + Width * (y - 1)] == ALIVE)	// 左上
									count++;
								if(Cells[x + Width * (y - 1)] == ALIVE)			// 上
									count++;
							}
						}
					}
					else {												// 左右あり
						if(y == 0) {										// 上は無い
							if(Cells[(x + 1) + Width * y] == ALIVE)				// 右
								count++;
							if(Cells[(x + 1) + Width * (y + 1)] == ALIVE)		// 右下
								count++;
							if(Cells[x + Width * (y + 1)] == ALIVE)				// 下
								count++;
							if(Cells[(x - 1) + Width * (y + 1)] == ALIVE)		// 左下
								count++;
							if(Cells[(x - 1) + Width * y] == ALIVE)				// 左
								count++;
						}
						else {
							if(y == Height - 1) {							// 下は無い
								if(Cells[(x - 1) + Width * y] == ALIVE)			// 左
									count++;
								if(Cells[(x - 1) + Width * (y - 1)] == ALIVE)	// 左上
									count++;
								if(Cells[x + Width * (y - 1)] == ALIVE)			// 上
									count++;
								if(Cells[(x + 1) + Width * (y - 1)] == ALIVE)	// 右上
									count++;
								if(Cells[(x + 1) + Width * y] == ALIVE)			// 右
									count++;
							}
							else {											// 上下あり
								if(Cells[(x - 1) + Width * y] == ALIVE)			// 左
									count++;
								if(Cells[(x - 1) + Width * (y - 1)] == ALIVE)	// 左上
									count++;
								if(Cells[x + Width * (y - 1)] == ALIVE)			// 上
									count++;
								if(Cells[(x + 1) + Width * (y - 1)] == ALIVE)	// 右上
									count++;
								if(Cells[(x + 1) + Width * y] == ALIVE)			// 右
									count++;
								if(Cells[(x + 1) + Width * (y + 1)] == ALIVE)	// 右下
									count++;
								if(Cells[x + Width * (y + 1)] == ALIVE)			// 下
									count++;
								if(Cells[(x - 1) + Width * (y + 1)] == ALIVE)	// 左下
									count++;
							}
						}
					}
				}
				switch(count) {
					case 0:	// 周囲の生命体数が1以下だと死滅
					case 1: NewGen[x + Width * y] = DEAD;
							break;
					case 2:	// 周囲の生命体数が2 - 3の場合は現状維持
							NewGen[x + Width * y] = Cells[x + Width * y];
							break;
					case 3:	// 周囲の生命体数が3の場合は、生命体が誕生する
							NewGen[x + Width * y] = ALIVE;
							break;
					case 4:	// 周囲の生命体数が4以上だと過密で死滅
					case 5:
					case 6:
					case 7:
					case 8: NewGen[x + Width * y] = DEAD;
							break;
				}
			}
		}
	}
	void Transition() {
		for(int y = 0; y < Height; y++) {		// 高さ
			for(int x = 0; x < Width; x++) {	// 幅
				Cells[x + Width * y] = NewGen[x + Width * y];
			}
		}
	}
	int GetW() {return Width;}
	int GetH() {return Height;}
	int* GetCells() {return Cells;}
};
