Esempio n. 1
0
int main( int argc, char *argv[] ) {
	printf( "have %i args\n", argc );
	printf( "first arg: %s\n", argv[0] );
	PuzzleState ps;
	PiecesLeft pl;
	if( argc == 2 ) {
		LoadState( ps, pl, argv[1] );
		sprintf( solutionfilename, "SOLVED_%s", argv[1] );
		printf( "Solving\n");
		PrintRemainingPieces( pl );
		Solve( pl, ps );
		printf( "Unsolvable?\n");
	} else {
		Piece e = pieces[4];
		for( int ori = 0; ori < 8; ++ori ) {
			printf( "Piece rotated %i\n", ori );
			PrintPiece( Rot( e, ori ) );
			printf( "\n" );
		}
	}
}
Esempio n. 2
0
/* Evaluate the current board position for the side stored in the board
 * structure. Score for white.  (Score for black = -1* this.)  We also pass the values
 * of alpha and beta to this routine on the expectation that we might be able to get a
 * cutoff if the score is particularly high or low without having to do the time consuming
 * part of the eval().  */
int EvalMain(Board *B, int alpha, int beta) {
  int sq,p,npw=0,tpts=B->WPts+B->BPts,sq2,def, score=0;
  int *SpDef, *SpWon, lazyscore;
  BITBOARD pieces = B->All;
  BOOL one_sided;
#ifdef DEBUG_EVAL
  int control = 0, oldscore = 0, contestcount = 0;
#endif
  
  /* Check for a drawn position */
  if (IsDrawnMaterial(B))
    return ((Current_Board.side == WHITE) ? (DRAW_SCORE) : -(DRAW_SCORE));
  
  /* Check if the game is theoretically won/lost */
  score = IsWonGame(B);
#ifdef DEBUG_EVAL
  if (score != 0) fprintf(stdout,"\nPosition Theoretically Won : %d\n\n",score);
#endif

  /* Check to see if we can just cutoff here - this score is so good that
   * we needn't bother working it out exactly - it's going to cause a cutoff. 
   * We have to be very careful because the score difference gained by doing
   * a proper eval here might be huge, therefore we only cutoff if this
   * position is theoretically won, and beta isn't, or it is theoretically
   * lost and alpha isn't. We can't just use standard futility cutoffs like
   * we do below, because in theoretically won positions, the score returned
   * by LazyEval() will almost always be much larger than EVAL_FUTILITY. */
  if (USE_EVAL_SC && score!=0 && ((score > 0 && beta<T_WIN_BOUND) ||
                                  (score < 0 && alpha>-(T_WIN_BOUND)))) {
    EvalCuts++;
#ifdef DEBUG_EVAL
    fprintf(stdout,"Early Cut [1] %d  (A=%d,B=%d)\n",score,alpha,beta);
#endif
    return score;
  }
  
   /* Get a lazy score evaluation
    * (material score & simple positional terms plus passed pawns) */
  lazyscore = LazyEval(B) + score;

   /* Check to see if we can just cutoff here.  The expectation is that the LazyEval
    * is alway within EVAL_FUTILITY of the true score.  Of course this isn't always
    * true, but we hope that it is true most of the time. */
  if (USE_EVAL_SC && (lazyscore > (beta+EVAL_FUTILITY) || lazyscore < (alpha-EVAL_FUTILITY))) {
    EvalCuts++;
#ifdef DEBUG_EVAL
    fprintf(stdout,"Early Cut [2] %d  (A=%d,B=%d)\n",lazyscore,alpha,beta);
#endif
    return lazyscore;
  } 

   /* We didn't get a cutoff so we have to be more careful and evaluate the board properly.
    * Begin with the LazyEval() score we obtained BEFORE any possible truncation due to lack
    * of mating material (we don't want to do this twice!). */
  score += prematscore;

#ifdef DEBUG_EVAL
  fprintf(stdout,"\nFull Eval\n---------\n");
#endif

   /* Generate arrays storing how many times each side attacks each square on the board.
    * This takes quite some time, but it is worth the effort! */
  GenerateAttacks(B);

   /* Now loop through all the pieces on the board and sum their contributions.
    * Also include the contributions of the empty spaces, measuring board
    * domination and territorial control.
    * There is the specialised version for the endgame below. */
  if (B->Gamestage < Endgame) {

     /* Work out how much square possession is worth */
    SpWon = SpaceWon[B->Gamestage];
    SpDef = SpaceDefended[B->Gamestage];
     /* Loop through the board */
    for (sq=0;sq<64;sq++) {
      p = B->pieces[sq];
      
#ifdef DEBUG_EVAL
      fprintf(stdout,"Square %c%d  [",File(sq)+97,8-Rank(sq));
      PrintPiece(p);
      fprintf(stdout,"] : ");
#endif
      switch(p) {
        /* White Piece */
      case (wpawn)  : score += TactPawn(sq,B,WHITE);
                      npw += SquareColour[sq]; break;
      case (wrook)  : score += TactRook(sq,B,WHITE); break;
      case (wknight): score += TactKnight(sq,B,WHITE); break;
      case (wbishop): score += TactBishop(sq,B,WHITE); break;
      case (wqueen) : score += TactQueen(sq,B,WHITE); break;
      case (wking)  : score += TactKing(sq,B,WHITE); break;
        /* Black Piece */
      case (bpawn)  : score -= TactPawn(sq,B,BLACK);
                      npw += SquareColour[sq]; break;
      case (brook)  : score -= TactRook(sq,B,BLACK); break;
      case (bknight): score -= TactKnight(sq,B,BLACK); break;
      case (bbishop): score -= TactBishop(sq,B,BLACK); break;
      case (bqueen) : score -= TactQueen(sq,B,BLACK); break;
      case (bking)  : score -= TactKing(sq,B,BLACK); break;
        /* Empty square - reward for possession by one side */
      case (empty)  : sq2=ConvertSq[sq];
#ifdef DEBUG_EVAL
        oldscore = score;
#endif
	    /* If only one side is attacking a square, then it is won
	     * by that side.  Otherwise it can only be defended. */
        one_sided = (!(B->WAttacks[sq2]) || !(B->BAttacks[sq2]));
        def = B->WAttacks[sq2] - B->BAttacks[sq2];
        if (one_sided) {
          if (def>0) score += SpWon[sq];
          else if (def<0) score -= SpWon[Flip[sq]];
        }
        else {
		      /* We have no clear winner, so evaluate the ownership of the square (slow!!) */
          def = EvaluateOwnership(B,sq);
          if (def > 0) score += SpDef[sq];
          else if (def < 0) score -= SpDef[Flip[sq]];
#ifdef DEBUG_EVAL
		  contestcount++;
#endif
        }
        
#ifdef DEBUG_EVAL
        control += score-oldscore;
        fprintf(stdout,"%d", score-oldscore);
#endif
        break;
      }
#ifdef DEBUG_EVAL
      fprintf(stdout,"\n");
#endif
    }
  }
    /* If we're in the endgame then use this simpler version */
  else {
     /* Loop through the pieces */
    while (pieces) {     
      sq = FirstPiece(pieces);
      p = B->pieces[sq];
#ifdef DEBUG_EVAL
      fprintf(stdout,"Square %c%d  [",File(sq)+97,8-Rank(sq));
      PrintPiece(p);
      fprintf(stdout,"] : ");
#endif

      switch(p) {
        /* White Piece */
      case (wpawn)  : score += TactPawn(sq,B,WHITE); break;
      case (wrook)  : score += TactRook(sq,B,WHITE); break;
      case (wknight): score += TactKnight(sq,B,WHITE); break;
      case (wbishop): score += TactBishop(sq,B,WHITE); break;
      case (wqueen) : score += TactQueen(sq,B,WHITE); break;
      case (wking)  : score += TactKing(sq,B,WHITE); break;
        /* Black Piece */
      case (bpawn)  : score -= TactPawn(sq,B,BLACK); break;
      case (brook)  : score -= TactRook(sq,B,BLACK); break;
      case (bknight): score -= TactKnight(sq,B,BLACK); break;
      case (bbishop): score -= TactBishop(sq,B,BLACK); break;
      case (bqueen) : score -= TactQueen(sq,B,BLACK); break;
      case (bking)  : score -= TactKing(sq,B,BLACK); break;
      }
      RemoveFirst(pieces);
#ifdef DEBUG_EVAL
    fprintf(stdout,"\n");
#endif
    }
  }
#ifdef DEBUG_EVAL
  fprintf(stdout,"After Piece Tactics : %d\n",score);
  fprintf(stdout,"Control Balance = %d\n",control);
  fprintf(stdout,"Contested Empty Squares : %d\n\n",contestcount);
#endif 
  
  /* Add on general positional score */
  if (B->Gamestage <= Middle) score += TacticsPositional(B);
  
  /* -- General score modifiers -- */
  
  /* Modifiers for pawns blocking bishops.  Your pawns should be on different squares to your
   * own bishops, but the same as your opponent's */

  /* White Bishops */
  if (B->WhiteBishops) {
    /* Only black square bishops */
    if (!(B->WhiteBishops & WhiteMask)) score += npw*PAWN_BLOCK;
    /* Only white square bishops */
    else if (!(B->WhiteBishops & BlackMask)) score -= npw*PAWN_BLOCK;
    /* Bonus for having two bishops (or more) on opposite colours */
    else score += TWO_BISHOPS;
#ifdef DEBUG_EVAL
    if (npw!=0) {
      if (!(B->WhiteBishops & WhiteMask)) fprintf(stdout,"White has only black square bishops : Pawn Block = %d\n",-npw*PAWN_BLOCK);
      else if (!(B->WhiteBishops & BlackMask)) fprintf(stdout,"White has only white square bishops : Pawn Block = %d\n",npw*PAWN_BLOCK);
    }
    if ((B->WhiteBishops & WhiteMask) && (B->WhiteBishops & BlackMask)) fprintf(stdout,"White has a bishop pair [+%d]\n",TWO_BISHOPS);
#endif
  }

  /* Black Bishops */
  if (B->BlackBishops) {
    /* Only black square bishops */
    if (!(B->BlackBishops & WhiteMask)) score -= npw*PAWN_BLOCK;
    /* Only white square bishops */
    else if (!(B->BlackBishops & BlackMask)) score += npw*PAWN_BLOCK;
    /* Penalty for opponent having two bishops (or more) on opposite colours */
    else score -= TWO_BISHOPS;
#ifdef DEBUG_EVAL
    if (npw!=0) {
      if (!(B->BlackBishops & WhiteMask)) fprintf(stdout,"Black has only black square bishops : Pawn Block = %d\n",npw*PAWN_BLOCK);
      else if (!(B->BlackBishops & BlackMask)) fprintf(stdout,"Black has only white square bishops : Pawn Block = %d\n",-npw*PAWN_BLOCK);
    }
    if ((B->BlackBishops & WhiteMask) && (B->BlackBishops & BlackMask)) fprintf(stdout,"Black has a bishop pair [-%d]\n",TWO_BISHOPS);
#endif
  }
  
  /* Penalty for having no pawns */
  if (!B->WhitePawns) score -= NO_PAWNS;
  if (!B->BlackPawns) score += NO_PAWNS;

  /* If there is no mating material for one side then the score cannot favour that side
   * (Note - we calculated this in the LazyEval and retained the results) */
  if (!wmat) score = min(0,score);
  if (!bmat) score = max(0,score); 
#ifdef DEBUG_EVAL
  if (!wmat) fprintf(stdout,"No mating material for white\n");
  if (!bmat) fprintf(stdout,"No mating material for black\n");
#endif 
#ifdef DRAWISH_ENDINGS
  /* Test for a 'drawish' ending, and reduce the score if so */
  if (Drawish(B)) score = (score * (50+tpts)) / 100;
#ifdef DEBUG_EVAL
  if (Drawish(B)) fprintf(stdout,"Drawish Position (score reduced)\n");
#endif
#endif  

#ifdef DEBUG_EVAL
  fprintf(stdout,"Final Score : %d   [Delta %d]\n",score,score-lazyscore);
#endif

   // Return score, possibly altered by the skill level
  if (Skill == 10) return score;
  return score + Random(((10-Skill) * 4) + 1) + 2 * Skill - 20;
}