double MiniMax(const Environment & tablero,int jug,int prof,int limite,Environment::ActionType & accion){ const double INF=1000000000000.0, mINF=-1000000000000000.0, gano=999999999999999, pierdo=-999999999999999999; Environment::ActionType accion_anterior; double mejor, aux; if(prof==limite or tablero.JuegoTerminado()){ return ValoracionTest(tablero,jug); } else{ if(prof%2==0) mejor=mINF; else mejor=INF; int ult_act=-1; Environment hijo=tablero.GenerateNextMove(ult_act); while(!(hijo==tablero)){ aux=MiniMax(hijo,jug,prof+1,limite,accion_anterior); if(prof%2==0){ if(aux>mejor){ mejor=aux; accion=static_cast <Environment::ActionType>(ult_act); } } else{ if(aux<mejor){ mejor=aux; accion=static_cast<Environment::ActionType>(ult_act); } } hijo=tablero.GenerateNextMove(ult_act); } return mejor; } }
double Player::Poda_AlfaBeta(const Environment &tablero, int jugador, int prof, const int MAX_PROF, Environment::ActionType &accion, double alfa, double beta){ if(prof==MAX_PROF || tablero.JuegoTerminado()) return Valoracion(tablero, jugador); else{ int last_accion=-1; double temporal; Environment::ActionType accion_previa; Environment hijo=tablero.GenerateNextMove(last_accion); //NODO ALFA if((prof%2)==0){ while(!(hijo==tablero)){ temporal=Poda_AlfaBeta(hijo, jugador, prof+1,MAX_PROF, accion_previa, alfa, beta); // Si existe una jugada mejor, actualizamos el alfa. if(temporal > alfa){ alfa=temporal; accion=static_cast<Environment::ActionType>(last_accion); } if(beta<=alfa){ break; } hijo=tablero.GenerateNextMove(last_accion); } return alfa; } //NODO BETA else{ while(!(hijo==tablero)){ temporal=Poda_AlfaBeta(hijo, jugador, prof+1,MAX_PROF, accion_previa, alfa, beta); // Si existe una jugada peor, actualizamos el beta. if(temporal < beta){ beta=temporal; accion=static_cast<Environment::ActionType>(last_accion); } if(beta<=alfa){ break; } hijo=tablero.GenerateNextMove(last_accion); } return beta; } } }
double Poda_alphaBetha(const Environment & tablero,int jug,int prof,int limite,Environment::ActionType & accion,double alpha,double betha){ Environment::ActionType accion_anterior=accion; double aux; if(prof==limite or tablero.JuegoTerminado()){ return Valoracion(tablero,jug); } else{ int ult_act=-1; Environment hijo=tablero.GenerateNextMove(ult_act); while(!(hijo==tablero)){ aux=Poda_alphaBetha(hijo,jug,prof+1,limite,accion_anterior,alpha,betha); if(prof%2==0){ if(aux>alpha){ alpha=aux; if(prof==0) accion=static_cast <Environment::ActionType>(ult_act); } } else{ if(aux<betha){ betha=aux; //if(prof==0) // accion=static_cast<Environment::ActionType>(ult_act); } } if(betha<=alpha) return alpha; hijo=tablero.GenerateNextMove(ult_act); } if (prof%2==0) return alpha; else return betha; } }
int valorMax(const Environment & actual, int jug, int profundidad, int limite_profundidad, int marcador) { int valor_max; Environment sigact[4]; if (profundidad == limite_profundidad || !actual.a_movement_is_possible(jug)) return Heuristica(actual, jug, marcador); else { int n_act = actual.GenerateNextMove(sigact, jug); valor_max = -INFINITO; for (int i = 0; i < n_act; i++) { valor_max = mayor(valor_max, valorMin(sigact[i], jug, profundidad+1, limite_profundidad, marcador)); } return valor_max; } }
/** Esta funcion devuelve la siguiente mejor accion guiada por la heuristica usando el algoritmo minimax. Devuelve: La siguiente accion a realizar. Parametros: "actual" contiene el estado del tablero. "jug" indica que jugador esta pidiendo el valor heuristico. "limite_profundidad" establece el limite de exploracion del grafo. OBSERVACION: esta parametrizacion es solo indicativa, y el alumno podra modificarla segun sus necesidades */ Environment::ActionType MiniMax(const Environment & actual, int jug, int limite_profundidad){ Environment::ActionType accion; int mayor = -INFINITO, mayor_actual, profundidad = 0; Environment sigact[4]; int n_act = actual.GenerateNextMove(sigact, jug); for (int i = 0; i < n_act; i++) { mayor_actual = valorMin(sigact[i], jug, profundidad+1, limite_profundidad, actual.Marcador(jug)); if (mayor_actual > mayor) { mayor = mayor_actual; accion = static_cast<Environment::ActionType> (sigact[i].Last_Action(jug)); } } cout << "Jugador: " << jug; cout << " mayor " << mayor; cout << endl; return accion; }
int valorMin(const Environment & actual, int jug, int profundidad, int limite_profundidad, int marcador) { int valor_min; int jug_adversario; if (jug == 1) jug_adversario = 2; else if (jug == 2) jug_adversario = 1; Environment sigact[4]; if (profundidad == limite_profundidad || !actual.a_movement_is_possible(jug_adversario)) return Heuristica(actual, jug, marcador); else { int n_act = actual.GenerateNextMove(sigact, jug_adversario); valor_min = INFINITO; for (int i = 0; i < n_act; i++) { valor_min = minimo(valor_min, valorMax(sigact[i], jug, profundidad+1, limite_profundidad, marcador)); } return valor_min; } }
double PodaAlfaBeta(const Environment & tablero, int jugador, int profundidad, int profLimite, Environment::ActionType & accion, double alfa, double beta){ Environment::ActionType ult_accion; //Profundidad máxima o fin del juego, se acabó if(profundidad == profLimite || tablero.JuegoTerminado()) return Valoracion(tablero, jugador); else{ // Hijos int ult_act = -1; //Generar siguiente nodo tablero hijo Environment hijo = tablero.GenerateNextMove(ult_act); //Profundidad par --> nodo MAX if(profundidad%2 == 0){ //Recorrido de nodos hijos while(!(hijo==tablero)){ double aux = PodaAlfaBeta(hijo, jugador, profundidad+1,profLimite,ult_accion,alfa,beta); // if (profundidad == 0) //cout << "Acción -> " << ult_act << endl; if(aux > alfa){ alfa = aux; if (profundidad == 0) accion = static_cast<Environment::ActionType> (ult_act); } if(beta <= alfa){ return alfa; //poda } else { //Generación del siguiente nodo tablero hijo hijo = tablero.GenerateNextMove(ult_act); } } return alfa; // no poda }else{ //Nivel impar -> nodo MIN while(!(hijo==tablero)){ double aux = PodaAlfaBeta(hijo, jugador, profundidad+1, profLimite, ult_accion, alfa, beta); if(aux < beta) beta = aux; if(beta <= alfa){ return beta; //poda } else{ hijo = tablero.GenerateNextMove(ult_act); } } return beta; // no poda } } }