Source Code (Use browser search to find items of interest.)

Class Index

kreversi'Engine (./kdegames/kreversi/Engine.h:187)

class Engine : public SuperEngine {
public:
  Engine(int st, int sd);
  Engine(int st);
  Engine();
  virtual ~Engine() {};

  Move ComputeMove(Game g);
  Move ComputeFirstMove(Game g);
  int ComputeMove2(int xplay, int yplay, int player, int level,
    int cutoffval, ULONG64 playerbits, ULONG64 opponentbits);

  int TryAllMoves(int opponent, int level, int cutoffval,
		  ULONG64 opponentbits, ULONG64 playerbits);

  int EvaluatePosition(int player);
  void SetupBcBoard();
  void SetupBits();
  int CalcBcScore(int player);
  ULONG64 ComputeOccupiedBits(int player);

  void yield();

private:
  static const int LARGEINT;
  static const int ILLEGAL_VALUE;
  static const int BC_WEIGHT;
  int  m_board[10][10];
  int  m_bc_board[9][9];
  Score m_score;
  Score m_bc_score;
  SquareStack m_squarestack;
  int  m_depth;
  int  m_coeff;
  int  m_nodes_searched;
  bool m_exhaustive;
  ULONG64 m_coord_bit[9][9];
  ULONG64 m_neighbor_bits[9][9];
  long lastYield;
};

kreversi'Engine::Engine() (./kdegames/kreversi/Engine.cpp:211)

Engine::Engine(int st, int sd) : SuperEngine(st, sd) {
  SetupBcBoard(); 
  SetupBits(); 
}



kreversi'Engine::Engine() (./kdegames/kreversi/Engine.cpp:217)

Engine::Engine(int st) : SuperEngine(st) { 
  SetupBcBoard(); 
  SetupBits(); 
}



kreversi'Engine::Engine() (./kdegames/kreversi/Engine.cpp:223)

Engine::Engine() : SuperEngine(5) { 
  SetupBcBoard(); 
  SetupBits(); 
}


// keep GUI alive

kreversi'Engine::yield() (./kdegames/kreversi/Engine.cpp:230)

void Engine::yield() {
  qApp->processEvents();
}



kreversi'Engine::ComputeMove() (./kdegames/kreversi/Engine.cpp:235)

Move Engine::ComputeMove(Game g) {
  m_exhaustive = false;

  int player = g.GetWhoseTurn();

  if (player == Score::NOBODY) 
    return Move(-1,-1,-1);

  m_score.InitScore(g.GetScore(Score::WHITE), g.GetScore(Score::BLACK));
  if (m_score.GetScore(Score::WHITE) + m_score.GetScore(Score::BLACK) == 4)
    return ComputeFirstMove(g);

  // JAVA m_board = new int[10][10];
  //m_squarestack = new SquareStack(3000); // More than enough...
  m_squarestack.init(3000);
  m_depth = m_strength;

  if (m_score.GetScore(Score::WHITE) + m_score.GetScore(Score::BLACK) +
      m_depth + 4 >= 64)
    m_depth =
      64 - m_score.GetScore(Score::WHITE) - m_score.GetScore(Score::BLACK);
  else if (m_score.GetScore(Score::WHITE) + m_score.GetScore(Score::BLACK) +
	   m_depth + 7 >= 64)
    m_depth += 3;
  else if (m_score.GetScore(Score::WHITE) + m_score.GetScore(Score::BLACK) +
	   m_depth + 9 >= 64)
    m_depth += 2;
  else if (m_score.GetScore(Score::WHITE) + m_score.GetScore(Score::BLACK) +
	   m_depth + 11 >= 64)
    m_depth++;

  if (m_score.GetScore(Score::WHITE) + m_score.GetScore(Score::BLACK) +
      m_depth >= 64) m_exhaustive = true;

  m_coeff =
    100 - (100*
	   (m_score.GetScore(Score::WHITE) + m_score.GetScore(Score::BLACK) +
	    m_depth - 4))/60;

  m_nodes_searched = 0;

  for (int x=0; x<10; x++)
    for (int y=0; y<10; y++)
      m_board[x][y] = Score::NOBODY;

  for (int x=1; x<9; x++)
    for (int y=1; y<9; y++)
      m_board[x][y] = g.GetSquare(x, y);

  m_bc_score.InitScore(CalcBcScore(Score::WHITE), CalcBcScore(Score::BLACK));

  ULONG64 playerbits = ComputeOccupiedBits(player);
  ULONG64 opponentbits = ComputeOccupiedBits(Score::GetOpponent(player));

  int maxval = -LARGEINT;
  int max_x = 0;
  int max_y = 0;

  MoveAndValue moves[60];
  int number_of_moves = 0;
  int number_of_maxval = 0;

  SetInterrupt(false);

  ULONG64 null_bits;
  null_bits = 0;

  //struct tms tmsdummy; 
  //long starttime = times(&tmsdummy);

  for (int x=1; x<9; x++)
    for (int y=1; y<9; y++)
      if (m_board[x][y] == Score::NOBODY &&
	  (m_neighbor_bits[x][y] & opponentbits) != null_bits)
	{

	  int val = ComputeMove2(x, y, player, 1, maxval, 
				 playerbits, opponentbits);

	  if (val != ILLEGAL_VALUE)
	    {
	      moves[number_of_moves++].setXYV(x, y, val);

	      if (val > maxval)
		{
		  maxval = val;
		  max_x = x;
		  max_y = y;
		  number_of_maxval = 1;
		}
	      else if (val == maxval) number_of_maxval++;
	    }

	  if (GetInterrupt()) break;
	}

  // long endtime = times(&tmsdummy);

  if (number_of_maxval > 1)
    {
      int r = m_random.getLong(number_of_maxval) + 1;

      int i;

      for (i=0; i < number_of_moves; i++)
	if (moves[i].m_value == maxval && --r <= 0) break;

      max_x = moves[i].m_x;
      max_y = moves[i].m_y;
    }

  if (GetInterrupt()) {       
    return Move(-1, -1, -1);
  } else if (maxval != -LARGEINT) {
    return Move(max_x, max_y, player);
  } else {
    return Move(-1, -1, -1);
  }
}



