Exemple #1
0
vector<Card*> TestControllerv2::ProposeAttacks(Player* attackPlayer, Player* blockPlayer, double &value, int recur, bool needVal) {
//	TODO: Consider the number of states that must be calculated and if too large consider no attacks, all attacks and then
//		remove creatures that die, and repeat.
	vector<Card*> attacking;
	vector<Card*> potAttacks;
	potAttacks = GetPotentialAttackers(attackPlayer);
//	for(int i=0; i<potAttacks.size(); i++) {
//		if(potAttacks[i]->CanAttack()) {
//			attacking.push_back(potAttacks[i]);
//		}
//	}
	if(potAttacks.size() == 0 && !needVal) {
		return attacking;
	}
	vector<bool> isAttacking;
	for(int i=0; i< potAttacks.size(); i++) {
		isAttacking.push_back(false);
	}
	vector<bool> bestAttacks;
	double* attackBoard = new double[CardList::size];
	double* blockBoard = new double[CardList::size];
	GetBoardVec(attackPlayer,attackBoard);
	GetBoardVec(blockPlayer,blockBoard);
	double bestVal = -0.1;
	GenerateAttacks(isAttacking,0,potAttacks.size(),bestVal, &bestAttacks, attackBoard, blockBoard, potAttacks, attackPlayer, blockPlayer, recur);
//    cout << "bestVal is " << bestVal << endl;

	for(int i=0; i<bestAttacks.size(); i++) {
		if(bestAttacks[i]) {
			attacking.push_back(potAttacks[i]);
		}
	}
    value = bestVal;
	delete attackBoard;
	delete blockBoard;
	return attacking;
}
Exemple #2
0
double TestControllerv2::GenerateAttacks(vector<bool> isAttacking, int beg, int end, double& bestVal, vector<bool>* bestAttacks, double* attackState, double* blockState, vector<Card*> potAttacks, Player* attackPlayer, Player* blockPlayer, int recur) {
	if(beg!=end) {
		for(int i=0; i<2; i++) {
			if(i==1) {
				isAttacking[beg] = true;
			}
			double val = 0;
			val = GenerateAttacks(isAttacking,beg+1,end,bestVal,bestAttacks,attackState,blockState,potAttacks,attackPlayer,blockPlayer,recur);
//			cout << "val = " << val << endl;
			if(val>=bestVal) {
//				cout << val << " > " << bestVal << endl;
				bestVal = val;
				*bestAttacks = isAttacking;
			}
			else if(val==bestVal) {
//			Break ties by having the most creatures attack
				int newAtt=0;
				int oldAtt=0;
				for(int k=0; k<isAttacking.size(); k++) {
					if(isAttacking[k]) {
						newAtt++;
					}
					if(bestAttacks[0][k]) {
						oldAtt++;
					}
				}
				if(newAtt>oldAtt) {
					bestVal = val;
					*bestAttacks = isAttacking;
				}
			}
		}
		return 0.;
	}
	else {
//        if(recur==1) {
//            cout << "isAttacking: ";
//            for(int i=0; i<isAttacking.size(); i++) {
//                cout << isAttacking[i] << " ";
//            }
//            cout << endl;
//        }
//        else {
//            cout << "propAttack: ";
//            for(int i=0; i<isAttacking.size(); i++) {
//                cout << isAttacking[i] << " ";
//            }
//            cout << endl;
//        }
		double value;
		vector<Card*> attackers;
		for(int i=0; i<isAttacking.size(); i++) {
			if(isAttacking[i]) {
				attackers.push_back(potAttacks[i]);
			}
		}
		ProposeBlocks(attackers,blockPlayer,attackPlayer,value,recur,true);
		value = 1-value;
        if(bestVal==-0.1) {                                                                                                                                                
//          cout << val << " > " << bestVal << endl;
            bestVal = value;
            *bestAttacks = isAttacking;
        }


//        if(recur==1) {
//		    cout << "Attack Value = " << value << endl;
//        }
//        else {
//		    cout << "Prop attack Value = " << value << endl;
//        }

//		if(attackers.size()>0) {
//			ProposeBlocks(attackers,blockPlayer,attackPlayer,value,recur,true);
//			if(value!=-1) {
////			Convert from blocker's value to attackers value
//				value = 1-value;
//			}
//			else {
////			If no possible blockers
//				double* blockBoardTemp = new double[totalCards];
//				double* attackBoardTemp = new double[totalCards];
//				memcpy(blockBoardTemp,blockState,totalCards*sizeof(double));
//				memcpy(attackBoardTemp,attackState,totalCards*sizeof(double));
//				int damage=0;
//				for(int j=0; j<attackers.size(); j++) {
//					damage += attackers[j]->GetPower();
//				}
//				if(recur>0) {
//					PredictCrackback(blockPlayer,attackPlayer,blockBoardTemp,attackBoardTemp,attackers,damage,value);
//					value = 1-value;
//				}
//				else {
//					value = AssessGameState(attackBoardTemp,blockBoardTemp,attackPlayer->lifeTotal,blockPlayer->lifeTotal-damage);
//				}
//				delete blockBoardTemp;
//				delete attackBoardTemp;
//			}
//		}
//		else {
////			There were no attacks
//			double* blockBoardTemp = new double[totalCards];
//			double* attackBoardTemp = new double[totalCards];
//			memcpy(blockBoardTemp,blockState,totalCards*sizeof(double));
//			memcpy(attackBoardTemp,attackState,totalCards*sizeof(double));
//			if(recur>0) {
//				vector<Card*> emptyAttack;
//				PredictCrackback(blockPlayer,attackPlayer,blockBoardTemp,attackBoardTemp,emptyAttack,0,value);
//				value = 1-value;
//			}
//			else {
//				value = AssessGameState(attackBoardTemp,blockBoardTemp,attackPlayer->lifeTotal,blockPlayer->lifeTotal);
//			}
//			delete blockBoardTemp;
//			delete attackBoardTemp;
//		}
		return value;
	}
}
Exemple #3
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;
}