⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cminesweeper.cpp

📁 AI.Techniques.for.Game.Programming一书的源程序
💻 CPP
字号:
#include "CMinesweeper.h"

//-----------------------------------constructor-------------------------
//
//-----------------------------------------------------------------------
CMinesweeper::CMinesweeper():
                             m_dRotation(RandFloat() * CParams::dTwoPi),
                             m_lTrack(0),
                             m_rTrack(0),
                             m_dFitness(0),
							               m_dScale(CParams::iSweeperScale),
                             m_bCollided(false)
                             
			 
{
  //create a static start position
  m_vPosition = SVector2D(180, 200);

   //create the sensors
  CreateSensors(m_Sensors, CParams::iNumSensors, CParams::dSensorRange); 

  //initialize its memory
  m_MemoryMap.Init(CParams::WindowWidth,
                   CParams::WindowHeight);

}


//-------------------------------- CreateSensors ------------------------
//
//	This function returns a vector of points which make up the segments of
//  the sweepers sensors.
//------------------------------------------------------------------------
void CMinesweeper::CreateSensors(vector<SPoint> &sensors,
                                 int            NumSensors,
                                 double         range)
{
  //make sure vector of sensors is empty before proceeding
  sensors.clear();

  double SegmentAngle = CParams::dPi / (NumSensors-1);

	//going clockwise from 90deg left of position calculate the fan of
	//points radiating out (not including the origin)
	for (int i=0; i<CParams::iNumSensors; i++)
	{
		//calculate vertex position
		SPoint point;

    point.x = -sin(i * SegmentAngle - CParams::dHalfPi) * range;

	  point.y = cos(i * SegmentAngle - CParams::dHalfPi) * range;
		
		sensors.push_back(point);
		
	}//next segment

}
//-----------------------------Reset()------------------------------------
//
//	Resets the sweepers position, energy level and rotation
//
//------------------------------------------------------------------------
void CMinesweeper::Reset()
{
	//reset the sweepers positions
	m_vPosition = SVector2D(180, 200);
	
	//and the energy level
	m_dFitness = 0;

  //and the rotation
  m_dRotation = RandFloat() * CParams::dTwoPi;

  //reset its memory
  m_MemoryMap.Reset();

}

//------------------------- RenderMemory ---------------------------------
//
//------------------------------------------------------------------------
void CMinesweeper::Render(HDC surface)
{
  //render the memory
  m_MemoryMap.Render(surface);

  string s = itos(m_MemoryMap.NumCellsVisited());
  s = "Num Cells Visited: " + s;
  TextOut(surface, 230,0,s.c_str(), s.size());

}
//---------------------WorldTransform--------------------------------
//
//	sets up a translation matrix for the sweeper according to its
//  scale, rotation and position. Returns the transformed vertices.
//-------------------------------------------------------------------
void CMinesweeper::WorldTransform(vector<SPoint> &sweeper, double scale)
{
	//create the world transformation matrix
	C2DMatrix matTransform;
	
	//scale
	matTransform.Scale(scale, scale);
	
	//rotate
	matTransform.Rotate(m_dRotation);
	
	//and translate
	matTransform.Translate(m_vPosition.x, m_vPosition.y);
	
	//now transform the ships vertices
	matTransform.TransformSPoints(sweeper);
}