kreversi'Engine::ComputeFirstMove() (./kdegames/kreversi/Engine.cpp:356)

Move Engine::ComputeFirstMove(Game g) {
  int r;
  int player = g.GetWhoseTurn();

  r = m_random.getLong(4) + 1;

  if (player == Score::WHITE)
    {
      if (r == 1) return Move(3, 5, player);
      else if (r == 2) return  Move(4, 6, player);
      else if (r == 3) return  Move(5, 3, player);
      else return  Move(6, 4, player);
    }
  else
    {
      if (r == 1) return  Move(3, 4, player);
      else if (r == 2) return  Move(5, 6, player);
      else if (r == 3) return  Move(4, 3, player);
      else return  Move(6, 5, player);
    }
}



kreversi'Engine::ComputeMove2() (./kdegames/kreversi/Engine.cpp:379)

int Engine::ComputeMove2(int xplay, int yplay, int player, int level,
			 int cutoffval, ULONG64 playerbits, 
			 ULONG64 opponentbits)
{
  int number_of_turned = 0;
  SquareStackEntry mse;
  int opponent = Score::GetOpponent(player);

  m_nodes_searched++;

  m_board[xplay][yplay] = player;
  playerbits |= m_coord_bit[xplay][yplay];
  m_score.ScoreAdd(player, 1);
  m_bc_score.ScoreAdd(player, m_bc_board[xplay][yplay]);

  ///////////////////
  // Turn all pieces:
  ///////////////////

  for (int xinc=-1; xinc<=1; xinc++)
    for (int yinc=-1; yinc<=1; yinc++)
      if (xinc != 0 || yinc != 0)
	{
	  int x, y;

	  for (x = xplay+xinc, y = yplay+yinc; m_board[x][y] == opponent;
	       x += xinc, y += yinc)
	    ;

	  if (m_board[x][y] == player)
	    for (x -= xinc, y -= yinc; x != xplay || y != yplay;
		 x -= xinc, y -= yinc)
	      {
		m_board[x][y] = player;
		playerbits |= m_coord_bit[x][y];
		opponentbits &= ~m_coord_bit[x][y];
		m_squarestack.Push(x, y);
		m_bc_score.ScoreAdd(player, m_bc_board[x][y]);
		m_bc_score.ScoreSubtract(opponent, m_bc_board[x][y]);
		number_of_turned++;
	      }
	}

  int retval = -LARGEINT;

  if (number_of_turned > 0)
    {
      //////////////
      // Legal move:
      //////////////

      m_score.ScoreAdd(player, number_of_turned);
      m_score.ScoreSubtract(opponent, number_of_turned);

      if (level >= m_depth) retval = EvaluatePosition(player); // Terminal node
      else
	{
	  int maxval = TryAllMoves(opponent, level, cutoffval, opponentbits,
				   playerbits);

	  if (maxval != -LARGEINT) retval = -maxval;
	  else
	    {
	      ///////////////////////////////////////////////////////////////
	      // No possible move for the opponent, it is players turn again:
	      ///////////////////////////////////////////////////////////////
	      retval= TryAllMoves(player, level, -LARGEINT, playerbits,
				  opponentbits);

	      if (retval == -LARGEINT)
		{
		  ///////////////////////////////////////////////
		  // No possible move for anybody => end of game:
		  ///////////////////////////////////////////////

		  int finalscore =
		    m_score.GetScore(player) - m_score.GetScore(opponent);

		  if (m_exhaustive) retval = finalscore;
		  else
		    {
		      // Take a sure win and avoid a sure loss (may not be optimal):

		      if (finalscore > 0) retval = LARGEINT - 65 + finalscore;
		      else if (finalscore < 0) retval = -(LARGEINT - 65 + finalscore);
		      else retval = 0;
		    }
		}
	    }
	}

      m_score.ScoreAdd(opponent, number_of_turned);
      m_score.ScoreSubtract(player, number_of_turned);
    }

  /////////////////
  // Restore board:
  /////////////////

  for (int i = number_of_turned; i > 0; i--)
    {
      mse = m_squarestack.Pop();
      m_bc_score.ScoreAdd(opponent, m_bc_board[mse.m_x][mse.m_y]);
      m_bc_score.ScoreSubtract(player, m_bc_board[mse.m_x][mse.m_y]);
      m_board[mse.m_x][mse.m_y] = opponent;
    }

  m_board[xplay][yplay] = Score::NOBODY;
  m_score.ScoreSubtract(player, 1);
  m_bc_score.ScoreSubtract(player, m_bc_board[xplay][yplay]);

  if (number_of_turned < 1 || GetInterrupt()) return ILLEGAL_VALUE;
  else return retval;
}



