Example #1
0
bool
menu( game_t ** game )
{
	options_t options;
	char str[MAX_COM_LEN];
	modeOption_t modeOption;

	clearError();

	modeOption = chooseMode();

	raiseErrorIf( errorCode() == NOERROR, errorCode(), true );

	switch( modeOption ){
		case MODE0:
		case MODE1:
		case MODE2:
			options = chooseOptions( (modus_t)modeOption );
			raiseErrorIf( errorCode() == NOERROR, errorCode(), true );
			*game = newGame( &options );
			return true;
		case READFROMFILE:
			drawText("Enter the name of the file:\n");
			*game = readGame( askString( str ) );
			return true;
		case QUIT:
		default:
			return false;
	}
}
Example #2
0
bool gib::readStream(QString::iterator& first, QString::iterator last){
//    dataList_.push_back( data() );
    while (first != last){
        QString s = readLine(first, last);
        if (s == "\\HS")
            readHeader(first, last);
        else if (s == "\\GS")
            readGame(first, last);
    }

    return true;
}
Example #3
0
int main(int argc, const char * argv[]){

    sudokuGrid sample;

    readGame(sample);

    showGame(sample);
    printf("\n\n\n\n");

    if(hasSolution(sample)){
        showGame(sample);
    }

    getch();
    return 0;
}
Example #4
0
int main( int argc, char **argv )
{
  int sock, len, r;
  int32_t min, max;
  uint16_t port;
  Game *game;
  MatchState state;
  Action action;
  struct sockaddr_in addr;
  struct hostent *hostent;
  FILE *file, *toServer, *fromServer;
  char line[ MAX_LINE_LEN ];

  if( argc < 4 ) {

    fprintf( stderr, "usage: player game server port\n" );
    exit( EXIT_FAILURE );
  }

  file = fopen( argv[ 1 ], "r" );
  if( file == NULL ) {

    fprintf( stderr, "ERROR: could not open game %s\n", argv[ 1 ] );
    exit( EXIT_FAILURE );
  }
  game = readGame( file );
  if( game == NULL ) {

    fprintf( stderr, "ERROR: could not read game %s\n", argv[ 1 ] );
    exit( EXIT_FAILURE );
  }
  fclose( file );

  hostent = gethostbyname( argv[ 2 ] );
  if( hostent == NULL ) {

    fprintf( stderr, "ERROR: could not look up address for %s\n", argv[ 2 ] );
    exit( EXIT_FAILURE );
  }

  if( sscanf( argv[ 3 ], "%"SCNu16, &port ) < 1 ) {

    fprintf( stderr, "ERROR: invalid port %s\n", argv[ 3 ] );
    exit( EXIT_FAILURE );
  }

  if( ( sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {

    fprintf( stderr, "ERROR: could not open socket\n" );
    exit( EXIT_FAILURE );
  }

  addr.sin_family = AF_INET;
  addr.sin_port = htons( port );
  memcpy( &addr.sin_addr, hostent->h_addr_list[ 0 ], hostent->h_length );

  if( connect( sock, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 ) {

    fprintf( stderr, "ERROR: could not open connect to %s:%"PRIu16"\n",
	     argv[ 2 ], port );
    exit( EXIT_FAILURE );
  }

  toServer = fdopen( sock, "w" );
  fromServer = fdopen( sock, "r" );
  if( toServer == NULL || fromServer == NULL ) {

    fprintf( stderr, "ERROR: could not get socket streams\n" );
    exit( EXIT_FAILURE );
  }

  if( fprintf( toServer, "VERSION:%"PRIu32".%"PRIu32".%"PRIu32"\n",
	       VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION ) != 14 ) {

    fprintf( stderr, "ERROR: could not get send version to server\n" );
    exit( EXIT_FAILURE );
  }
  fflush( toServer );

  while( fgets( line, MAX_LINE_LEN, fromServer ) ) {

    /* ignore comments */
    if( line[ 0 ] == '#' || line[ 0 ] == ';' ) {
      continue;
    }

    len = readMatchState( line, game, &state );
    if( len < 0 ) {

      fprintf( stderr, "ERROR: could not read state %s", line );
      exit( EXIT_FAILURE );
    }

    if( stateFinished( &state.state ) ) {
      /* ignore the game over message */

      continue;
    }

    if( currentPlayer( game, &state.state ) != state.viewingPlayer ) {
      /* we're not acting */

      continue;
    }

	int bucket = computeHandValue(game,&state.state,state.viewingPlayer,min,max);
    
	/* add a colon (guaranteed to fit because we read a new-line in fgets) */
    line[ len ] = ':';
    ++len;

    //if( ( random() % 2 ) && raiseIsValid( game, &state.state, &min, &max ) ) {
      /* raise */
    if ((bucket >= 3) && raiseIsValid(game, &state.state, &min, &max)) {  
	  action.type = raise;
      action.size = min + random() % ( max - min + 1 );
    } else if (bucket >=2) {
      /* call */

      action.type = call;
      action.size = 0;
    }
	else{
		action.type = fold;
		action.size = 0;
	}

    if( !isValidAction( game, &state.state, 0, &action ) ) {

      fprintf( stderr, "ERROR: chose an invalid action\n" );
      exit( EXIT_FAILURE );
    }

    r = printAction( game, &action, MAX_LINE_LEN - len - 1,
		     &line[ len ] );
    if( r < 0 ) {

      fprintf( stderr, "ERROR: line too long after printing action\n" );
      exit( EXIT_FAILURE );
    }
    len += r;
    line[ len ] = '\n';
    ++len;

    if( fwrite( line, 1, len, toServer ) != len ) {

      fprintf( stderr, "ERROR: could not get send response to server\n" );
      exit( EXIT_FAILURE );
    }
    fflush( toServer );
  }

  return EXIT_SUCCESS;
}
Example #5
0
int main( int argc, char **argv )
{
  int i, listenSocket[ MAX_PLAYERS ], v, longOpt;
  int fixedSeats, quiet, append;
  int seatFD[ MAX_PLAYERS ];
  FILE *file, *logFile, *transactionFile;
  ReadBuf *readBuf[ MAX_PLAYERS ];
  Game *game;
  rng_state_t rng;
  ErrorInfo errorInfo;
  struct sockaddr_in addr;
  socklen_t addrLen;
  char *seatName[ MAX_PLAYERS ];

  int useLogFile, useTransactionFile;
  uint64_t maxResponseMicros, maxUsedHandMicros, maxUsedPerHandMicros;
  int64_t startTimeoutMicros;
  uint32_t numHands, seed, maxInvalidActions;
  uint16_t listenPort[ MAX_PLAYERS ];

  struct timeval startTime, tv;

  char name[ MAX_LINE_LEN ];
  static struct option longOptions[] = {
    { "t_response", 1, 0, 0 },
    { "t_hand", 1, 0, 0 },
    { "t_per_hand", 1, 0, 0 },
    { "start_timeout", 1, 0, 0 },
    { 0, 0, 0, 0 }
  };

  /* set defaults */

  /* game error conditions */
  maxInvalidActions = DEFAULT_MAX_INVALID_ACTIONS;
  maxResponseMicros = DEFAULT_MAX_RESPONSE_MICROS;
  maxUsedHandMicros = DEFAULT_MAX_USED_HAND_MICROS;
  maxUsedPerHandMicros = DEFAULT_MAX_USED_PER_HAND_MICROS;

  /* use random ports */
  for( i = 0; i < MAX_PLAYERS; ++i ) {

    listenPort[ i ] = 0;
  }

  /* use log file, don't use transaction file */
  useLogFile = 1;
  useTransactionFile = 0;

  /* print all messages */
  quiet = 0;

  /* by default, overwrite preexisting log/transaction files */
  append = 0;

  /* players rotate around the table */
  fixedSeats = 0;

  /* no timeout on startup */
  startTimeoutMicros = -1;

  /* parse options */
  while( 1 ) {

    i = getopt_long( argc, argv, "flLp:qtTa", longOptions, &longOpt );
    if( i < 0 ) {

      break;
    }

    switch( i ) {
    case 0:
      /* long option longOpt */

      switch( longOpt ) {
      case 0:
	/* t_response */

	if( sscanf( optarg, "%"SCNu64, &maxResponseMicros ) < 1 ) {

	  fprintf( stderr, "ERROR: could not get response timeout from %s\n",
		   optarg );
	  exit( EXIT_FAILURE );
	}

	/* convert from milliseconds to microseconds */
	maxResponseMicros *= 1000;
	break;

      case 1:
	/* t_hand */

	if( sscanf( optarg, "%"SCNu64, &maxUsedHandMicros ) < 1 ) {

	  fprintf( stderr,
		   "ERROR: could not get player hand timeout from %s\n",
		   optarg );
	  exit( EXIT_FAILURE );
	}

	/* convert from milliseconds to microseconds */
	maxUsedHandMicros *= 1000;
	break;

      case 2:
	/* t_per_hand */

	if( sscanf( optarg, "%"SCNu64, &maxUsedPerHandMicros ) < 1 ) {

	  fprintf( stderr, "ERROR: could not get average player hand timeout from %s\n", optarg );
	  exit( EXIT_FAILURE );
	}

	/* convert from milliseconds to microseconds */
	maxUsedPerHandMicros *= 1000;
	break;

      case 3:
	/* start_timeout */

	if( sscanf( optarg, "%"SCNd64, &startTimeoutMicros ) < 1 ) {

	  fprintf( stderr, "ERROR: could not get start timeout %s\n", optarg );
	  exit( EXIT_FAILURE );
	}

	/* convert from milliseconds to microseconds */
	if( startTimeoutMicros > 0 ) {

	  startTimeoutMicros *= 1000;
	}
	break;

      }
      break;

    case 'f':
      /* fix the player seats */;

      fixedSeats = 1;
      break;

    case 'l':
      /* no transactionFile */;

      useLogFile = 0;
      break;

    case 'L':
      /* use transactionFile */;

      useLogFile = 1;
      break;

    case 'p':
      /* port specification */

      if( scanPortString( optarg, listenPort ) < 0 ) {

	fprintf( stderr, "ERROR: bad port string %s\n", optarg );
	exit( EXIT_FAILURE );
      }

      break;

    case 'q':

      quiet = 1;
      break;

    case 't':
      /* no transactionFile */

      useTransactionFile = 0;
      break;

    case 'T':
      /* use transactionFile */

      useTransactionFile = 1;
      break;

    case 'a':

      append = 1;
      break;

    default:

      fprintf( stderr, "ERROR: unknown option %c\n", i );
      exit( EXIT_FAILURE );
    }
  }

  if( optind + 4 > argc ) {

    printUsage( stdout, 0 );
    exit( EXIT_FAILURE );
  }

  /* get the game definition */
  file = fopen( argv[ optind + 1 ], "r" );
  if( file == NULL ) {

    fprintf( stderr, "ERROR: could not open game definition %s\n",
	     argv[ optind + 1 ] );
    exit( EXIT_FAILURE );
  }
  game = readGame( file );
  if( game == NULL ) {

    fprintf( stderr, "ERROR: could not read game %s\n", argv[ optind + 1 ] );
    exit( EXIT_FAILURE );
  }
  fclose( file );

  /* save the seat names */
  if( optind + 4 + game->numPlayers > argc ) {

    printUsage( stdout, 0 );
    exit( EXIT_FAILURE );
  }
  for( i = 0; i < game->numPlayers; ++i ) {

    seatName[ i ] = argv[ optind + 4 + i ];
  }

  /* get number of hands */
  if( sscanf( argv[ optind + 2 ], "%"SCNu32, &numHands ) < 1
      || numHands == 0 ) {

    fprintf( stderr, "ERROR: invalid number of hands %s\n",
	     argv[ optind + 2 ] );
    exit( EXIT_FAILURE );
  }

  /* get random number seed */
  if( sscanf( argv[ optind + 3 ], "%"SCNu32, &seed ) < 1 ) {

    fprintf( stderr, "ERROR: invalid random number seed %s\n",
	     argv[ optind + 3 ] );
    exit( EXIT_FAILURE );
  }
  init_genrand( &rng, seed );
  srandom( seed ); /* used for random port selection */

  if( useLogFile ) {
    /* create/open the log */
    if( snprintf( name, MAX_LINE_LEN, "%s.log", argv[ optind ] ) < 0 ) {

      fprintf( stderr, "ERROR: match file name too long %s\n", argv[ optind ] );
      exit( EXIT_FAILURE );
    }
    if (append) {
      logFile = fopen( name, "a+" );
    } else {
      logFile = fopen( name, "w" );
    }
    if( logFile == NULL ) {

      fprintf( stderr, "ERROR: could not open log file %s\n", name );
      exit( EXIT_FAILURE );
    }
  } else {
    /* no log file */

    logFile = NULL;
  }

  if( useTransactionFile ) {
    /* create/open the transaction log */

    if( snprintf( name, MAX_LINE_LEN, "%s.tlog", argv[ optind ] ) < 0 ) {

      fprintf( stderr, "ERROR: match file name too long %s\n", argv[ optind ] );
      exit( EXIT_FAILURE );
    }
    if (append) {
      transactionFile = fopen( name, "a+" );
    } else {
      transactionFile = fopen( name, "w" );
    }
    if( transactionFile == NULL ) {

      fprintf( stderr, "ERROR: could not open transaction file %s\n", name );
      exit( EXIT_FAILURE );
    }
  } else {
    /* no transaction file */

    transactionFile = NULL;
  }

  /* set up the error info */
  initErrorInfo( maxInvalidActions, maxResponseMicros, maxUsedHandMicros,
		 maxUsedPerHandMicros * numHands, &errorInfo );

  /* open sockets for players to connect to */
  for( i = 0; i < game->numPlayers; ++i ) {

    listenSocket[ i ] = getListenSocket( &listenPort[ i ] );
    if( listenSocket[ i ] < 0 ) {

      fprintf( stderr, "ERROR: could not create listen socket for player %d\n",
	       i + 1 );
      exit( EXIT_FAILURE );
    }
  }

  /* print out the final port assignments */
  for( i = 0; i < game->numPlayers; ++i ) {

    printf( i ? " %"PRIu16 : "%"PRIu16, listenPort[ i ] );
  }
  printf( "\n" );
  fflush( stdout );

  /* print out usage information */
  printInitialMessage( argv[ optind ], argv[ optind + 1 ],
		       numHands, seed, &errorInfo, logFile );

  /* wait for each player to connect */
  gettimeofday( &startTime, NULL );
  for( i = 0; i < game->numPlayers; ++i ) {

    if( startTimeoutMicros >= 0 ) {
      uint64_t startTimeLeft;
      fd_set fds;

      gettimeofday( &tv, NULL );
      startTimeLeft = startTimeoutMicros
	- (uint64_t)( tv.tv_sec - startTime.tv_sec ) * 1000000
	- ( tv.tv_usec - startTime.tv_usec );
      if( startTimeLeft < 0 ) {

	startTimeLeft = 0;
      }
      tv.tv_sec = startTimeLeft / 1000000;
      tv.tv_usec = startTimeLeft % 1000000;

      FD_ZERO( &fds );
      FD_SET( listenSocket[ i ], &fds );
      if( select( listenSocket[ i ] + 1, &fds, NULL, NULL, &tv ) < 1 ) {
	/* no input ready within time, or an actual error */

	fprintf( stderr, "ERROR: timed out waiting for seat %d to connect\n",
		 i + 1 );
	exit( EXIT_FAILURE );
      }
    }

    addrLen = sizeof( addr );
    seatFD[ i ] = accept( listenSocket[ i ],
			  (struct sockaddr *)&addr, &addrLen );
    if( seatFD[ i ] < 0 ) {

      fprintf( stderr, "ERROR: seat %d could not connect\n", i + 1 );
      exit( EXIT_FAILURE );
    }
    close( listenSocket[ i ] );

    v = 1;
    setsockopt( seatFD[ i ], IPPROTO_TCP, TCP_NODELAY,
		(char *)&v, sizeof(int) );

    readBuf[ i ] = createReadBuf( seatFD[ i ] );
  }

  /* play the match */
  if( gameLoop( game, seatName, numHands, quiet, fixedSeats, &rng, &errorInfo,
		seatFD, readBuf, logFile, transactionFile ) < 0 ) {
    /* should have already printed an error message */

    exit( EXIT_FAILURE );
  }

  //fflush( stderr );
  //fflush( stdout );
  // Otherwise the last line or two of the log file
  // won't be written sometimes when run through a
  // Ruby interface.
  fflush(NULL);
  if( transactionFile != NULL ) {
    fclose( transactionFile );
  }
  if( logFile != NULL ) {
    fclose( logFile );
  }
  free( game );

  return EXIT_SUCCESS;
}
Example #6
0
void Game::play()
{
	long maxp = gameSettings->getMaxp();
	long maxl = gameSettings->getMaxl();
	long maxg = gameSettings->getMaxg();
	int level = gameSettings->getLevel();
	int preview = gameSettings->getPreview();
	int stat = gameSettings->getStat();
	int size = gameSettings->getSize();
	int sliding = gameSettings->getSliding();
	int delay = gameSettings->getDelay();
	int animate = gameSettings->getAnimate();
	int exit = gameSettings->getExit();
	int pieceStartX = gameSettings->getPieceStartX();
	int frameRateDelay = gameSettings->getFrameRateDelay();
	int nextPiece = 0;
	int viewBoard = gameSettings->getViewBoard();
	int stepMode = gameSettings->getStepMode();
	milisec1 = GetTickCount();
	milisec2 = GetTickCount();
	seconds = time(NULL);

	if (strlen(gameSettings->getWgameFilename()) != 0)
	{
		if (wGameFile.open(gameSettings->getWgameFilename()))
		{
			cout << "Could not open the file  \"" << gameSettings->getWgameFilename() << "\"" << endl;

			return;
		}
	}

	if (strlen(gameSettings->getRgameFilename()) != 0)
	{
		if (rGameFile.open(gameSettings->getRgameFilename()))
		{
			cout << "Could not open the file  \"" << gameSettings->getRgameFilename() << "\"" << endl;

			return;
		}
	}

	if (strlen(gameSettings->getWhtmlFilename()) != 0)
	{
		wHtml.open(gameSettings->getWhtmlFilename());

		if (!wHtml.good())
		{
			cout << "Could not open the file  \"" << gameSettings->getWhtmlFilename() << "\"" << endl;

			return;
		}
	}

  board = new Board(gameSettings->getWidth(), gameSettings->getHeight(), sliding, pieceStartX);

	Piece setStaticInitializersPiece(board, 1, sliding, 1);

	Player *player = new Player(board);

	Random random = Random(gameSettings->getSeed());
	GameInfo gameInfo(maxCntblockstat);

  writeTmpFile(board);

	double equity = player->evaluate();
	double maxDiff = 0;

	int pieces[10];

	if (preview > 1)
		pieces[0] = random.getRandomP();

	pieces[1] = 0;
	pieces[2] = 0;
	pieces[3] = 0;
	pieces[4] = 0;
	pieces[5] = 0;
	pieces[6] = 0;
	pieces[7] = 0;
	pieces[8] = 0;
	pieces[9] = 0;

	if (wGameFile.isOpen())
	{
		// 1. Version of the file
		wGameFile.writeShort(1);													// # Version (short)
		
		// 2. Header
		wGameFile.writeShort(DATA_HEADER);								// # Type of block
		wGameFile.writeShort(1);													// # Version
		wGameFile.writeShort(gameSettings->getWidth());		// # Width (short)
		wGameFile.writeShort(gameSettings->getHeight());	// # Height (short)
		wGameFile.writeInt(gameSettings->getSeed());			// # Seed (int)
		wGameFile.writeByte(gameSettings->getLevel());		// # Level (byte)
		wGameFile.writeByte(gameSettings->getPreview());	// # Preview (byte)
		wGameFile.writeByte(pieces[0]);      							// # Piece (byte)
	}

	while ((maxg==0 && maxl==0 && maxp==0) || 
		     ((maxg > 0 && games < maxg) ||
		      (maxl > 0 && totalLines < maxl) ||
				  (maxp > 0 && totalPieces < maxp)))
	{
		if (exit == 1 || gameSettings->getExit() == 1)
			break;

		//-------------------------------------------
		if (stepMode != gameSettings->getStepMode()) {
			stepMode = gameSettings->getStepMode();
			initTime();
		}
		
		if (level != gameSettings->getLevel()) {
			level = gameSettings->getLevel();
			initTime();
		}

		if (sliding != gameSettings->getSliding())
		{
			sliding = gameSettings->getSliding();
			board->setSliding(sliding);
			initTime();
		}

		if (preview != gameSettings->getPreview())
		{
			preview = gameSettings->getPreview();

			if (preview == 1)
				pieces[1] = 0;
			else
			{
				if (nextPiece == 0)
					nextPiece = pieces[1] = random.getRandomP();
				else
					pieces[1] = nextPiece;
			}

			initTime();
		}

		if (animate != gameSettings->getAnimate()) {
			animate = gameSettings->getAnimate();
			initTime();
		}

		if (delay != gameSettings->getDelay()) {
			delay = gameSettings->getDelay();
			initTime();
		}

		if (frameRateDelay != gameSettings->getFrameRateDelay()) {
			frameRateDelay = gameSettings->getFrameRateDelay();
			initTime();
		}

		if (viewBoard != gameSettings->getViewBoard()) {
			viewBoard = gameSettings->getViewBoard();
			initTime();
		}

		while (gameSettings->isPause())
			::Sleep(10);

		if (board->getWidth() != gameSettings->getWidth())
		{
			delete board;
			pieceStartX = gameSettings->getPieceStartX();
			board = new Board(gameSettings->getWidth(), gameSettings->getHeight(), sliding, pieceStartX);
			Piece setStaticInitializersPiece(board, 1, sliding, 1);			
		}
		//-------------------------------------------

		if (preview > 1)
			nextPiece = pieces[1] = random.getRandomP();
		else
			pieces[0] = random.getRandomP();

		if (wGameFile.isOpen())
			wGameFile.writeByte(pieces[1]);									// # Piece

		Piece bestPiece(board, pieces[0]);


		gameObserverList.notify(board, 
														&gameInfo, 
														pieces[0], 
														pieces[1], 
														1, 
														milisec1,
														milisec2,
														cntblockstat, 
														games,
														cntPieces,
														cntLines,
														totalMoves,
														totalSlided,
														totalLines,
														totalLines2,
														totalPieces,
														totalPieces2,
														minLines,
														maxLines,
														linesPerGame);


		if (!animate)
			::Sleep(delay*10);

		int playAgain;
		Move *bestMove;
		MoveList *moveList;

		do
		{
			playAgain = 0;
			gameSettings->setIsThinking();

			if (animate != gameSettings->getAnimate()) {
				animate = gameSettings->getAnimate();
				initTime();
			}

			bestMove = player->play(pieces, level, preview, animate, &gameObserverList);

			if (bestMove > 0)
				bestPiece.set(bestMove->getV(), bestMove->getX(), bestMove->getY(), bestMove->getClearedLines());

			gameSettings->setIsNotThinking();

			moveList = board->getMoveList(level);

			gameObserverList.notify(moveList);

			while (gameSettings->isStepModeOn() && gameSettings->isStepWait())
			{
				if (level != gameSettings->getLevel()) {
					level = gameSettings->getLevel();
					initTime();
					playAgain = 1;
					break;
				}

				if (preview != gameSettings->getPreview())
				{
					preview = gameSettings->getPreview();

					if (preview == 1)
						pieces[1] = 0;
					else
					{
						if (nextPiece == 0)
							nextPiece = pieces[1] = random.getRandomP();
						else
							pieces[1] = nextPiece;
					}

					initTime();
					playAgain = 1;

					gameObserverList.notify(board, 
																	&gameInfo, 
																	pieces[0], 
																	pieces[1], 
																	1, 
																	milisec1,
																	milisec2,
																	cntblockstat, 
																	games,
																	cntPieces,
																	cntLines,
																	totalMoves,
																	totalSlided,
																	totalLines,
																	totalLines2,
																	totalPieces,
																	totalPieces2,
																	minLines,
																	maxLines,
																	linesPerGame);



					break;
				}

				if (sliding != gameSettings->getSliding() && bestMove > 0)
				{
					sliding = gameSettings->getSliding();
					board->setSliding(sliding);

					initTime();
					playAgain = 1;
					break;
				}

				::Sleep(10);
			}
		} while (playAgain);

		if (gameSettings->isStepModeOn())
			gameSettings->setStepWait();

		if (!animate && bestMove > 0)
		{
			bestPiece.setPiece();

			if (bestPiece.getClearedLines() > 0)
				board->clearLines(bestPiece.getY(), bestPiece.getHeight());
		}

		Move *move;
		int index = 0;

		int length = moveList->getLength();

		totalMoves += length;

		if (animate && bestMove > 0)
		{
			// Animate the moves.
			MovePath *movePath = board->getMovePath(level);
			MovePathStep *s = movePath->getPath(bestMove->getV(), bestMove->getX(), bestMove->getY());

			int skipFirst = 0;

			int prevy = -1;

			while (s > 0)
			{
				//----
				// Calculate the number of steps for the current line (y value).
				MovePathStep *s1 = s;
				int y1 = s1->y;
				int cnt;

				if (prevy != y1)
				{
					cnt = 0;

					while (s1 > 0 && s1->y == y1) {
						cnt++;
						s1 = s1->next;
					}
					prevy = y1;
				}
				//----
				
				if (animate != gameSettings->getAnimate())
					break;

				if (delay != gameSettings->getDelay())
					delay = gameSettings->getDelay();

				int v = s->v;
				int x = s->x;
				int y = s->y;

				Piece piece(board, bestPiece.getP());
				piece.setPiece(v, x, y);

				if (skipFirst)
					gameObserverList.notify(board, 
																	&gameInfo, 
																	pieces[0], 
																	pieces[1], 
																	0, 
																	milisec1,
																	milisec2,
																	cntblockstat, 
																	games,
																	cntPieces,
																	cntLines,
																	totalMoves,
																	totalSlided,
																	totalLines,
																	totalLines2,
																	totalPieces,
																	totalPieces2,
																	minLines,
																	maxLines,
																	linesPerGame);

				if (gameSettings->isSlidingOn())
					::Sleep((double)delay / cnt);
				else
					::Sleep((double)delay);

				piece.clearPiece();
				skipFirst = 1;
				s = s->next;

				while (gameSettings->isPause())
					::Sleep(10);
			}

			bestPiece.setPiece();

			if (bestPiece.getClearedLines() > 0)
			{
				int clearedLinesBits = board->getClearedLines(bestPiece.getY(), bestPiece.getHeight());

				for (int n=0; n<4; n++)
				{
					board->flashLines(bestPiece.getY(), bestPiece.getHeight(), clearedLinesBits);
					
					if (n<3)
					{
						gameObserverList.notify(board, 
																		&gameInfo, 
																		pieces[0], 
																		pieces[1], 
																		0, 
																		milisec1,
																		milisec2,
																		cntblockstat, 
																		games,
																		cntPieces,
																		cntLines,
																		totalMoves,
																		totalSlided,
																		totalLines,
																		totalLines2,
																		totalPieces,
																		totalPieces2,
																		minLines,
																		maxLines,
																		linesPerGame);

						if (delay > 0)
						{
							if (delay >= 50)
								::Sleep(150);
							else
								::Sleep(150-(50-delay)*2);
						}
					}
				}

				board->clearLines(bestPiece.getY(), bestPiece.getHeight());
			}
		}

		cntPieces++;
		totalPieces++;
		
		if (bestMove > 0)
			totalSlided += bestMove->isSlided();

		// Log the moves
		if (wGameFile.isOpen())
		{
			wGameFile.writeShort(length);											// # Number of legal moves.
			wGameFile.writeByte(bestPiece.getV());						// # V
			wGameFile.writeShort(bestPiece.getX());						// # X
			wGameFile.writeShort(bestPiece.getY());						// # Y

			move = moveList->getFirstMove();

			while (move != 0)
			{																									// Move:
				wGameFile.writeByte(move->getV());							// # V
				wGameFile.writeShort(move->getX());							// # X
				wGameFile.writeShort(move->getY());							// # Y

				for (int i=preview; i<=level; i++)							// Equity (e.g):
					wGameFile.writeFloat(move->getEquity(i));			// L2, L3, L4

				move = moveList->getNextMove();
			}
		}

		if (preview > 1)
			pieces[0] = pieces[1];

  	int clearedLines = bestPiece.getClearedLines();

  	if (bestMove == 0) 
		{
  		games++;
  		
			linesPerGame = totalLines/games;
		}
		else
		{
			cntLines += clearedLines;
			totalLines += clearedLines;

			cntBlock += 4 - clearedLines * board->getWidth();

			if (DEBUG == 0)
			{
				int xxx = cntBlock/4;
				if (xxx < maxCntblockstat)
					cntblockstat[xxx]++;
			}
		}

  	if (cntLines > maxLines)
  		maxLines = cntLines;

		if (bestMove == 0)
		{
  		if (cntLines < minLines || minLines==-1)
  			minLines = cntLines;
			
			cntBlock = 0;
			cntPieces = 0;
  		cntLines = 0;
		  board->clear();
			pieces[0] = random.getRandomP();
		}
	}

	delete board;
	delete player;

	if (wGameFile.isOpen())
	{
		wGameFile.writeByte(END_PIECE);				// # Piece
		wGameFile.close();
	}

	if (rGameFile.isOpen() && strlen(gameSettings->getWhtmlFilename()) > 0)
	{
		readGame(maxp, size);
		rGameFile.close();
	}

	gameSettings->setExit(2);
}