上周完成了遗传算法的底层编码,这周还设计一个能体现效果的小Demo。
我们使用了最简单的生产者、消费者一个循环体系。生产者是草,消费者是牛。
生产者具有的性状有:
草的高低、草的生长位置、草的颜色、草的血量
其中草的生长位置在一个矩形区域里随机,草的颜色在黄色和绿色之间随机,草的高低在1.0-2.5倍之间变化,草的血量在500-1500变化。
且草的高低将影响草的颜色,比较高的草更多的呈现黄色(用尽了生长潜能),比较矮的草更多的呈现绿色。
草的血量将直接影响到是否会很容易被牛吃完。
草的代码:
glassObject.class:
public class glassObject:GAObject
{
public Color mColor;
public float mHeight;
public int mHp;
private int mAllhp;
public static Vector3 mpos_leftdown;
public static Vector3 mpos_rightup;
public float timer = 0.0f;
public override void Decode ()
{
bool[][] mAllBitBunch = FreedomAIEncoderAndDecoder.BreakBitBunch (mbitbunch,mBreakPoint);
mColor.r = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[0],Mathf.Min(Color.green.r,Color.yellow.r),Mathf.Max(Color.green.r,Color.yellow.r));
mColor.g = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[1],Mathf.Min(Color.green.g,Color.yellow.g),Mathf.Max(Color.green.g,Color.yellow.g));
mColor.b = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[2],Mathf.Min(Color.green.b,Color.yellow.b),Mathf.Max(Color.green.b,Color.yellow.b));
mHeight = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[3],1.0f,2.5f);
mAllhp = FreedomAIEncoderAndDecoder.BitBunch2int (mAllBitBunch[4],500,1500);
float tx = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[5],0.0f,1.0f);tx = (mpos_rightup.x - mpos_leftdown.x) * tx + mpos_leftdown.x;
float ty = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[6],0.0f,1.0f);ty = (mpos_rightup.y - mpos_leftdown.y) * ty + mpos_leftdown.y;
float tz = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch [7], 0.0f, 1.0f);tz = (mpos_rightup.z - mpos_leftdown.z) * tz + mpos_leftdown.z;
mPosition = new Vector3 (tx,ty,tz);
mHp = mAllhp;
}
public override void Encode ()
{
bool[] mColor_R = FreedomAIEncoderAndDecoder.float2BitBunch (mColor.r,Mathf.Min(Color.green.r,Color.yellow.r),Mathf.Max(Color.green.r,Color.yellow.r),10);
bool[] mColor_G = FreedomAIEncoderAndDecoder.float2BitBunch (mColor.g,Mathf.Min(Color.green.g,Color.yellow.g),Mathf.Max(Color.green.g,Color.yellow.g),10);
bool[] mColor_B = FreedomAIEncoderAndDecoder.float2BitBunch (mColor.b,Mathf.Min(Color.green.b,Color.yellow.b),Mathf.Max(Color.green.b,Color.yellow.b),10);
bool[] mHeight_Bit = FreedomAIEncoderAndDecoder.float2BitBunch (mHeight,1.0f,2.5f,11);
bool[] mAllhp_Bit = FreedomAIEncoderAndDecoder.int2BitBunch (mAllhp,500,1500,10);
bool[] mPosition_X = FreedomAIEncoderAndDecoder.float2BitBunch ((mPosition.x-mpos_leftdown.x)/(mpos_rightup.x-mpos_leftdown.x),0.0f,1.0f,11);
bool[] mPosition_Y = FreedomAIEncoderAndDecoder.float2BitBunch ((mPosition.y-mpos_leftdown.y)/(mpos_rightup.y-mpos_leftdown.y),0.0f,1.0f,11);
bool[] mPosition_Z = FreedomAIEncoderAndDecoder.float2BitBunch ((mPosition.z-mpos_leftdown.z)/(mpos_rightup.z-mpos_leftdown.z),0.0f,1.0f,11);
mbitbunch = FreedomAIEncoderAndDecoder.JointBitBunch (mColor_R,mColor_G,mColor_B,mHeight_Bit,mAllhp_Bit,mPosition_X,mPosition_Y,mPosition_Z);
}
public override void InitBreakPoint ()
{
mBreakPoint.Clear ();
mBreakPoint.Add (10);
mBreakPoint.Add (10);
mBreakPoint.Add (10);
mBreakPoint.Add (11);
mBreakPoint.Add (10);
mBreakPoint.Add (11);
mBreakPoint.Add (11);
mBreakPoint.Add (11);
}
public override float Evaluate ()
{
return (float)mHp / (float)1000;
}
public override void RandomData ()
{
mColor = new Color ();
mColor.r = Random.Range (Mathf.Min(Color.green.r,Color.yellow.r),Mathf.Max(Color.green.r,Color.yellow.r));
mColor.g = Random.Range (Mathf.Min(Color.green.g,Color.yellow.g),Mathf.Max(Color.green.g,Color.yellow.g));
mColor.b = Random.Range (Mathf.Min(Color.green.b,Color.yellow.b),Mathf.Max(Color.green.b,Color.yellow.b));
mHeight = Random.Range (1.0f,2.5f);
mAllhp = Random.Range (500,1500);mHp = mAllhp;
mPosition = new Vector3 ();
mPosition.x = Random.Range (mpos_leftdown.x,mpos_rightup.x);
mPosition.y = Random.Range (mpos_leftdown.y,mpos_rightup.y);
mPosition.z = Random.Range (mpos_leftdown.z,mpos_rightup.z);
}
public override string ToString ()
{
return mColor.ToString () + " " + mHeight.ToString () + " " + mHp.ToString() + " " + mPosition.ToString();
}
比较重要的在于,编码函数和解码函数——都是利用了之前封装好的方法,分别是把性状里的具体数据转化成二进制编码,和把二进制编码转化成数据。
另外关于草的行为:草的行为十分简单,血量高于0就默默光合作用——越绿越快也就是加血加的多,血量低于0就消除。
这里使用了我们之前提到了RBS系统——SimpleAI:
public class GlassJudger:SimpleAIStateJudger
{
public string DoJudge(SimpleAI pSimpleAI)
{
if(((glassObject)pSimpleAI.mCharacter).mHp<0)
return "Die";
else
return "Idle";
}
}
public class GlassRunner:SimpleAIRunner
{
public void DoRun(SimpleAI sAI,string code)
{
if (code == "Die")
{
sAI.Destroy ();
}
glassObject go = (glassObject)sAI.mCharacter;
Color mC = go.mColor;
if (go.timer < 1.0f)
{
go.timer += Time.deltaTime;
return;
}
go.timer = 0.0f;
float rate = mC.g / (mC.r + mC.b);
go.mHp += (int)(rate*4);
}
}