//-------------------------------Update()--------------------------------
//
//	First we take sensor readings and feed these into the sweepers brain.
//
//	The inputs are:
//	
//  The readings from the minesweeper's sensors
//  The readings from the minesweeper's feelers
//  bCollided
//
//	We receive two outputs from the brain.. lTrack & rTrack.
//	So given a force for each track we calculate the resultant rotation 
//	and acceleration and apply to current velocity vector.
//
//-----------------------------------------------------------------------
bool CMinesweeper::Update(vector<SPoint> &objects)
{
	
	//this will store all the inputs for the NN
	vector<double> inputs;	

  //grab sensor readings
  TestSensors(objects);


  //input sensors into net
  for (int sr=0; sr<m_vecdSensors.size(); ++sr)
  {
    inputs.push_back(m_vecdSensors[sr]);

    inputs.push_back(m_vecFeelers[sr]);
  }
	
  inputs.push_back(m_bCollided);
  
	//update the brain and get feedback
	vector<double> output = m_ItsBrain.Update(inputs);

	//make sure there were no errors in calculating the 
	//output
	if (output.size() < CParams::iNumOutputs) 
  {
    return false;
  }

  
	//assign the outputs to the sweepers left & right tracks
	m_lTrack = output[0];
	m_rTrack = output[1];

	//calculate steering forces
	double RotForce = m_lTrack - m_rTrack;

  //clamp rotation
	Clamp(RotForce, -CParams::dMaxTurnRate, CParams::dMaxTurnRate);
	
	m_dRotation += RotForce;

	//update Look At 
	m_vLookAt.x = -sin(m_dRotation);
	m_vLookAt.y = cos(m_dRotation);

  //if the sweepers haven't collided with an obstacle
  //update their position
  if (!m_bCollided)
  {
    m_dSpeed = (m_lTrack + m_rTrack);

   //update position
   m_vPosition += (m_vLookAt * m_dSpeed);
  }

  //update the memory map
  m_MemoryMap.Update(m_vPosition.x, m_vPosition.y);
  
	return true;
}
//----------------------- TestSensors ------------------------------------
//
//  This function checks for any intersections between the sweeper's 
//  sensors and the objects in its environment
//------------------------------------------------------------------------
void CMinesweeper::TestSensors(vector<SPoint> &objects)
{
  m_bCollided = false;  
  
  //first we transform the sensors into world coordinates
  m_tranSensors = m_Sensors;

  WorldTransform(m_tranSensors, 1);  //scale is 1

  //flush the sensors
  m_vecdSensors.clear();
  m_vecFeelers.clear();

  //now to check each sensor against the objects in the world
  for (int sr=0; sr<m_tranSensors.size(); ++sr)
  {
    bool bHit = false;

    double dist = 0;

    for (int seg=0; seg<objects.size(); seg+=2)
    {
      if (LineIntersection2D(SPoint(m_vPosition.x, m_vPosition.y),
                             m_tranSensors[sr],
                             objects[seg],
                             objects[seg+1],
                             dist))
      {
        bHit = true;

        break;        
      }
    }
      
    if (bHit)
    {
      m_vecdSensors.push_back(dist);

      //implement very simple collision detection
      if (dist < CParams::dCollisionDist)
      {
        m_bCollided = true;
      }
    }
    
    else
    {
      m_vecdSensors.push_back(-1);
    } 
    
    //check how many times the minesweeper has visited the cell
    //at the current position
    int HowOften = m_MemoryMap.TicksLingered(m_tranSensors[sr].x,
                                             m_tranSensors[sr].y);

    
    //Update the memory info according to HowOften. The maximum
    //value is 1 (because we want all the inputs into the
    //ANN to be scaled between -1 < n < 1)
    if (HowOften == 0)
    {
      m_vecFeelers.push_back(-1);

      continue;
    }
    
    if (HowOften < 10) 
    {
      m_vecFeelers.push_back(0);

      continue;
    }

    if (HowOften < 20)
    {
      m_vecFeelers.push_back(0.2);

      continue;
    }

    if (HowOften < 30)
    {
      m_vecFeelers.push_back(0.4);

      continue;
    }

    if (HowOften < 50)
    {
      m_vecFeelers.push_back(0.6);

      continue;
    }

    if (HowOften < 80) 
    {
      m_vecFeelers.push_back(0.8);

      continue;
    }

     m_vecFeelers.push_back(1);   

  }//next sensor
}

//------------------------- EndOfRunCalculations() -----------------------
//
//------------------------------------------------------------------------
void CMinesweeper::EndOfRunCalculations()
{
  m_dFitness += m_MemoryMap.NumCellsVisited();
}




		

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -