[FreedomAI第七周]遗传与生态实践篇第二部分

这一篇我们来讨论讨论牛。

牛的性状有:牛的初始位置,牛的速度,牛的强壮度,牛的血量。

牛的强壮度在直观表现上会体现出Cube的大小,同时也会影响减血的速度,越强壮,每秒减血的就越慢。

CowObject.class:

public class CowObject:GAObject
	{
		public float mStrongRate;

		public float mVelocity;

		public int mLife;

		public int mTempLife;
		public static Vector3 mpos_leftdown;
		public static Vector3 mpos_rightup;

		public float timer = 0.0f; 
		public SimpleAI mGlassTarget = null;
		public float RoundTimer = 0.0f;
		public float EatTimer = 0.0f;
		public int lastTime = 0;
		public Vector3 RoundTarget = Vector3.zero;

		public override void Decode ()
		{
			bool[][] mAllBitBunch = FreedomAIEncoderAndDecoder.BreakBitBunch (mbitbunch,mBreakPoint);
			string s = "";
			mStrongRate = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[0],0.0f,1.0f);
			mVelocity = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[1],1.5f,6.0f);
			mLife = FreedomAIEncoderAndDecoder.BitBunch2int (mAllBitBunch[2],100,1000);mTempLife = mLife;
			float tx =  FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[3],0.0f,1.0f);tx = (mpos_rightup.x - mpos_leftdown.x) * tx + mpos_leftdown.x;
			float ty =  FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[4],0.0f,1.0f);ty = (mpos_rightup.y - mpos_leftdown.y) * ty + mpos_leftdown.y;
			float tz = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch [5], 0.0f, 1.0f);tz = (mpos_rightup.z - mpos_leftdown.z) * tz + mpos_leftdown.z;
			mPosition = new Vector3 (tx,ty,tz); 
		}

		public override void Encode ()
		{
			bool[] tStrongRate_bit = FreedomAIEncoderAndDecoder.float2BitBunch (mStrongRate,0.0f,1.0f,10);
			bool[] tVelocity_bit = FreedomAIEncoderAndDecoder.float2BitBunch (mVelocity,1.5f,6.0f,10);
			bool[] tLife = FreedomAIEncoderAndDecoder.int2BitBunch (mLife,100,1000,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 (tStrongRate_bit,tVelocity_bit,tLife,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 (11);
			mBreakPoint.Add (11);
		}

		public override float Evaluate ()
		{
			return (float)mTempLife / (float)1000;
		}

		public override void RandomData ()
		{
			System.Random srd = new System.Random ();

			mStrongRate = Random.Range (0.0f,1.0f);
			mVelocity = Random.Range (3.0f,6.5f);
			mLife = Random.Range (0,1000);mTempLife = mLife;
			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 mStrongRate.ToString () + "  " + mVelocity.ToString () + "  " + mLife.ToString() + "  " + mPosition.ToString(); 
		}

	}

牛的行为会相对稍微复杂一些,牛有三种状态,一种是死亡,血量低于0就有消亡。第二种是巡逻,闲逛,吃饱了就会去闲逛。第三种是吃草,首先是对草的选择,会优先选择近的且高的草。

public class CowRunner:SimpleAIRunner
	{
		public void DoRun(SimpleAI sAI,string code)
		{
			string s = code;

			((CowObject)sAI.mCharacter).timer += Time.deltaTime;
			if (((int)((CowObject)sAI.mCharacter).timer) - ((CowObject)sAI.mCharacter).lastTime > 0) 
			{
				((CowObject)sAI.mCharacter).mTempLife -= 30 + (int)(15*((CowObject)sAI.mCharacter).mStrongRate);
				((CowObject)sAI.mCharacter).lastTime = ((int)((CowObject)sAI.mCharacter).timer);
			}
			if (code == "Die") 
			{
				sAI.Destroy ();
			}
			else if (code == "Round")
			{
				((CowObject)sAI.mCharacter).mGlassTarget = null;
				if (((CowObject)sAI.mCharacter).RoundTimer > 0.0f && (((CowObject)sAI.mCharacter)).RoundTarget != Vector3.zero)
				{
					float distance = Vector3.Distance(sAI.mAIRT.transform.position,((CowObject)sAI.mCharacter).RoundTarget);
					if (distance > 1.5f) 
					{
						sAI.GetComponent<AIMove> ().mDirection = ((CowObject)sAI.mCharacter).RoundTarget - sAI.mAIRT.transform.position;
						sAI.GetComponent<AIMove> ().mDirection.y = 0.0f;
						sAI.GetComponent<AIMove> ().mVelocity = ((CowObject)sAI.mCharacter).mVelocity;
					}
					else
					{
						sAI.GetComponent<AIMove> ().mVelocity = 0.0f;
					}
					((CowObject)sAI.mCharacter).RoundTimer -= Time.deltaTime;
				}
				else
				{
					((CowObject)sAI.mCharacter).RoundTimer = 2.5f;
					((CowObject)sAI.mCharacter).RoundTarget = sAI.GeneratePos + new Vector3 (Random.Range(-10,10),0,Random.Range(-10,10));
				}
			} 
			else 
			{
				((CowObject)sAI.mCharacter).RoundTarget = Vector3.zero;
				((CowObject)sAI.mCharacter).RoundTimer = 0.0f;
				if (((CowObject)sAI.mCharacter).mGlassTarget == null||((CowObject)sAI.mCharacter).mGlassTarget.mAIRT==null) 
				{
					SimpleAI[] SimpleAIs = SimpleAISetSingleton.getInstance ().GetComponent<SimpleAISet> ().FindAIsWithRiaus (sAI.mAIRT.transform.position,20.0f,1<<LayerMask.NameToLayer("Default"),"Glass");
					int startIndex = Random.Range (0,SimpleAIs.Length);
					for (int i = startIndex; i < SimpleAIs.Length; i++)
					{
						float f2 = ((glassObject)SimpleAIs [i].mCharacter).mHeight;
						f2 = (f2 - 1.0f) / 1.5f;
						if (Random.Range (0.0f, 1.0f) < f2) 
						{
							((CowObject)sAI.mCharacter).mGlassTarget = SimpleAIs [i];
							break;
						}
					}
					s+="Finding";
				}
				else
				{
					float distance = Vector3.Distance(sAI.mAIRT.transform.position,((CowObject)sAI.mCharacter).mGlassTarget.mAIRT.transform.position);
					if (distance>1.5f)
					{
						sAI.GetComponent<AIMove> ().mDirection = ((CowObject)sAI.mCharacter).mGlassTarget.mAIRT.transform.position - sAI.mAIRT.transform.position;
						sAI.GetComponent<AIMove> ().mDirection.y = 0.0f;
						sAI.GetComponent<AIMove> ().mVelocity = ((CowObject)sAI.mCharacter).mVelocity;
			
					}
					else
					{
						sAI.GetComponent<AIMove> ().mVelocity = 0.0f;
						if (((CowObject)sAI.mCharacter).EatTimer < 1.0f)
						{
							((CowObject)sAI.mCharacter).EatTimer += Time.deltaTime;
						}
						else 
						{
							((CowObject)sAI.mCharacter).mTempLife += 40;
							((CowObject)sAI.mCharacter).mTempLife = Mathf.Min (((CowObject)sAI.mCharacter).mTempLife,((CowObject)sAI.mCharacter).mLife);
							((glassObject)((CowObject)sAI.mCharacter).mGlassTarget.mCharacter).mHp -= 40;
						}
					}
				}
			}
		}	
	};

运行结果:

第一代:


第二代:


第三代:


我们可以注意到,首先是草的生长位置向左下偏移,草的高度,草的颜色偏接近矮绿,这是因为,绿的加血更多,活的更健康,高的更容易被吃掉,而右上的草里牛群近,也容易被吃掉,所以就进化出了这样的结果。

而我们可以把玩家当作这里的牛,不同的是,玩家的选择是不固定的,他可能选择砍任何位置的草,可能旋转砍任何颜色的草,可能选择砍任何高矮的草,也就是草进化空间是我们事先未设置好的由玩家做了什么来决定,也就是给到了玩家事先未设置好的游戏机制反馈。

猜你喜欢

转载自blog.csdn.net/qq_33999892/article/details/80539252