[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdegames/kreversi
From:       Dmitry Suzdalev <dimsuz () gmail ! com>
Date:       2007-12-05 9:08:45
Message-ID: 1196845725.171904.20756.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 745061 by dimsuz:

Fix crash caused by the fact that KReversi Engine can't compute to moves at the same time.
Someday it should become multithreaded I guess...

BUG: 153465


 M  +48 -33    Engine.cpp  
 M  +3 -1      Engine.h  
 M  +2 -0      commondefs.h  
 M  +13 -1     kreversigame.cpp  
 M  +1 -1      kreversiscene.cpp  


--- trunk/KDE/kdegames/kreversi/Engine.cpp #745060:745061
@@ -118,6 +118,7 @@
 #include "Engine.h"
 #include "kreversigame.h"
 #include <QApplication>
+#include <KDebug>
 
 // ================================================================
 //                          Class ULONG64
@@ -126,7 +127,7 @@
 #if !defined(__GNUC__)
 
 
-ULONG64::ULONG64() : QBitArray(64) 
+ULONG64::ULONG64() : QBitArray(64)
 {
   fill(0);
 }
@@ -135,7 +136,7 @@
 // Initialize an ULONG64 from a 32 bit value.
 //
 
-ULONG64::ULONG64( unsigned int value ) : QBitArray(64) 
+ULONG64::ULONG64( unsigned int value ) : QBitArray(64)
 {
   fill(0);
   for(int i = 0; i < 32; i++) {
@@ -148,7 +149,7 @@
 // Shift an ULONG64 left one bit.
 //
 
-void ULONG64::shl() 
+void ULONG64::shl()
 {
   for(int i = 63; i > 0; i--)
     setBit(i, testBit(i - 1));
@@ -191,7 +192,7 @@
 }
 
 
-void SquareStack::resize(int size) 
+void SquareStack::resize(int size)
 {
   m_squarestack.resize(size);
 }
@@ -201,7 +202,7 @@
 // resize it to 'size'.
 //
 
-void SquareStack::init(int size) 
+void SquareStack::init(int size)
 {
   resize(size);
 
@@ -212,7 +213,7 @@
 
 
 
-inline SquareStackEntry SquareStack::Pop() 
+inline SquareStackEntry SquareStack::Pop()
 {
   return m_squarestack[--m_top];
 }
@@ -233,7 +234,7 @@
 //
 
 
-inline void MoveAndValue::setXYV(int x, int y, int value) 
+inline void MoveAndValue::setXYV(int x, int y, int value)
 {
   m_x     = x;
   m_y     = y;
@@ -241,13 +242,13 @@
 }
 
 
-MoveAndValue::MoveAndValue() 
+MoveAndValue::MoveAndValue()
 {
   setXYV(0,0,0);
 }
 
 
-MoveAndValue::MoveAndValue(int x, int y, int value) 
+MoveAndValue::MoveAndValue(int x, int y, int value)
 {
   setXYV(x, y, value);
 }
@@ -274,7 +275,7 @@
   void dec(ChipColor color)             { m_score[color]--; }
   void add(ChipColor color, uint s)     { m_score[color] += s; }
   void sub(ChipColor color, uint s)     { m_score[color] -= s; }
-  
+
 private:
   uint  m_score[2];
 };
@@ -290,7 +291,7 @@
 
 
 Engine::Engine(int st, int sd)/* : SuperEngine(st, sd) */
-    : m_strength(st)
+    : m_strength(st), m_computingMove( false )
 {
   m_random.setSeed(sd);
   m_score = new Score;
@@ -300,8 +301,8 @@
 }
 
 
-Engine::Engine(int st) //: SuperEngine(st) 
-    : m_strength(st)
+Engine::Engine(int st) //: SuperEngine(st)
+    : m_strength(st), m_computingMove(false)
 {
   m_random.setSeed(0);
   m_score = new Score;
@@ -311,8 +312,8 @@
 }
 
 
-Engine::Engine()// : SuperEngine(1) 
-    : m_strength(1)
+Engine::Engine()// : SuperEngine(1)
+    : m_strength(1), m_computingMove(false)
 {
   m_random.setSeed(0);
   m_score = new Score;
@@ -328,7 +329,7 @@
 }
 
 // keep GUI alive
-void Engine::yield() 
+void Engine::yield()
 {
   qApp->processEvents();
 }
@@ -336,8 +337,15 @@
 
 // Calculate the best move from the current position, and return it.
 
-KReversiPos Engine::computeMove(const KReversiGame& game, bool competitive) 
+KReversiPos Engine::computeMove(const KReversiGame& game, bool competitive)
 {
+    if( m_computingMove )
+    {
+        kDebug() << "I'm already computing move! Yours KReversi Engine.";
+        return KReversiPos();
+    }
+    m_computingMove = true;
+
   ChipColor color;
 
   // A competitive game is one where we try our damnedest to make the
@@ -355,7 +363,10 @@
   // Get the color to calculate the move for.
   color = game.currentPlayer();
   if (color == NoColor)
-    return KReversiPos(NoColor, -1, -1);
+  {
+      m_computingMove = false;
+      return KReversiPos();
+  }
 
   // Figure out the current score
   m_score->set(White, game.playerScore(White));
@@ -364,7 +375,10 @@
   // Treat the first move as a special case (we can basically just
   // pick a move at random).
   if (m_score->score(White) + m_score->score(Black) == 4)
-    return ComputeFirstMove(game);
+  {
+      m_computingMove = false;
+      return ComputeFirstMove(game);
+  }
 
   // Let there be room for 3000 changes during the recursive search.
   // This is more than will ever be needed.
@@ -372,7 +386,7 @@
 
   // Get the search depth.  If we are close to the end of the game,
   // the number of possible moves goes down, so we can search deeper
-  // without using more time.  
+  // without using more time.
   m_depth = m_strength;
   if (m_score->score(White) + m_score->score(Black) + m_depth + 3 >= 64)
     m_depth = 64 - m_score->score(White) - m_score->score(Black);
@@ -392,7 +406,7 @@
   // values and the later in the game the more we use the number of
   // pieces.
   m_coeff = 100 - (100*
-		   (m_score->score(White) + m_score->score(Black) 
+		   (m_score->score(White) + m_score->score(Black)
 		    + m_depth - 4)) / 60;
 
   // Initialize the board that we use for the search.
@@ -430,7 +444,7 @@
   null_bits = 0;
 
   // The main search loop.  Step through all possible moves and keep
-  // track of the most valuable one.  This move is stored in 
+  // track of the most valuable one.  This move is stored in
   // (max_x, max_y) and the value is stored in maxval.
   m_nodes_searched = 0;
   for (int x = 1; x < 9; x++) {
@@ -458,8 +472,8 @@
 	  // user wants a casual game, which is set in the settings
 	  // dialog.
 	  int randi = m_random.getLong(7);
-	  if (maxval == -LARGEINT 
-	      || m_competitive 
+	  if (maxval == -LARGEINT
+	      || m_competitive
 	      || randi < (int) m_strength) {
 	    maxval = val;
 	    max_x  = x;
@@ -473,7 +487,7 @@
       }
 
       // Jump out prematurely if interrupt is set.
-      if (interrupted()) 
+      if (interrupted())
 	break;
     }
   }
@@ -486,7 +500,7 @@
     int  i;
 
     for (i = 0; i < number_of_moves; i++) {
-      if (moves[i].m_value == maxval && --r <= 0) 
+      if (moves[i].m_value == maxval && --r <= 0)
 	break;
     }
 
@@ -494,6 +508,7 @@
     max_y = moves[i].m_y;
   }
 
+  m_computingMove = false;
   // Return a suitable move.
   if (interrupted())
     return KReversiPos(NoColor, -1, -1);
@@ -507,7 +522,7 @@
 // Get the first move.  We can pick any move at random.
 //
 
-KReversiPos Engine::ComputeFirstMove(const KReversiGame& game) 
+KReversiPos Engine::ComputeFirstMove(const KReversiGame& game)
 {
   int    r;
   ChipColor  color = game.currentPlayer();
@@ -554,7 +569,7 @@
   // Loop through all 8 directions and turn the pieces that can be turned.
   for (int xinc = -1; xinc <= 1; xinc++)
     for (int yinc = -1; yinc <= 1; yinc++) {
-      if (xinc == 0 && yinc == 0) 
+      if (xinc == 0 && yinc == 0)
 	continue;
 
       int x, y;
@@ -616,7 +631,7 @@
 	  else {
 	    // Take a sure win and avoid a sure loss (may not be optimal):
 
-	    if (finalscore > 0) 
+	    if (finalscore > 0)
 	      retval = LARGEINT - 65 + finalscore;
 	    else if (finalscore < 0)
 	      retval = -(LARGEINT - 65 + finalscore);
@@ -670,14 +685,14 @@
 
   for (int x = 1; x < 9; x++) {
     for (int y = 1; y < 9; y++) {
-      if (m_board[x][y] == NoColor 
+      if (m_board[x][y] == NoColor
 	  && (m_neighbor_bits[x][y] & colorbits) != null_bits) {
 	int val = ComputeMove2(x, y, opponent, level+1, maxval, opponentbits,
 			       colorbits);
 
 	if (val != ILLEGAL_VALUE && val > maxval) {
 	  maxval = val;
-	  if (maxval > -cutoffval || interrupted()) 
+	  if (maxval > -cutoffval || interrupted())
 	    break;
 	}
       }
@@ -687,7 +702,7 @@
       break;
   }
 
-  if (interrupted()) 
+  if (interrupted())
     return -LARGEINT;
 
   return maxval;
@@ -713,7 +728,7 @@
     retval = score_color - score_opponent;
   else {
     retval = (100-m_coeff) *
-      (m_score->score(color) - m_score->score(opponent)) 
+      (m_score->score(color) - m_score->score(opponent))
       + m_coeff * BC_WEIGHT * (m_bc_score->score(color)
 			       - m_bc_score->score(opponent));
   }
--- trunk/KDE/kdegames/kreversi/Engine.h #745060:745061
@@ -249,7 +249,7 @@
   Score*        m_score;
   Score*        m_bc_score;
   SquareStack  m_squarestack;
-  
+
   int          m_depth;
   int          m_coeff;
   int          m_nodes_searched;
@@ -262,6 +262,8 @@
 
   ULONG64      m_coord_bit[9][9];
   ULONG64      m_neighbor_bits[9][9];
+
+  bool m_computingMove;
 };
 
 #endif
--- trunk/KDE/kdegames/kreversi/commondefs.h #745060:745061
@@ -33,6 +33,8 @@
     ChipColor color;
     int row;
     int col;
+
+    bool isValid() const { return ( color != NoColor || row != -1 || col != -1 ); }
 };
 
 typedef QList<KReversiPos> PosList;
--- trunk/KDE/kdegames/kreversi/kreversigame.cpp #745060:745061
@@ -79,7 +79,11 @@
     if( !demoMode )
         move = KReversiPos( m_playerColor, row, col );
     else
+    {
         move = m_engine->computeMove( *this, true );
+        if( !move.isValid() )
+            return;
+    }
 
     if( !isMovePossible(move) )
     {
@@ -145,7 +149,15 @@
     // FIXME dimsuz: m_competitive. Read from config.
     // (also there's computeMove in getHint)
     KReversiPos move = m_engine->computeMove( *this, true );
-    Q_ASSERT(move.color == m_computerColor);
+    if( !move.isValid() )
+        return;
+
+    if( move.color != m_computerColor )
+    {
+        kDebug() << "Strange! makeComputerMove() just got not computer move!";
+        return;
+    }
+
     makeMove(move);
     m_undoStack.push( m_changedChips );
 }
--- trunk/KDE/kdegames/kreversi/kreversiscene.cpp #745060:745061
@@ -392,7 +392,7 @@
         return;
     }
     KReversiPos hint = m_game->getHint();
-    if(hint.row == -1 || hint.col == -1)
+    if( !hint.isValid() )
         return;
     if( m_hintChip == 0 )
         m_hintChip = new KReversiChip( hint.color, m_frameSet, this );
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic