//////////////////////////////////
// Cell_World.cs
// Class Definitions for Cells.cs
// Copyright (c) 2026 by Y-sama
//////////////////////////////////
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;		//Graphicsクラス（アンチエイリアス）使用の為
using System.Collections.Generic;	//List使用の為
using System.IO;					//FileStream使用の為
using System.Text;					//Encording使用の為
using System.Reflection;			//Assemblyを使う為
using System.Resources;				//リソース使用の為

namespace Cell_World
{
	/////////////////
	//Cellクラス定義
	/////////////////
	public class Cell
	{
		///////////////////////
		//ゲーム関係フィールド
		//     定数定義
		///////////////////////
		int Max_Left = 17520;					//セルの最長余命（単位1時間、2年で24hours x 365days x 2years = 17,520）
		int Max_Life = 4320;					//セルの最大初期エネルギー（半年で24hours x 180days = 4320）
		const int Max_Tribe = 4;				//現在はCell-P, Cell-B, Cell-G, Cell-D（死亡）
		const int Max_Dir = 8;					//↑:0、↗:1、→:2、↘:3、↓:4、↙:5、←:6、↖:7
		const int Not_Found = -1;				//Find_***処理用
		int Living_Cost = 24;					//【調整項目】余命（Left）、生命力（Life）の消耗時間
		/////////////////////////////////
		//メンバーフィールドとプロパティ
		/////////////////////////////////
		//生存フラグ
		public bool Alive {get; private set;}	//生存（true）、死亡（false）
		//繁殖フラグ
		public bool Intmarg {get; set;}			//異種族間婚の許可
		//位置
		private Point Location;					//Cellの位置（World内の位置座標）
		private int[] m_Around = new int[8];	//環境情報フィールド（Aroundの実体）
		public int[] Around						//Cell周囲の存在（野原:0、山:1、河川:2、食物：3、セル：4 + ID）
		{	get
			{
				return m_Around;
			}
			private set
			{
				m_Around = value;
			}
		}
		//性格系
		public int Affection {get; set;}		//愛着性
		public int Hostility {get; set;}		//敵対性
		//能力系
		public int Left {get; set;}				//余命（Max_Left: 単位1時間、2年で24hours x 365days x 2years = 17,520）
		public int Life {get; set;}				//生命力（Max_Life: 半年分で24hours x 180days = 4320）
		public int Power {get; private set;}	//攻撃力（Lifeによる）
		public int Defense {get; private set;}	//防御力（LifeとLeft<経験>による）
		public int Fertility {get; private set;}//生殖力（Leftによる）
		//識別系
		public int ID {get; set;}				//Cellのゼロベースの固有番号
		public int Tribe {get; set;}			//種族（ピンク:0、ブルー:1、グリーン:2、モノ（死亡）:3の4色）
		//運動系
		public int Dir {get; set;}				//Cellの移動方向（↑:0、↗:1、→:2、↘:3、↓:4、↙:5、←:6、↖:7）

		///////////////////
		//メンバーメソッド
		///////////////////
		public Cell(bool intmarg)				//コンストラクター
		{
			//異種族婚許可、性格系、能力系、運動系パラメーターは生成時決定
			Init(intmarg);
		}

		public void Init(bool intmarg)			//Cellの初期化
		{
			//CellのIDはWorldクラスのCreate_Cellで与えられ、Born_Atで記録される
			ID = Not_Found;
			//生存フラグ
			Alive = true;
			//繁殖フラグ（原則異種族間婚はタブー）
			Intmarg = intmarg;
			//位置（周囲状況－WorldのCheck_Aroundで更新される）
			for(int i = 0; i < 8; i++)
				Around[i] = Not_Found;	//Not_Found(-1)はエラー値
			//性格系
			Affection = World.rand.Next(10, 101);		//愛着性（10から100まで）
			Hostility = World.rand.Next(10, 101);		//敵対性（10から100まで）
			//余命
			Left = (Max_Left * World.rand.Next(10, 101)) / 100;	//最長余命 X 10 - 100%
			//生命力（半年分）
			Life = (Max_Life * World.rand.Next(10, 101)) / 100;	//最大初期エネルギー X 10 - 100%
			//能力系
			Power = World.rand.Next(10, 101);			//攻撃力（LifeとLeftによる）
			Defense = World.rand.Next(5, 51)		;	//防御力（Ditto）－一般に防御力は攻撃力より弱い
			Fertility = World.rand.Next(10, 101);		//生殖力（Leftによる）
			//識別系（種族表示色－ピンク、ブルー、グリーン、モノ（死亡）の4種－前3種を使用）
			Tribe = World.rand.Next(Max_Tribe - 1);
			//運動系
			Dir = World.rand.Next(8);					//↑:0、↗:1、→:2、↘:3、↓:4、↙:5、←:6、↖:7
		}

		public bool Born_At(int id, int x, int y)		//CellのID、座標設定（どこに、誰として生まれるのか）
		{
			if(ID != Not_Found)							//既に生まれている場合、エラー
				return false;
			else
			{
				ID = id;
				Location.X = x;
				Location.Y = y;
				return true;
			}
		}

		public string Show_Param()						//パラメーターの表示
		{
			string param = "No.";
			if(ID < 9)
				param += " " + (ID + 1).ToString() + " ";
			else
				param += (ID + 1).ToString() + " ";
			param += Alive ? "生存状態：存命" : "生存状態：死亡";
			param += "（余命：" + Left.ToString() + "）";
			string[] tribe = new string[4] {"ピンク", "ブルー", "グリーン", "モノトーン（死亡）"};
			param += "、種族：" + tribe[Tribe];
			param +=  "、愛着性：" + Affection.ToString() + "、敵対性：" + Hostility.ToString()
			+ "、生命力：" + Life.ToString() + "、攻撃力：" + Power.ToString()
			+ "、防御力：" + Defense.ToString() + "、生殖力：" + Fertility.ToString() + Environment.NewLine;
			return param;
		}

		public Point Where()					//Cellの座標の取得
		{
			return Location;
		}

		public void Get_There(Point there)		//指定locationへ移動する
		{
			Location = there;
		}

		public void VitalCheck()				//死亡要因をチェックし、Aliveを決定する
		{
			if(Left > 0 && Life > 0)			//余命があり、且つ生命力がある
			{
				Alive = true;
			}
			else
			{
				Alive = false;					//死亡
				Tribe = 3;						//セルの色をモノ（死亡－3 <食物>）に変える
			}
		}

		public int Find_Cell()					//周囲にセルがいるか否かチェックする（戻り値は複合）
		{										//戻り値(val)：絶対方向（val & 0x0F）、周囲のセルのID（val >> 4）
			int dir = 0;						//戻り値（全bitが0）
			int id = Not_Found;					//戻り値（全bitが1）
			//方向は↑:0、↗:1、→:2、↘:3、↓:4、↙:5、←:6、↖:7
			for(int i = 0; i < Max_Dir; i++)
			{
				dir = (Dir + 7 + i) % Max_Dir;	//進行方向斜め左から
				if(Around[dir] >= 4)			//セルがいる場合
				{
					id = Around[dir] - 4;		//idはセルのID
					return dir | (id << 4);		//idはdir（0 - 7）がかからないよう16倍にする
				}
			}
			return Not_Found;					//セルがいない場合は-1を返す
		}

		public int Find_Food()					//周囲に食物があるか否かチェックする
		{
			//方向は↑:0、↗:1、→:2、↘:3、↓:4、↙:5、←:6、↖:7
			for(int i = 0; i < Max_Dir; i++)
			{
				int f_dir = (Dir + 7 + i) % Max_Dir;	//進行方向斜め左から
				if(Around[f_dir] == 3)
					return f_dir;				//戻り値は絶対方向(0－7）
			}
			return Not_Found;					//ない場合は-1を返す
		}

		public void Get_Food(int dir)			//周囲に食物があれば移動して摂食する
		{
			if(dir < 0 || dir > 7)
				return;							//エラー（何もしない）
			Get_Move(dir)	;					//食物へ移動する
			Life += 168;						//【調整項目】7日分（24h x 7d）のエネルギー回復
		}

		//周囲に（進むことが出来る）野原があるか否かチェックする |7|0|1|
		//進行方向（Dir）と前進、後退を指定できる(forward)		 |6|C|2|
		//前進→Dir、後退→(Dir + 4) % 8;						 |5|4|3|
		public int Find_Field(bool forward = true, int d = -1)
		{
			//進行方向指示がある場合（エラーチェック付）
			if(d > -1 && d < 8)
				Dir = d;
			//野原の方角を記録（nは野原のある方向の数、dirは戻り値）
			int[] field = new int[Max_Dir] {-1, -1, -1, -1, -1, -1, -1, -1};
			int n = 0, dir = Not_Found;
			//方向は↑:0、↗:1、→:2、↘:3、↓:4、↙:5、←:6、↖:7
			for(int i = 0; i < Max_Dir; i++)
			{
				if(Around[i] == 0)				//Around[]に野原があれば
				{
					field[n] = i;				//fieldにその方向を記録してゆく
					if(forward)					//前進可で
					{
						if(i == Dir)			//進行方向に野原があれば
							dir = i;			//その方向
					}
					else						//後退で
					{
						if(i == (Dir + 4) % 8)	//逆方向に野原があれば
							dir = i;			//その方向
					}
					n++;
				}
			}
			if(n == 0)							//ない場合は
				return Not_Found;				//-1を返す（エラー）
			else
			{
				if(dir == -1)					//真前または後ろへ進めないなら
					dir = field[World.rand.Next() % n];	//乱数による選択
				//dirがDirの場合でも「1/8（12.5%)」の確率で（パニック状態）
				else if(dir == Dir && World.rand.Next() % Max_Dir == 0)
					dir = field[World.rand.Next() % n];	//乱数による選択
			}
			return dir;
		}

		public void Get_Move(int dir)			//野原があれば一つ移動する（Locationを変更する）
		{
			if(dir < 0 || dir > 7)
				return;							//エラーチェック
			switch(dir)
			{
				case 0:		//↑
					Location.Y--;
					break;
				case 1:		//↗
					Location.X++;
					Location.Y--;
					break;
				case 2:		//→
					Location.X++;
					break;
				case 3:		//↘
					Location.X++;
					Location.Y++;
					break;
				case 4:		//↓
					Location.Y++;
					break;
				case 5:		//↙
					Location.X--;
					Location.Y++;
					break;
				case 6:		//←
					Location.X--;
					break;
				case 7:		//↖
					Location.X--;
					Location.Y--;
					break;
			}
			Dir = dir;
		}

		public void Aging()							//加齢変化（老化）
		{
			Left -= Living_Cost;					//寿命
			Life -= Living_Cost;					//生命力
		}

		public void Param_Change()					//【調整項目】状態変化により、各種パラメーターが変化する
		{
			//【余命とライフステージ】
			//余命（MAX_LEFT－17,520）の90%（15,768）が最大なので、人間の平均余命80歳として
			//幼年期0-15歳(20%)、青年期16-29歳(16%)、壮年期30-49歳(25%)、老年期50-80歳(37.5%)
			//の分布を考えれば、m_leftは、
			//幼年期（～12,951）、青年期（12,950～9,801）、壮年期（9,800～5,901）、老年期（5,900～0）
			//程度と考えられるが、余命の最小値が10%の1,752なので以下のように調整
			//幼年期（～8,001）、青年期（8,000～5,001）、壮年期（5,000～2,001）、老年期（2,000～0）
			//【攻撃力】
			//生命力の初期値は半年分のエネルギー（MAX_LIFE－4320）の10 - 90%であり、食物と死体を摂食
			//することでしか増加できない為、攻撃力（m_power）増加要因として幼年期は1000あれば1/2の
			//確率でm_powerが増加、青年期、壮年期は2000あれば1/2、1/3で増加
			//【防衛力】
			//これは「亀の甲より年の効」で「（見做し）経験を積んだ」として壮年期、老年期に1/3の確率
			//で増加
			//【生殖力】
			//これは若さだけなので、幼少期、青年期に1/2、壮年期に1/3の確率で増加、老年期は1/2の確率
			//で減少
			if(Left > 8000)			//幼年期
			{
				if(Life > 1000 && World.rand.Next() % 2 == 0)
					Power++;
				if(World.rand.Next() % 2 == 0)
					Fertility++;
			}
			else if(Left > 5000)	//青年期
			{
				if(Life > 2000 && World.rand.Next() % 2 == 0)
					Power++;
				if(World.rand.Next() % 2 == 0)
					Fertility++;
			}
			else if(Left > 2000)	//壮年期
			{
				if(Life > 2000 && World.rand.Next() % 3 == 0)
					Power++;
				if(World.rand.Next() % 3 == 0)
					Defense++;
				if(World.rand.Next() % 3 == 0)
					Fertility++;
			}
			else					//老年期
			{
				if(World.rand.Next() % 3 == 0)
					Defense++;
			}
		}

		public void Damaged(int d)					//加害を受け、生命力、余命が減少する
		{
			//ダメージ(d) = 相手攻撃力(Power) - 自分の防御力(Defense)とする
			if(d > 0)
			{
				Life -= d;
				Left -= d;
			}
		}

		public void Killed()						//殺されて、生命力、余命が0になる
		{
			Left = 0;
			Life = 0;
			Tribe = 3;
			Alive = false;
		}
	}

	//////////////////
	//Worldクラス定義
	//////////////////
	public class World : PictureBox
	{
		///////////////////////
		//定数定義（変更不可）
		///////////////////////
		const int Wld_Width = 80;				//Worldの幅（セル数）
		const int Wld_Height = 40;				//Worldの高さ（セル数）
		const int Max_Population = Wld_Width * Wld_Height / 2;	//「世界」に棲めるセルの最大人口
		const int Max_Tribe = 4;				//現在はCell-P, Cell-B, Cell-G, Cell-D（死亡）
		const int Max_Dir = 8;					//↑:0、↗:1、→:2、↘:3、↓:4、↙:5、←:6、↖:7
		const int Not_Found = -1;				//Find_***処理用
		/////////////////////////////////
		//ゲーム関係フィールド
		/////////////////////////////////
		public static Random rand;				//乱数（World、Cell共通）
		private bool Gameover = false;			//ゲーム終了サイン
		private string Message;					//ゲームオーバーの際に、呼び出しユーザーに返すメッセージ
		private int Ini_pop = 0;				//開始時のセル数（0で初期化）
		private List<Cell> CellList = new List<Cell>();				//セルリスト
		private int[] Tribe_Status = new int[4];					//Cell-P, Cell-B, Cell-G, Cell-Dの状況を記録（0で初期化）
		private char[] Map = new char[Wld_Width * Wld_Height];		//「文字」地形図（野原:' '、山:'^'、河川:'~'、食物：'O'）
		private int[] PrevMap = new int[Wld_Width * Wld_Height];	//直前の「論理」地形図（野原:0、山:1、河川:2、食物：3、セル：4 + ID）
		public int MyID = Not_Found;			//アバターCellのID
		//【調整項目】定数定義（変更可）
		int Max_Param = 100;					//Cellの属性の最大値
		int Increase = 1;						//パラメーターの増加幅
		int Decrease = -1;						//パラメーターの減少幅
		///////////////////////
		//描画関係フィールド
		///////////////////////
		//地形描画用Bitmap「野原:0」、「山:1」、「河川:2」、「食物：3」
		Bitmap[] Terrain_Bmp = new Bitmap[Max_Tribe];
		//Cell描画用Bitmap「ピンク:0」、「ブルー:1」、「グリーン:2」、「モノ（死亡）:3」+ Cell-Me（Avatar）
		Bitmap[] Cell_Bmp = new Bitmap[Max_Tribe + 1];
		//PictrueBox描画関係プロパティ
		public Bitmap Canvas {set; get;}		//仮想画面ビットマップ
		public Graphics gHandle {set; get;}		//仮想画面のグラフィック

		//コンストラクター
		public World()
		{
			//乱数の初期化
			rand = new Random((int)DateTime.Now.Ticks);
			//World（PictureBoxから派生）コントロール
			this.Width = 16 * Wld_Width;		//16 x 16ビットマップ x 80
			this.Height = 16 * Wld_Height;		//16 x 16ビットマップ x 40
			//本プログラムのリソースマネージャー作成
			ResourceManager rm = new ResourceManager("Cell_World", Assembly.GetAssembly(typeof(World)));
			//ビットマップの読み込み
			//地形は「野原:0」、「山:1」、「河川:2」、「食物：3」
			Terrain_Bmp[0] = (Bitmap)rm.GetObject("Field");
			Terrain_Bmp[1] = (Bitmap)rm.GetObject("Mountain");
			Terrain_Bmp[2] = (Bitmap)rm.GetObject("River");
			Terrain_Bmp[3] = (Bitmap)rm.GetObject("Food");
			//Cellは「ピンク:0」、「ブルー:1」、「グリーン:2」、「モノ（死亡）:3」
			Cell_Bmp[0] = (Bitmap)rm.GetObject("Cell-P");
			Cell_Bmp[1] = (Bitmap)rm.GetObject("Cell-B");
			Cell_Bmp[2] = (Bitmap)rm.GetObject("Cell-G");
			Cell_Bmp[3] = (Bitmap)rm.GetObject("Cell-D");
			//アバターCell用
			Cell_Bmp[Max_Tribe] = (Bitmap)rm.GetObject("Cell-Me");
			//「世界」の初期化
			Init();
		}

		//デストラクター
		~World()
		{
			//「世界」の初期化
			Init();									//「世界」の初期化
			//ビットマップの廃棄
			for(int i = 0; i < Max_Tribe; i++)
			{
				Terrain_Bmp[i].Dispose();
				Cell_Bmp[i].Dispose();
			}
			//アバターCell用
			Cell_Bmp[Max_Tribe].Dispose();
			//描画関係終了処理
			if(gHandle != null)
				gHandle.Dispose();					//グラフィックリソースの開放
			if(Canvas != null)
				Canvas.Dispose();					//ビットマップリソースの開放
		}

		/////////////////////
		//ゲーム関係メソッド
		/////////////////////
		public void Init()							//「世界」の初期化
		{
			//MapとPrevMapの初期化（新しいC#ではArray.Fill）
			for(int i = 0; i < Map.Length; i++)
			{
				Map[i] = '\0';		//オリジナルの「文字」マップ
				PrevMap[i] = -1;	//「文字」マップに基づく論理マップ
			}
			//再ゲームも考えられるのでGCに任せる
			CellList.Clear();						//Cellのリストを初期化
			Gameover = false;						//ゲーム開始
			Message = String.Empty;					//メッセージの初期化
			//既存の仮想画面、グラフィックハンドルがあれば廃棄する
			if(gHandle != null)
				gHandle.Dispose();
			if(Canvas != null)
				Canvas.Dispose();
			//指定サイズ（16 x 16）のビットマップ仮想画面（80 x 40）の作成
			Canvas = new Bitmap(16 * Wld_Width, 16 * Wld_Height);
			//Graphicsクラス（アンチエイリアス）
			gHandle = Graphics.FromImage(Canvas);
			gHandle.SmoothingMode = SmoothingMode.AntiAlias;
			gHandle.PixelOffsetMode = PixelOffsetMode.HighQuality;
			//背景表示
			if(Read_Map("world_terrain.trn"))
				ShowMap();
		}

		public void GameOver()						//強制終了
		{
			//ゲーム終了処理
			Gameover = true;
		}

		public bool Is_GameOver()					//ゲーム終了サインの取得
		{
			return Gameover;
		}

		public string Get_Message()					//ゲーム終了時のメッセージを取得
		{
			return Message;
		}

