前回からの続きです。今回はCell_World共通部分とCellクラスを取り上げます。
【World_Cellコード-共通部分とCellクラス】
//////////////////////////////////
// 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クラスはもっと長いので、これも適宜分割して解説します。