昨日告知しましたように、Embarcadero C++とBCCS keltonで開発したCellのC#版(ユーザーもアバターで参加できるのでVersion 2.0としましたが...)、Cells for C#がどうもできあがったようなので、これについて書いてみようかと思います。
最初にこのコンセプトでプログラムを作ろうとしたとき時の【Cell】シリーズ始動...でも書いていますが、
(1)プログラムの本質はライフゲームです。セル・オートマトンと言い換えてもよいかと思います。(Cellとか、Cellsf or C#の名称もそこから来ています。)
(2)ただ、よく知られたライフゲーム
(このブログでも2023年に紹介した、矢張りEmbarcadero C++とBCCS keltonで開発したもの)
は数学的で、静的に集合離散(過密過疎)を表したものであり、その生成、消滅ルールが結構単純であることが不満でした。
(3)それで我々が住む「人間社会」に似せた「動的」な変化を与えたらどうなるか、見てみたいと、と考えました。この「動的」の意味は「単に『主役である存在の単位、セル』が『動く(Mobility)』だけではなく、セルの行動様式がセルの行動や、セル間のコミュニケーションにより『社会的に変化』してゆく」ことで、
同じ条件でスタートしても結果が常に異なる
ようにしたいと考えました。
(4)その結果、オリジナル版のブログで書いたように、
***仕様メモ***
1.新しいコンセプトのライフゲーム
2.オブジェクトは"world"と"cell"で、"world"がゲームの「場」、"cell"が「場」で誕生、生存、死亡する生命体プレーヤー
3."world"クラスは80 x 40(ピクセルで1280 x 640)の広さを持つ
4.従来のライフゲームは植物の様に移動せず、過密、過疎で生態系が影響を受けたが、"cell"は動物をイメージして移動する。
5."cell"は誕生と共に別スレッドで個別に行動し、"world"内を移動する。
6."cell"の特徴(DNAをイメージ)として、「年齢」、「生命力」、「攻撃力」、「防御力」、「生殖力」etcを持つ。
7."cell"が移動して他のcellと隣接すると、「愛着」または「攻撃性」の特性により、交尾したり、闘争になったりする。
8.死亡要因は「寿命」、攻撃による「生命力の枯渇」
9.「栄養」や「水分」の摂取をどうするか、「病気」、「事故」をどうするか検討中
昨日はこう(「Cell種」、「人種」は即ち生物学的な"race")書きましたが、チト「参●党」を想起してしまうので政治色が強くなりすぎるのと、意図するものはより「社会、文化的集団」である「部族-"tribe"」であったことから、本日「(しかし、往々にして「部族」も「種」の違いが起源となりうるので)種族-"tribe"」という概念に変えました。
今度は「愛着性」、「敵対性(攻撃性<hostility>から変更しました)」という特性の契機としてこの「種族」が使えることを思いつき、また同時に「種族」を超えた行動を許可するパラメーターとして「異種族婚(Inter-tribe marriage)許可」の概念も、本日取り入れることにしました。
という「社会的存在」を想定し、その概念はCells for C#でも承継しております。以下にCells for C#におけるCellクラスのデータ部のみ掲載します。
/////////////////
//Cellクラス定義
/////////////////
public class Cell
{
///////////////////////
//ゲーム関係フィールド
// 定数定義 (解説:C#はCやC++の"define"が使えないので、このように定数を定義しています。namespace共通で宣言できるとよいのですが、クラスごとに設定する必要があります。)
///////////////////////
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)
///////////////////
//メンバーメソッド
///////////////////
(以下略)
そしてこのセルという生命体が社会活動を行う「場」がWorldであり、矢張りデータ部分だけ紹介しておきます。
//////////////////
//Worldクラス定義
//////////////////
public class World : PictureBox
//解説:オリジナル版では描画やUIはメインウィンドウで行っていましたが、C#版は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共通-解説:これもC#の仕様の為、この静的変数を共通の乱数発生拠点にしました。)
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(解説:Ver 2.0で追加しました。)
//【調整項目】定数定義(変更可)
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;} //仮想画面のグラフィック
//解説:↑で述べたように、オリジナルではメインウィンドウでCANVASクラスとCBITMAPクラスを使って描画していましたが、C#版ではコントロール化して、ここで描画しています。
このように、「『世界』の中で生成された性格や能力が一つづつ異なる『セル』が、放浪しつつ、他セルと遭遇して、ライフサイクルに応じて性格や能力を変化させつつ、社会を形成、発展、破壊してゆく物語」を作りたかったのでした。
このコンセプトはCells for C#でも全く変わりありません。
次回は最初に行ったC#へ単純移植する際の失敗談でも披露しましょうかね?