		public bool Read_Map(string fn)				//「世界」の地図を読み込む
		{
			string data = "";
			try
			{
				using(StreamReader file = new StreamReader(fn, Encoding.UTF8))	//入力UTF-8
				{
					data = file.ReadToEnd();		//ファイルを読む
					file.Close();					//ファイルを閉じる
				}
			}
			catch(FileNotFoundException e)			//FileNotFoundException用
			{
				string errMessage = "地形ファイル（" + fn + "）を読み込めませんでした" + Environment.NewLine;
				MessageBox.Show(errMessage + e.Message , "ファイル読込エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				Message += errMessage;
				return false;
			}
			catch(Exception e)						//FileNotFoundException以外用
			{
				MessageBox.Show("その他エラーが発生しました。\r\n" + e.Message , "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
			//文字列の行分割
			string[] lines = data.Split(new[]{"\r\n","\n","\r"}, StringSplitOptions.None);
			//エラーチェック
			if(lines.Length != Wld_Height)
			{
				MessageBox.Show("正しい地形ファイルではありません。" , "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
			else
			{
				data = String.Empty;
				foreach(string line in lines)
					data += line;
				Map = data.ToCharArray();
			}
			return true;
		}

		public int Check_What(int x, int y)			//Mapの桝目をチェックし、何があるかを返す（野原:0、山:1、河川:2、食物：3、セル：4 + m_id、それ以外：-1）
		{
			int val = Not_Found;	//戻り値
			//エラーチェック
			if(x >= Wld_Width || x < 0 || y >= Wld_Height || y < 0)
				return val;
			Cell c;					//周囲にCellがいる場合のID取得用
			switch(Map[y * Wld_Width + x])
			{
				case '\0':			//「NULL(0X0)」 - 0
				case ' ':			//「野原(0X20)」- 0
					val = 0;
					break;
				case '^':			//「山(0X5E)」  - 1
					val = 1;
					break;
				case '~':			//「河川(0X7E)」- 2
					val = 2;
					break;
				case 'O':			//「食物(0X4F)」- 3
					val = 3;
					break;
				case 'C':			//「cell(0X43)」- 4 + ID
					c = Get_Cell(x, y);	//その位置にいるセルのポインターを取得
					val = 4 + c.ID;		//セルであることとIDを通知する
					break;
				default:			//エラー処理
					Message += "地形地図に規定外のもの（" + Map[y * Wld_Width + x].ToString() + "）が発見されました" + Environment.NewLine;
					break;
			}
			return val;
		}

		public bool Create_Cells(int n, bool intmarg)	//指定個数のcellを作る
		{
			//開始時のセルの数を記録
			if(Ini_pop == 0)	Ini_pop = n;
			//cellの生成
			for(int i = 0; i < n; i++)
			{
				Cell c = new Cell(intmarg);				//Cellインスタンスを生成
				//誕生位置決定
				while(true)
				{
					//新たなCellのX、Y座標を乱数で求め、
					Point loc = new Point(rand.Next() % Wld_Width, rand.Next() % Wld_Height);
					//そこが「野原(0)」か否かチェック
					if(Check_What(loc.X, loc.Y) == 0)
					{
						c.Born_At(CellList.Count, loc.X, loc.Y);	//空白であれば誕生位置として登録
						Map[loc.Y * Wld_Width + loc.X] = 'C';		//Cellをマップに書き込む
						Check_Around(c);							//Cellの周囲情報を取得させる
						break;
					}
				}
				CellList.Add(c);						//セルリストへ登録
			}
			return true;
		}

		public int How_Many_Cells()						//m_celllistの登録されたcellの数を返す
		{
			return CellList.Count;
		}

		public void Check_Around(Cell c)				//周囲の状況をチェックし、指定cellのAround[8]を更新する
		{
			int[] around = c.Around;					//Cell周囲の存在物（野原:0、山:1、河川:2、食物：3、セル：4 + ID）
			Point loc = c.Where();						//CellのLocationを取得
			//エラーチェック（圏外は-1）
			if(loc.Y == 0)								//上チェック不要
			{
				if(loc.X % Wld_Width == 0)				//左チェック不要
				{
					//around[0, 1, 5, 6, 7]は不要
					around[0] = around[1] = around[5] = around[6] = around[7] = Not_Found;
					around[2] = Check_What(loc.X + 1, loc.Y);
					around[3] = Check_What(loc.X + 1, loc.Y + 1);
					around[4] = Check_What(loc.X, loc.Y + 1);
				}
				else if(loc.X % Wld_Width == Wld_Width - 1)	//右チェック不要
				{
					//around[0, 1, 2, 3, 7]は不要
					around[0] = around[1] = around[2] = around[3] = around[7] = Not_Found;
					around[4] = Check_What(loc.X, loc.Y + 1);
					around[5] = Check_What(loc.X - 1, loc.Y + 1);
					around[6] = Check_What(loc.X - 1, loc.Y);
				}
				else									//左右チェック要
				{
					//around[0, 1, 7]は不要
					around[0] = around[1] = around[7] = Not_Found;
					around[2] = Check_What(loc.X + 1, loc.Y);
					around[3] = Check_What(loc.X + 1, loc.Y + 1);
					around[4] = Check_What(loc.X, loc.Y + 1);
					around[5] = Check_What(loc.X - 1, loc.Y + 1);
					around[6] = Check_What(loc.X - 1, loc.Y);
				}
			}
			else if(loc.Y == Wld_Height - 1)			//下チェック不要
			{
				if(loc.X % Wld_Width == 0)				//左チェック不要
				{
					//around[3, 4, 5, 6, 7]は不要
					around[3] = around[4] = around[5] = around[6] = around[7] = Not_Found;
					around[0] = Check_What(loc.X, loc.Y - 1);
					around[1] = Check_What(loc.X + 1, loc.Y - 1);
					around[2] = Check_What(loc.X + 1, loc.Y);
				}
				else if(loc.X % Wld_Width == Wld_Width - 1)	//右チェック不要
				{
					//around[1, 2, 3, 4, 5]は不要
					around[1] = around[2] = around[3] = around[4] = around[5] = Not_Found;
					around[0] = Check_What(loc.X, loc.Y - 1);
					around[6] = Check_What(loc.X - 1, loc.Y);
					around[7] = Check_What(loc.X - 1, loc.Y - 1);
				}
				else									//左右チェック要
				{
					//around[3, 4, 5]は不要
					around[3] = around[4] = around[5] = Not_Found;
					around[0] = Check_What(loc.X, loc.Y - 1);
					around[1] = Check_What(loc.X + 1, loc.Y - 1);
					around[2] = Check_What(loc.X + 1, loc.Y);
					around[6] = Check_What(loc.X - 1, loc.Y);
					around[7] = Check_What(loc.X - 1, loc.Y - 1);
				}
			}
			else										//上下チェック要
			{
				if(loc.X % Wld_Width == 0) {			//左チェック不要
					//around[5, 6, 7]は不要
					around[5] = around[6] = around[7] = Not_Found;
					around[0] = Check_What(loc.X, loc.Y - 1);
					around[1] = Check_What(loc.X + 1, loc.Y - 1);
					around[2] = Check_What(loc.X + 1, loc.Y);
					around[3] = Check_What(loc.X + 1, loc.Y + 1);
					around[4] = Check_What(loc.X, loc.Y + 1);
				}
				else if(loc.X % Wld_Width == Wld_Width - 1) {	//右チェック不要
					//around[1, 2, 3]は不要
					around[1] = around[2] = around[3] = Not_Found;
					around[0] = Check_What(loc.X, loc.Y - 1);
					around[4] = Check_What(loc.X, loc.Y + 1);
					around[5] = Check_What(loc.X - 1, loc.Y + 1);
					around[6] = Check_What(loc.X - 1, loc.Y);
					around[7] = Check_What(loc.X - 1, loc.Y - 1);
				}
				else {									//左右チェック要
					//全て必要
					around[0] = Check_What(loc.X, loc.Y - 1);
					around[1] = Check_What(loc.X + 1, loc.Y - 1);
					around[2] = Check_What(loc.X + 1, loc.Y);
					around[3] = Check_What(loc.X + 1, loc.Y + 1);
					around[4] = Check_What(loc.X, loc.Y + 1);
					around[5] = Check_What(loc.X - 1, loc.Y + 1);
					around[6] = Check_What(loc.X - 1, loc.Y);
					around[7] = Check_What(loc.X - 1, loc.Y - 1);
				}
			}
		}

		public Cell Get_Cell(int n)						//CellListの指定番目のセルを返す
		{
			return CellList[n];
		}

		public Cell Get_Cell(int x, int y)				//座標位置にあるセルを返す
		{
			int LastCell = CellList.Count;
			for(int i = 0; i < LastCell; i++)
			{
				Point loc = CellList[i].Where();
				if(loc.X == x && loc.Y == y)
					return CellList[i];
			}
			return null;
		}

		public string Get_Distribution()				//ピンク、ブルー、グリーンの生死状況を返す
		{
			//Tribe_Statusの初期化
			for(int i = 0; i < Tribe_Status.Length; i++)
				Tribe_Status[i] = 0;
			int LastCell = CellList.Count;
			for(int i = 0; i < LastCell; i++)
			{
				switch(CellList[i].Tribe)
				{
					case 0:		//ピンク
						Tribe_Status[0]++;
						break;
					case 1:		//ブルー
						Tribe_Status[1]++;
						break;
					case 2:		//グリーン
						Tribe_Status[2]++;
						break;
					default:	//死亡（モノ）
						Tribe_Status[3]++;
						break;
				}
			}
			string Distribution = "－－－－－－－－－－" + Environment.NewLine
								+ "ピンク　セル：" + Tribe_Status[0].ToString() + Environment.NewLine
								+ "ブルー　セル：" + Tribe_Status[1].ToString() + Environment.NewLine
								+ "グリーンセル：" + Tribe_Status[2].ToString() + Environment.NewLine
								+ "死亡　　セル：" + Tribe_Status[3].ToString();
			return 	Distribution;
		}

		public string Show_Cell_Param()					//総てのcell属性を表示する
		{
			string parameters = String.Empty;
			int LastCell = CellList.Count;
			for(int i = 0; i < LastCell; i++)
			{
				parameters += CellList[i].Show_Param();
				if(i == MyID)	//アバターを指定している場合にアバターのCellについて修正する
				{
					parameters = parameters.TrimEnd('\r', '\n') + " - My avatar" + Environment.NewLine; 
				}
			}
			return parameters;
		}

		public void Goes_Around()						//「世界が廻る（時が過ぎる）」→セルに日常活動を行わせる
		{
			if(!Gameover)
			{
				//最大人口超の場合
				if(CellList.Count > Max_Population)
				{
					Gameover = true;					//ゲームオーバー
					Message += "現在の人口過密が異常となりました！（人口爆発）" + 
								Environment.NewLine + Get_Distribution() +
								Environment.NewLine + "（詳細はログを参照ねがいます。）";
					return;
				}
				bool extinction = true;					//絶滅チェッカー
				int LastCell = CellList.Count;
				for(int i = 0; i < LastCell; i++)		//"foreach"は配列が変化するとエラーになる為
				{
					Cell cell = CellList[i];			//IDから対象セルを求める
					cell.VitalCheck();					//対象セルの生死状態をチェック
					if(cell.Alive)						//生存している場合
					{
						Check_Around(cell);				//対象セルの周囲を確認する
						Point loc = cell.Where();		//対象セルの位置を取得
						Map[loc.Y * Wld_Width + loc.X] = ' ';	//対象セルの旧座標を' 'にする
						//周囲のセルの有無を確認する
						Cell y = null;					//周囲のセル
						int dir = Not_Found;			//周囲のセルのいる方向
						int val = cell.Find_Cell();		//対象セルの周囲にセルがいるか確認
						if(val != Not_Found)			//周囲にセルが見つかったならば
						{
							dir = val & 0x0F;			//dirは周囲のセルの絶対方向（0 - 7）
							y = Get_Cell(val >> 4);		//周囲のセルのポインターを取得
						}
						//コンピューター処理とマニュアル処理へ分岐させる
						if(i == MyID && cell.Alive)		//ユーザー判断による処理（アバターの場合）
							AvatarProcess(this, cell, y, dir);
						else							//コンピューター判断による処理
							AutoProcess(cell, y, dir);
						loc = cell.Where();				//対象セルの移動があり得るので再取得
						Map[loc.Y * Wld_Width + loc.X] = 'C';	//マップのセルxの新座標を'C'にする
						cell.Aging();					//老化による減衰と生命力消耗
						cell.Param_Change();			//状況変化から各種パラメーターを調整
						//絶滅チェック（一つでもAliveがtrueであればfalse）
						extinction = false;
					}
					cell.VitalCheck();					//活動後の対象セルの生死状態をチェック
				}
				if(extinction)							//全滅により終了
				{
					Gameover = true;
					Message += "全セルが死亡しました！（全滅）" + 
								Environment.NewLine + Get_Distribution() +
								Environment.NewLine + "（詳細はログを参照ねがいます。）";
				}
			}
		}

		private void AvatarProcess(World world, Cell cell, Cell y, int dir)
		{
			AvatarController ac = new AvatarController(world, cell, y, dir);
			//Worldクラスインスタンスを持つ親フォームの右隣に表示する
			ac.StartPosition = FormStartPosition.Manual;//ダイアログ位置を任意指定
			Form parent = this.FindForm();				//親フォーム
			ac.Location = new Point(parent.Location.X + parent.Width, parent.Location.Y);
			ac.ShowDialog(this);
			ac.Dispose();
			if(dir != Not_Found)						//yが存在しない場合もあるので
				y.VitalCheck();							//活動後の相手セルの生死状態をチェック
		}

		private void AutoProcess(Cell cell, Cell y, int dir)
		{
			if(dir != Not_Found)						//周囲にセルが見つかったならば
			{
				y.VitalCheck();							//相手セルの生死状態をチェック
				if(y.Alive)								//相手セルが生きていれば
				{
					if(cell.Intmarg)					//異種族婚を許可しているか
					{
						//【調整項目】
						if(cell.Affection < 30 &&		//愛着性が30未満で
							cell.Hostility > 70)		//敵対性が70超であれば
							Intimidate(cell, y, dir);	//相互に威嚇する
						else if(cell.Affection > 40 &&	//愛着性が40超で
							cell.Hostility < 50)		//敵対性が50未満であれば
							Get_Close(cell, y, dir);	//親交を結ぶ
						else							//それ以外は
							Flee(cell, y, dir);			//相手から離れる
					}
					else								//異種族婚が認められなければ
					{
						if(cell.Tribe != y.Tribe)		//異種族なら
							Intimidate(cell, y, dir);	//相互に威嚇する
						else							//同種族であっても
						{
							//【調整項目】
							if(cell.Affection < 30 &&	//愛着性が30未満で
								cell.Hostility > 70)	//敵対性が70超であれば
								Intimidate(cell, y, dir);//相互に威嚇する
							else if(cell.Affection > 40 &&	//愛着性が40超で
								cell.Hostility < 50)	//敵対性が50未満であれば
								Get_Close(cell, y, dir);//親交を結ぶ
							else						//敵対が強ければ
								Flee(cell, y, dir);		//相手から離れる
						}
					}
					y.VitalCheck();						//活動後の相手セルの生死状態をチェック
				}
				else									//死んでいれば食物と同じ扱いとなる
				{
					cell.Get_Food(dir);					//移動して摂食する
				}
			}
			else										//周囲にセルがいないならば
			{
				dir = cell.Find_Food();					//周囲に食物があるかどうか確認する
				if(dir != Not_Found)					//あれば移動して、摂食する
					cell.Get_Food(dir);
				else
				{
					dir = cell.Find_Field();			//周囲に野原があるかどうか確認する
					if(dir != Not_Found)				//あれば移動する
						cell.Get_Move(dir);
				}
			}
		}

		public void Get_Close(Cell x, Cell y, int dir)	//親しくなり、愛着性が高まり、敵対性が低まる
		{
			//セルx, y両者の愛着性が50%を超える場合、交尾に進む
			if(x.Affection > 60 && y.Affection > 60)	//【調整項目】
				Make_Love(x, y, dir);
			//そうでなければセルx, y両者の愛着性が増え、敵対性が減る
			else {
				x.Affection += Increase;
				y.Affection += Increase;
				x.Hostility += Decrease;
				y.Hostility += Decrease;
			}
		}

		public void Make_Love(Cell x, Cell y, int dir)	//一定の愛着性を超えると交尾し、生殖力により出産し、相手を摂食する
		{
			//xと同種族のセルが何処か（！）に誕生する
			if(x.Fertility > 50)						//【調整項目】50だとなかなか生まない
			{
				int n = CellList.Count;		//次のIDを控える
				Create_Cells(1, x.Intmarg);	//xと同じIntmargのセルを生成
				Cell z = Get_Cell(n);		//新生セルのポインターを取得
				z.Tribe = x.Tribe;			//新生セルをxと同じ種族に設定
				//【調整項目】出産後、相手yを殺し、摂食する
				//y.Killed();
				//x.Get_Food(dir);
			}
			else	//離別（逃走）する
				Flee(x, y, dir);
		}

		public void Intimidate(Cell x, Cell y, int dir)	//敵対性と愛着性の度合いにより、相手を威嚇し、敵対性が高まり、愛着性が低まる
		{
			//セルx, y両者の敵対性が50%を超える場合、闘争に進む
			if(x.Hostility > 50 && y.Hostility > 50)	//【調整項目】
				Fight(x, y, dir);
			//そうでなければセルx, y両者の敵対性が増え、愛着性が減る
			else
			{
				x.Affection += Decrease;
				y.Affection += Decrease;
				x.Hostility += Increase;
				y.Hostility += Increase;
			}
		}

		public void Fight(Cell x, Cell y, int dir)		//異種族婚許可、敵対性により、相互に攻撃、被害を受ける
		{
			//相手の攻撃力が自分の攻撃力よりMAX_PARAM / 4（25）以上、又は
			//相手の生命力が自分の生命力の倍以上あれば
			if((y.Power > x.Power + Max_Param / 4) ||
				(y.Power > x.Power * 2))
				Flee(x, y, dir);								//逃走する
			else {
				//xの先制攻撃（xの攻撃力がyの防御力を上回る場合、被害を与える）
				y.Damaged(x.Power - y.Defense);
				//yの後攻攻撃
				x.Damaged(y.Power - x.Defense);
			}
		}

		public void Flee(Cell x, Cell y, int dir)		//敵対状態になっても、攻撃力、防御力の差が大きければ逃走する
		{
			int reverse = x.Find_Field(false, dir);		//相手yの反対方向の野原を探す
			x.Get_Move(reverse);						//逃走する
		}

		public void Make_Log()							//WorldのCell情報をログに記録
		{
			if(CellList.Count > 0)
			{
				//セルデータの出力ファイル名（"CellOf(yyyy-mm-dd_hh_mm)from<Ini_Pop>.txt"）
				string strNow = DateTime.Now.ToString("yyyy-MM-dd_HH_mm");
			 	string path = ".\\Log\\CellsOf(" + strNow + ")from" + Ini_pop.ToString() + ".txt";
				//ファイル出力
				using (StreamWriter file = new StreamWriter(path, false, Encoding.UTF8))
				{
					file.Write(Show_Cell_Param());		//ファイルを書く
					file.Close();						// ファイルを閉じる
				}
			}
		}

		///////////////////
		//描画関係メソッド
		///////////////////
		//画面消去
		public void Clear()
		{
			gHandle.Clear(this.BackColor);
		}

		//背景（m_map）を表示する
		public void ShowMap()
		{
			bool changed = false;						//m_Worldのマップとm_PrevMapとの差異フラグ
			for(int j = 0; j < Wld_Height; j++)			//Y座標
			{
				for(int i = 0; i < Wld_Width; i++)		//X座標
				{
					//ビットマップ表示
					int n = Check_What(i, j);			//(i, j)の位置に何があるか
					if(PrevMap[Wld_Width * j + i] != n)	//前回から変更があれば
					{
						PrevMap[Wld_Width * j + i] = n;	//記録して
						changed = true;					//差異フラグを立てる
					}
					Cell c;								//Cell
					switch(n)
					{
						case 0:	//野原
						case 1:	//山
						case 2:	//河川
						case 3:	//食物
							if(changed)					//前回から変更があれば
								gHandle.DrawImage(Terrain_Bmp[n], i * 16, j * 16);
							break;
						default:
							if(n > 3)					//Cell（4 + ID）の場合
							{
								c = Get_Cell(i, j);		//(i, j)の位置あるCellを取得
								if(c.ID == MyID && c.Alive)	//アバターの場合
									gHandle.DrawImage(Cell_Bmp[Max_Tribe], i * 16, j * 16);
								else						//アバターではない場合
									gHandle.DrawImage(Cell_Bmp[c.Tribe], i * 16, j * 16);
							}
							else if(n == -1)
								MessageBox.Show("地形ファイル（*.trn）に許容されない文字が含まれています。",
												"エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
						break;
					}
				}
				if(changed)		//変化が一つでもあれば、World（描画領域）を更新
					this.Image = (Image)Canvas;
			}
		}
	}

	//////////////////////////////
	//AvatarController ダイアログ
	//（最長3秒で自動的に閉じる）
	//////////////////////////////
	class AvatarController : Form
	{
		///////////////////////
		//定数定義（変更不可）
		///////////////////////
		const int Wld_Width = 80;		//Worldの幅（セル数）
		const int Max_Dir = 8;			//↑:0、↗:1、→:2、↘:3、↓:4、↙:5、←:6、↖:7
		const int Not_Found = -1;		//Find_***処理用
		//クラスフィールド
		World wld;						//Worldクラスインスタンス
		private Cell cell;				//自分（Avatar）セル自身
		private Cell you;				//遭遇する他のCell
		private int yDir;				//遭遇する他のCellの方向
		private int fDir = Not_Found;	//食べ物の方向
		//ダイアログコントロール
		//グループボックス
		GroupBox gBox;
		GroupBox gBoxFood;
		GroupBox gBoxMove;
		//ラベル
		private Label lblMe;
		private Label lblYou;
		private Label lblTribe;
		private Label lblAffection;
		private Label lblHostility;
		private Label lblMeTribe;
		private Label lblMeAffection;
		private Label lblMeHostility;
		private Label lblYouTribe;
		private Label lblYouAffection;
		private Label lblYouHostility;
		//チェックボックス
		private CheckBox InterMarriage;
		//ボタン
		private Button btnGetClose;		//親交
		private Button btnIntimidate;	//威嚇
		private Button btnFight;		//闘争
		private Button btnFlee;			//逃走
		private Button btnEat;			//摂食
		private Button[] btnDir;		//移動
		private Button btnPass;			//パス（何もしない）
		//自動終了タイマー
		Timer dlgTimer;

		//worldはcのいる世界、dirがNot_Foundでなければ、遭遇した他のセルがy（nullでない）
		public AvatarController(World world, Cell c, Cell y, int dir)
		{
			//引数の記録
			wld = world;
			cell = c;
			you = y;
			yDir = dir;
			//ダイアログの属性設定
			this.Text = "アバターコントローラー";
			this.ClientSize = new Size(320, 460);
			this.ControlBox = false;	//システムボタンを無効化
			this.ShowInTaskbar = true;	//タスクバー上表示
			this.FormBorderStyle = FormBorderStyle.FixedDialog;	//境界のスタイル
			this.StartPosition = FormStartPosition.CenterScreen;//画面中央
			InitControls();				//コントロールの配置
			SetControls(cell);			//コントロールの初期設定
			//3秒で閉じる設定にする
			dlgTimer = new Timer();
			dlgTimer.Tick += new EventHandler(OnPass_Click);
    		dlgTimer.Interval = 3000;
   			dlgTimer.Start();
		}

		private void InitControls()
		{
			//フォームのレイアウトを一時停止
			this.SuspendLayout();
			//グループボックス（相手セルへの対応）
			gBox = new GroupBox();
			gBox.Location = new Point(10, 10);
			gBox.Size = new Size(ClientSize.Width - 20, 180);
			gBox.Anchor = (AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom | AnchorStyles.Left);
			gBox.Enabled = false;		//初期状態は使用不可
			gBox.Text = "遭遇したCellへの対応";
			//チェックボックスの属性設定
			InterMarriage = new CheckBox();
			InterMarriage.Location = new Point(10, 16);
			InterMarriage.Size = new Size(ClientSize.Width - 40, 18);
			InterMarriage.CheckAlign = ContentAlignment.MiddleRight;
			InterMarriage.TextAlign = ContentAlignment.MiddleLeft;
			InterMarriage.Text = "異種族婚許可";
			InterMarriage.AutoCheck = false;	//ユーザー変更不可
			//ラベルの属性設定
			lblTribe = new Label();
			lblTribe.Size = new Size(60, 18);
			lblTribe.Location = new Point(10, 68);
			lblTribe.BorderStyle = BorderStyle.Fixed3D;
			lblTribe.Text = "種族";
			lblTribe.TextAlign = ContentAlignment.MiddleCenter;
			lblTribe.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblAffection = new Label();
			lblAffection.Size = new Size(60, 18);
			lblAffection.Location = new Point(10, 94);
			lblAffection.BorderStyle = BorderStyle.Fixed3D;
			lblAffection.Text = "愛着性";
			lblAffection.TextAlign = ContentAlignment.MiddleCenter;
			lblAffection.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblHostility = new Label();
			lblHostility.Size = new Size(60, 18);
			lblHostility.Location = new Point(10, 120);
			lblHostility.BorderStyle = BorderStyle.Fixed3D;
			lblHostility.Text = "	敵対性";
			lblHostility.TextAlign = ContentAlignment.MiddleCenter;
			lblHostility.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblMe = new Label();
			lblMe.Size = new Size(100, 18);
			lblMe.Location = new Point(80, 42);
			lblMe.BorderStyle = BorderStyle.Fixed3D;
			lblMe.Text = "アバターセル";
			lblMe.TextAlign = ContentAlignment.MiddleCenter;
			lblMe.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblMe.BackColor = Color.SkyBlue;
			lblMeTribe = new Label();
			lblMeTribe.Size = new Size(100, 18);
			lblMeTribe.Location = new Point(80, 68);
			lblMeTribe.BorderStyle = BorderStyle.Fixed3D;
			lblMeTribe.Text = "";
			lblMeTribe.TextAlign = ContentAlignment.MiddleCenter;
			lblMeTribe.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblMeTribe.BackColor = Color.SkyBlue;
			lblMeAffection = new Label();
			lblMeAffection.Size = new Size(100, 18);
			lblMeAffection.Location = new Point(80, 92);
			lblMeAffection.BorderStyle = BorderStyle.Fixed3D;
			lblMeAffection.Text = "";
			lblMeAffection.TextAlign = ContentAlignment.MiddleCenter;
			lblMeAffection.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblMeAffection.BackColor = Color.SkyBlue;
			lblMeHostility = new Label();
			lblMeHostility.Size = new Size(100, 18);
			lblMeHostility.Location = new Point(80, 120);
			lblMeHostility.BorderStyle = BorderStyle.Fixed3D;
			lblMeHostility.Text = "";
			lblMeHostility.TextAlign = ContentAlignment.MiddleCenter;
			lblMeHostility.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblMeHostility.BackColor = Color.SkyBlue;
			lblYou = new Label();
			lblYou.Size = new Size(100, 18);
			lblYou.Location = new Point(190, 42);
			lblYou.BorderStyle = BorderStyle.Fixed3D;
			lblYou.Text = "相手のセル";
			lblYou.TextAlign = ContentAlignment.MiddleCenter;
			lblYou.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblYou.BackColor = Color.Violet;
			lblYouTribe = new Label();
			lblYouTribe.Size = new Size(100, 18);
			lblYouTribe.Location = new Point(190, 68);
			lblYouTribe.BorderStyle = BorderStyle.Fixed3D;
			lblYouTribe.Text = "";
			lblYouTribe.TextAlign = ContentAlignment.MiddleCenter;
			lblYouTribe.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblYouTribe.BackColor = Color.Violet;
			lblYouAffection = new Label();
			lblYouAffection.Size = new Size(100, 18);
			lblYouAffection.Location = new Point(190, 92);
			lblYouAffection.BorderStyle = BorderStyle.Fixed3D;
			lblYouAffection.Text = "";
			lblYouAffection.TextAlign = ContentAlignment.MiddleCenter;
			lblYouAffection.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblYouAffection.BackColor = Color.Violet;
			lblYouHostility = new Label();
			lblYouHostility.Size = new Size(100, 18);
			lblYouHostility.Location = new Point(190, 120);
			lblYouHostility.BorderStyle = BorderStyle.Fixed3D;
			lblYouHostility.Text = "";
			lblYouHostility.TextAlign = ContentAlignment.MiddleCenter;
			lblYouHostility.Font = new Font("MS明朝", 8, FontStyle.Regular);
			lblYouHostility.BackColor = Color.Violet;
			//ボタンの属性設定
			btnGetClose = new Button();				//親交
			btnGetClose.Size = new Size(60, 24);
			btnGetClose.Location = new Point(10, 148);
			btnGetClose.Text = "親交";
			btnGetClose.BackColor = Color.LimeGreen;
			btnGetClose.Click += new EventHandler(OnGetClose_Click);
			btnIntimidate = new Button();			//威嚇
			btnIntimidate.Size = new Size(60, 24);
			btnIntimidate.Location = new Point(82, 148);
			btnIntimidate.Text = "威嚇";
			btnIntimidate.BackColor = Color.Orange;
			btnIntimidate.Click += new EventHandler(OnIntimidate_Click);
			btnFight = new Button();				//闘争
			btnFight.Size = new Size(60, 24);
			btnFight.Location = new Point(154, 148);
			btnFight.Text = "闘争";
			btnFight.BackColor = Color.Red;
			btnFight.Click += new EventHandler(OnFight_Click);
			btnFlee = new Button();					//逃走
			btnFlee.Size = new Size(60, 24);
			btnFlee.Location = new Point(226, 148);
			btnFlee.Text = "逃走";
			btnFlee.BackColor = Color.DeepSkyBlue;
			btnFlee.Click += new EventHandler(OnFlee_Click);
			//帰属関係設定
			gBox.Controls.Add(InterMarriage);
			gBox.Controls.Add(lblMe);
			gBox.Controls.Add(lblMeTribe);
			gBox.Controls.Add(lblMeAffection);
			gBox.Controls.Add(lblMeHostility);
			gBox.Controls.Add(lblYou);
			gBox.Controls.Add(lblYouTribe);
			gBox.Controls.Add(lblYouAffection);
			gBox.Controls.Add(lblYouHostility);
			gBox.Controls.Add(lblTribe);
			gBox.Controls.Add(lblAffection);
			gBox.Controls.Add(lblHostility);
			gBox.Controls.Add(btnGetClose);
			gBox.Controls.Add(btnIntimidate);
			gBox.Controls.Add(btnFight);
			gBox.Controls.Add(btnFlee);
			this.Controls.Add(gBox);
			//グループボックス（食物への対応）
			gBoxFood = new GroupBox();
			gBoxFood.Location = new Point(10, gBox.Height + 20);
			gBoxFood.Size = new Size(ClientSize.Width - 20, 48);
			gBoxFood.Anchor = (AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom | AnchorStyles.Left);
			gBoxFood.Text = "食物への対応";
			gBoxFood.Enabled = false;	//初期状態は使用不可
			//ボタンの属性設定
			btnEat = new Button();
			btnEat.Size = new Size(gBoxFood.Width - 40, 24);
			btnEat.Location = new Point(20, 16);
			btnEat.Text = "食べる";
			btnEat.BackColor = Color.LawnGreen;
			btnEat.Click += new EventHandler(OnEat_Click);
			//帰属関係設定
			gBoxFood.Controls.Add(btnEat);
			this.Controls.Add(gBoxFood);
			//グループボックス（移動対応）
			gBoxMove = new GroupBox();
			gBoxMove.Location = new Point(10, gBox.Height + gBoxFood.Height + 30);
			gBoxMove.Size = new Size(ClientSize.Width - 20, 160);
			gBoxMove.Anchor = (AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom | AnchorStyles.Left);
			gBoxMove.Text = "移動対応";
			//ボタンの属性設定
			btnDir  = new Button[8];	//↑:0、1、→:2、3、↓:4、5、←:6、7
			int btnW = 40, btnH = 40;
			int posX = (gBoxMove.Width - btnW * 3 - 8) / 2;
			int posY = 20;
			//本プログラムのリソースマネージャー作成
			ResourceManager rm = new ResourceManager("Cell_World", Assembly.GetAssembly(typeof(World)));
			Bitmap bmp;
			btnDir[0] = new Button();
			btnDir[0].Size = new Size(btnW, btnH);
			btnDir[0].Location = new Point(posX + btnW + 4, posY);
			btnDir[0].BackColor = Color.LightCyan;
			btnDir[0].Click += new EventHandler(OnUp_Click);
			bmp = (Bitmap)rm.GetObject("U");	//ビットマップの読み込み
			bmp.MakeTransparent(Color.White);
			btnDir[0].Image = bmp;
			btnDir[0].Enabled = false;	//初期状態は使用不可
			btnDir[1] = new Button();
			btnDir[1].Size = new Size(btnW, btnH);
			btnDir[1].Location = new Point(posX + (btnW + 4) * 2, posY);
			btnDir[1].BackColor = Color.LightCyan;
			btnDir[1].Click += new EventHandler(OnUpRight_Click);
			bmp = (Bitmap)rm.GetObject("UR");	//ビットマップの読み込み
			bmp.MakeTransparent(Color.White);
			btnDir[1].Image = bmp;
			btnDir[1].Enabled = false;	//初期状態は使用不可
			btnDir[2] = new Button();
			btnDir[2].Size = new Size(btnW, btnH);
			btnDir[2].Location = new Point(posX + btnW * 2 + 8, posY + btnH + 4);
			btnDir[2].BackColor = Color.LightCyan;
			btnDir[2].Click += new EventHandler(OnRight_Click);
			bmp = (Bitmap)rm.GetObject("R");	//ビットマップの読み込み
			bmp.MakeTransparent(Color.White);
			btnDir[2].Image = bmp;
			btnDir[2].Enabled = false;	//初期状態は使用不可
			btnDir[3] = new Button();
			btnDir[3].Size = new Size(btnW, btnH);
			btnDir[3].Location = new Point(posX + (btnW + 4) * 2, posY + btnH * 2 + 8);
			btnDir[3].BackColor = Color.LightCyan;
			btnDir[3].Click += new EventHandler(OnDownRight_Click);
			bmp = (Bitmap)rm.GetObject("DR");	//ビットマップの読み込み
			bmp.MakeTransparent(Color.White);
			btnDir[3].Image = bmp;
			btnDir[3].Enabled = false;	//初期状態は使用不可
			btnDir[4] = new Button();
			btnDir[4].Size = new Size(btnW, btnH);
			btnDir[4].Location = new Point(posX + btnW + 4, posY + btnH * 2 + 8);
			btnDir[4].Click += new EventHandler(OnDown_Click);
			btnDir[4].BackColor = Color.LightCyan;
			bmp = (Bitmap)rm.GetObject("D");	//ビットマップの読み込み
			bmp.MakeTransparent(Color.White);
			btnDir[4].Image = bmp;
			btnDir[4].Enabled = false;	//初期状態は使用不可
			btnDir[5] = new Button();
			btnDir[5].Size = new Size(btnW, btnH);
			btnDir[5].Location = new Point(posX, posY + btnH * 2 + 8);
			btnDir[5].BackColor = Color.LightCyan;
			btnDir[5].Click += new EventHandler(OnDownLeft_Click);
			bmp = (Bitmap)rm.GetObject("DL");	//ビットマップの読み込み
			bmp.MakeTransparent(Color.White);
			btnDir[5].Image = bmp;
			btnDir[5].Enabled = false;	//初期状態は使用不可
			btnDir[6] = new Button();
			btnDir[6].Size = new Size(btnW, btnH);
			btnDir[6].Location = new Point(posX, posY + btnH + 4);
			btnDir[6].BackColor = Color.LightCyan;
			btnDir[6].Click += new EventHandler(OnLeft_Click);
			bmp = (Bitmap)rm.GetObject("L");	//ビットマップの読み込み
			bmp.MakeTransparent(Color.White);
			btnDir[6].Image = bmp;
			btnDir[6].Enabled = false;	//初期状態は使用不可
			btnDir[7] = new Button();
			btnDir[7].Size = new Size(btnW, btnH);
			btnDir[7].Location = new Point(posX, posY);
			btnDir[7].BackColor = Color.LightCyan;
			btnDir[7].Click += new EventHandler(OnUpLeft_Click);
			bmp = (Bitmap)rm.GetObject("UL");	//ビットマップの読み込み
			bmp.MakeTransparent(Color.White);
			btnDir[7].Image = bmp;
			btnDir[7].Enabled = false;	//初期状態は使用不可
			//帰属関係設定
			gBoxMove.Controls.Add(btnDir[0]);
			gBoxMove.Controls.Add(btnDir[1]);
			gBoxMove.Controls.Add(btnDir[2]);
			gBoxMove.Controls.Add(btnDir[3]);
			gBoxMove.Controls.Add(btnDir[4]);
			gBoxMove.Controls.Add(btnDir[5]);
			gBoxMove.Controls.Add(btnDir[6]);
			gBoxMove.Controls.Add(btnDir[7]);
			this.Controls.Add(gBoxMove);
			//「パス」（Pass）ボタンの属性設定
			btnPass = new Button();
			btnPass.Size = new Size(60, 24);
			btnPass.Location = new Point(ClientSize.Width - btnPass.Width - 10, ClientSize.Height - btnPass.Height - 10);
			btnPass.Text = "パス";
			btnPass.Click += new EventHandler(OnPass_Click);
			this.Controls.Add(btnPass);
			//フォームのレイアウトを再開
			this.ResumeLayout(false);
			this.PerformLayout();
		}

		private void SetControls(Cell cell)
		{
			//異種族間婚許可の確認
			InterMarriage.Checked = cell.Intmarg;
			//Avatarの属性表示
			string[] tribes = new string[] {"ピンク", "ブルー", "グリーン", "死亡"};
			lblMeTribe.Text = tribes[cell.Tribe];
			lblMeAffection.Text = cell.Affection.ToString();
			lblMeHostility.Text = cell.Hostility.ToString();
			//Avatarセルの周囲状況をダイアログに反映させる
			for(int i = 0; i < Max_Dir; i++)
			{
				switch(cell.Around[i])	//ダイアログ呼び出し前にCheck_Around実行済
				{
					case 0:				//野原
					//「移動」処理の矢印の.Enabledを変更（進める）
						btnDir[i].Enabled = true;
						break;
					case 1:				//山（進めない）
					case 2:				//河川（進めない）
						break;
					case 3:				//食物
						//「食べる 」処理のgBoxFood.Enabledを変更（食べられる）
						fDir = i;		//食物のある方向
						gBoxFood.Enabled = true;
						break;
					default:			//セル（cell.Around[i] >= 4）
						break;
				}
				if(yDir != Not_Found)	//他のセルと遭遇したならば
				{
					if(you.Tribe < 3)			//生存するセル（Cell-P、Cell-B、Cell-G）なら
					{
						gBox.Enabled = true;	//他のセルへの対応が可能となる
					}
					else if(you.Tribe == 3)		//死亡したセルなら食物扱いとなるので
					{
						fDir = yDir;
						gBoxFood.Enabled = true;
					}
					//他のセルの属性表示
					lblYouTribe.Text = tribes[you.Tribe];
					lblYouAffection.Text = you.Affection.ToString();
					lblYouHostility.Text = you.Hostility.ToString();
				}
			}
		}

		//終了処理
		protected override void OnFormClosing(FormClosingEventArgs e)
		{
			base.OnFormClosing(e);
			//タイマーの停止と廃棄
			dlgTimer.Stop();
			dlgTimer.Dispose();
		}

		private void OnGetClose_Click(object sender, EventArgs e)
		{
			wld.Get_Close(cell, you, yDir);
			Close();
		}

		private void OnIntimidate_Click(object sender, EventArgs e)
		{
			wld.Intimidate(cell, you, yDir);
			Close();
		}

		private void OnFight_Click(object sender, EventArgs e)
		{
			wld.Fight(cell, you, yDir);
			Close();
		}

		private void OnFlee_Click(object sender, EventArgs e)
		{
			wld.Flee(cell, you, yDir);
			Close();
		}

		private void OnEat_Click(object sender, EventArgs e)
		{
			cell.Get_Food(fDir);
			Close();
		}

		private void OnUp_Click(object sender, EventArgs e)
		{
			cell.Get_Move(0);
			Close();
		}

		private void OnUpRight_Click(object sender, EventArgs e)
		{
			cell.Get_Move(1);
			Close();
		}

		private void OnRight_Click(object sender, EventArgs e)
		{
			cell.Get_Move(2);
			Close();
		}

		private void OnDownRight_Click(object sender, EventArgs e)
		{
			cell.Get_Move(3);
			Close();
		}

		private void OnDown_Click(object sender, EventArgs e)
		{
			cell.Get_Move(4);
			Close();
		}

		private void OnDownLeft_Click(object sender, EventArgs e)
		{
			cell.Get_Move(5);
			Close();
		}

		private void OnLeft_Click(object sender, EventArgs e)
		{
			cell.Get_Move(6);
			Close();
		}

		private void OnUpLeft_Click(object sender, EventArgs e)
		{
			cell.Get_Move(7);
			Close();
		}

		private void OnPass_Click(object sender, EventArgs e)
		{
			Close();
		}
	}
}
