void GenerateMoves(S_CurState i_stCurrent, float i_fTime, out S_CurMove[] o_stMoves) { int i; o_stMoves = new S_CurMove[6]; for (i = 0; i < 6; i++) { S_CurState stNew = i_stCurrent; stNew.fPointing -= ALLMOVES[i].bRight ? SHIP_STEERSPEED * i_fTime : 0; stNew.fPointing += ALLMOVES[i].bLeft ? SHIP_STEERSPEED * i_fTime : 0; if (stNew.fPointing < 0) { stNew.fPointing += 360; } if (stNew.fPointing > 360) { stNew.fPointing -= 360; } float fThrust = ALLMOVES[i].bThrottle ? SHIP_THRUST : 0; Vector2 a = new Vector2(Mathf.Cos(stNew.fPointing * (Mathf.PI / 180)) * fThrust, Mathf.Sin(stNew.fPointing * (Mathf.PI / 180)) * fThrust); a += oCustomGravity.force; a -= stNew.vVel * oRb.drag; stNew.vPos += (stNew.vVel * i_fTime) + (0.5f * a * i_fTime * i_fTime); stNew.vVel += a * i_fTime; o_stMoves[i].stValue = stNew; o_stMoves[i].a = Strategy5(stNew); o_stMoves[i].b = Strategy1(stNew); o_stMoves[i].c = Strategy2(stNew); o_stMoves[i].d = Strategy4(stNew); o_stMoves[i].e = MOVE_TO_MOVE_SCORE[stNew.iLastMove, i] * (1.0f / Strategy5(stNew)); } }
int EvaluateMoves(S_CurState i_stCurrent, int i_iLevel, bool i_bShallow) { int i, iMove = 0; float fBest = 1000000000, fWorst = -1000000000; float[] dTest = new float[6]; float a, b, c, d, e; S_CurMove[] aMoves; int iWorst; S_CurState stCurrent = i_stCurrent; stCurrent.fTimestep = 0.07f * TIME_FACTOR[i_iLevel]; GenerateMoves(stCurrent, 0.07f * TIME_FACTOR[i_iLevel], out aMoves); for (i = 0; i < 6; i++) { a = aMoves[i].a; b = aMoves[i].b; c = aMoves[i].c; d = aMoves[i].d; e = aMoves[i].e; //dTest[i] = a * 0.0f + b * 1000.0f + c * 1.0f + d * 10.0f + e * 0.05f; dTest[i] = a * 0.0f + b * 10000.0f + c * 2.0f + d * 10.0f + e * 0.1f; if (dTest[i] > fWorst) { fWorst = dTest[i]; iWorst = i; } } { //full search for (i = 0; i < 6; i++) { //recurse... stCurrent = aMoves[i].stValue; stCurrent.iLastMove = i; if (i_iLevel < /**/ 1) { dTest[i] += EvaluateMoves(stCurrent, i_iLevel + 1, true); } if (dTest[i] < fBest) { fBest = dTest[i]; iMove = i; } } } if (i_iLevel > 0) { return((int)fBest); } else { return(iMove); } } //score for how far from the line float Strategy0(S_CurState stValues) { return(CheckPoint.PointDistanceToLineSeg(stValues.vPos, stValues.l0, stValues.l1)); } //score for how much closer to goal float Strategy1(S_CurState stValues) { float fDistNow = (stValues.vPos - stValues.l1).magnitude; float fDistBefore = ((stValues.vPos - (stValues.vVel * stValues.fTimestep)) - stValues.l1).magnitude; float fScore = (fDistNow - fDistBefore); //negative value is closer return(fScore); } float CalcLineAngle(Vector2 a, Vector2 b) { float difx = b.x - a.x; float dify = b.y - a.y; float fResult = 360.0f - (Mathf.Atan2(-dify, difx) * (180.0f / Mathf.PI)); if (fResult >= 360.0f) { fResult -= 360.0f; } else if (fResult < 0.0f) { fResult += 360.0f; } return(fResult); } //score for pointing toward goal (more important further from goal) float Strategy2(S_CurState stValues) { float fGoalAngle = CalcLineAngle(stValues.vPos, stValues.l1); float fDiff = fGoalAngle - stValues.fPointing; if (fDiff < 0) { fDiff += 360; } if (fDiff > 360) { fDiff -= 360; } if (fDiff > 180) { fDiff = 360 - fDiff; //the difference of two angles can be max 180. } float fDistNow = (stValues.vPos - stValues.l1).magnitude; if (fDistNow > 1.0f) { fDistNow = 1.0f; } float fScore = fDiff / fDistNow; return(fScore); } //score for speed float Strategy3(S_CurState stValues) { float fVel = stValues.vVel.magnitude; float fScore = -fVel; return(fScore); } //score for speed vs dist to goal float Strategy4(S_CurState stValues) { float fVel = stValues.vVel.magnitude; float fDistNow = (stValues.vPos - stValues.l1).magnitude; if (fDistNow > 1.0f) { fDistNow = 1.0f; } float fScore = -fVel / (1.0f / fDistNow); return(fScore); } //score for dist to goal float Strategy5(S_CurState stValues) { float fDistNow = (stValues.vPos - stValues.l1).magnitude; float fScore = fDistNow; return(fScore); } //////////////////////////////////////////////////////////////////////// Vector2 vForceDir = new Vector2(0, 0); int iLastInput = 0; //bool bitfield float fReplayMessageTimer = 0; Vector2 vLastPosition; float[] fMeanSpeeds = new float[16]; internal float fMeanSpeed = 0.0f; internal int iNumEnemiesNear = 0; internal int iNumBulletsNear = 0; float fCurrentSpeedSeg = 0; int iBestMove = 0; void FixedUpdate() { if (!bInited) { return; } float fDist = (oRb.position - vLastPosition).magnitude; if (fDist > 0.80f) { fDist = 0.0f; //detect when player has jumped to a new position (after death) } //mean speed calculation (used in race music) int iLastSec = (int)fCurrentSpeedSeg; fCurrentSpeedSeg += Time.fixedDeltaTime; if (fCurrentSpeedSeg >= 16.0f) { fCurrentSpeedSeg -= 16.0f; } int iCurSec = (int)fCurrentSpeedSeg; if (iCurSec != iLastSec) { fMeanSpeeds[iCurSec] = 0.0f; } fMeanSpeeds[iCurSec] += fDist; fMeanSpeed = 0.0f; for (int i = 0; i < fMeanSpeeds.Length; i++) { if (i != iCurSec) { fMeanSpeed += fMeanSpeeds[i]; } } fMeanSpeed = fMeanSpeed / (fMeanSpeeds.Length - 1) * 10; //enemies near (used in mission music) iNumEnemiesNear = oMap.GetNumEnemiesNearPlayer(); //or enemy bullets near (used in mission music) iNumBulletsNear = oMap.GetNumBulletsNearPlayer(); //distance achievement fAchieveDistance += fDist * 10; vLastPosition = oRb.position; fTotalTimeMission += Time.fixedDeltaTime; if (bTimeCounting) { fTotalTime += Time.fixedDeltaTime; } //////get input, either from replay or from human player if (GameLevel.bRunReplay) { ReplayMessage rm; while (GameLevel.theReplay.Get(out rm, 0)) { //we got new input if (rm.iType == (byte)MsgType.MOVEMENT) { oRb.position = rm.vPos; oRb.velocity = rm.vVel; oRb.rotation = rm.fDirection; bThrottle = (rm.iKeyFlag & 8) != 0; bLeft = (rm.iKeyFlag & 4) != 0; bRight = (rm.iKeyFlag & 2) != 0; bAdjust = (rm.iKeyFlag & 1) != 0; } if (rm.iType == (byte)MsgType.BULLETP_NEW) { //part of CreateBullet() S_BulletInfo stBulletInfo; stBulletInfo.vPos = rm.vPos; stBulletInfo.vVel = rm.vVel; stBulletInfo.fDirection = rm.fDirection; GameObject o = Instantiate(oMap.oBulletObjBase, oMap.transform); o.GetComponent <Bullet>().Init(stBulletInfo, 0 /*iOwnerID*/); oASGeneral.PlayOneShot(oClipFire); } if (rm.iType == (byte)MsgType.PLAYER_KILL) { oRb.position = rm.vPos; oRb.velocity = rm.vVel; oRb.rotation = rm.fDirection; Kill(false); } } }