kreversi'Engine::TryAllMoves() (./kdegames/kreversi/Engine.cpp:495)

int Engine::TryAllMoves(int opponent, int level, int cutoffval,
			ULONG64 opponentbits, ULONG64 playerbits)
{
  int maxval = -LARGEINT;

  // keep GUI alive
  yield();

  ULONG64 null_bits;
  null_bits = 0;

  for (int x=1; x<9; x++)
    {
      for (int y=1; y<9; y++)
	if (m_board[x][y] == Score::NOBODY &&
	    (m_neighbor_bits[x][y] & playerbits) != null_bits)
	  {
	    int val = ComputeMove2(x, y, opponent, level+1, maxval, opponentbits,
				   playerbits);

	    if (val != ILLEGAL_VALUE && val > maxval)
	      {
		maxval = val;
		if (maxval > -cutoffval || GetInterrupt()) break;
	      }
	  }

      if (maxval > -cutoffval || GetInterrupt()) break;
    }

  if (GetInterrupt()) return -LARGEINT;
  return maxval;
}



kreversi'Engine::EvaluatePosition() (./kdegames/kreversi/Engine.cpp:530)

int Engine::EvaluatePosition(int player)
{
  int retval;

  int opponent = Score::GetOpponent(player);
  int score_player = m_score.GetScore(player);
  int score_opponent = m_score.GetScore(opponent);

  if (m_exhaustive) retval = score_player - score_opponent;
  else
    {
      retval = (100-m_coeff) *
	(m_score.GetScore(player) - m_score.GetScore(opponent)) +
	m_coeff * BC_WEIGHT *
	(m_bc_score.GetScore(player)-m_bc_score.GetScore(opponent));
    }

  return retval;
}



kreversi'Engine::SetupBits() (./kdegames/kreversi/Engine.cpp:551)

void Engine::SetupBits()
{
  //m_coord_bit = new long[9][9];
  //m_neighbor_bits = new long[9][9];

  ULONG64 bits = 1;

  for (int i=1; i < 9; i++)
    for (int j=1; j < 9; j++)
      {
	m_coord_bit[i][j] = bits;
#if !defined(__GNUC__)
	bits.shl();
#else
	bits *= 2;
#endif
      }

  for (int i=1; i < 9; i++)
    for (int j=1; j < 9; j++)
      {
	m_neighbor_bits[i][j] = 0;

	for (int xinc=-1; xinc<=1; xinc++)
	  for (int yinc=-1; yinc<=1; yinc++)
	    if (xinc != 0 || yinc != 0)
	      if (i + xinc > 0 && i + xinc < 9 && j + yinc > 0 && j + yinc < 9)
		m_neighbor_bits[i][j] |= m_coord_bit[i + xinc][j + yinc];
      }
}



kreversi'Engine::SetupBcBoard() (./kdegames/kreversi/Engine.cpp:583)

void Engine::SetupBcBoard()
{
  // JAVA m_bc_board = new int[9][9];

  for (int i=1; i < 9; i++)
    for (int j=1; j < 9; j++)
      {
	if (i == 2 || i == 7) m_bc_board[i][j] = -2; else m_bc_board[i][j] = 0;
	if (j == 2 || j == 7) m_bc_board[i][j] -= 2;
      }

  m_bc_board[1][1] = 20;
  m_bc_board[8][1] = 20;
  m_bc_board[1][8] = 20;
  m_bc_board[8][8] = 20;

  m_bc_board[1][2] = -2;
  m_bc_board[2][1] = -2;
  m_bc_board[1][7] = -2;
  m_bc_board[7][1] = -2;
  m_bc_board[8][2] = -2;
  m_bc_board[2][8] = -2;
  m_bc_board[8][7] = -2;
  m_bc_board[7][8] = -2;
}



kreversi'Engine::CalcBcScore() (./kdegames/kreversi/Engine.cpp:610)

int Engine::CalcBcScore(int player)
{
  int sum = 0;

  for (int i=1; i < 9; i++)
    for (int j=1; j < 9; j++)
      if (m_board[i][j] == player) 
	sum += m_bc_board[i][j];

  return sum;
}



kreversi'Engine::ComputeOccupiedBits() (./kdegames/kreversi/Engine.cpp:623)

ULONG64 Engine::ComputeOccupiedBits(int player)
{
  ULONG64 retval = 0;

  for (int i=1; i < 9; i++)
    for (int j=1; j < 9; j++)
      if (m_board[i][j] == player) retval |= m_coord_bit[i][j];

  return retval;
}