Sophie

Sophie

distrib > Mandriva > 10.0-com > i586 > by-pkgid > 9347541fe87a5ea3f3b8dbc50f660e8e > files > 50

libQGLViewer-devel-1.3.6-1mdk.i586.rpm

// =================================================================== //
// Time-stamp: <27 Jun 03 17:07:18 Jean-Guillaume.Dumas@imag.fr> 
// =================================================================== //
#ifndef __Agora_AlphaBeta__
#define __Agora_AlphaBeta__

#include <iostream>
#include <vector>
#include <algorithm>
#include <deque>
#include "givtimer.h"
#include "agora.h"

#define START_PROFONDEUR 5

#define WINNER 400
#define LOOSER -500
#define INFTYOT 300
#define MINFTYOT -INFTYOT
#define INFTY 800
#define MINFTY -INFTY
#define DINFTY 1600
#define MDINFTY -DINFTY
      
 
template<class Ints>
inline double Agora<Ints>::ami_ab(int depth, double alpha, double beta, bool ordi_color) {
          // always : A < B
        if ( depth <= 0 ) return (ordi_color?-eval():eval());
        int d  = depth -1 ;
        CoupsPossibles( _PM[d], ordi_color);
    
        if ( _PM[d].size() <= 0 )  return (LOOSER-depth+(ordi_color?-eval():eval()));

        Pile_t dep, arr;
        for(typename Possible_t::const_iterator pi = _PM[d].begin(); 
            pi != _PM[d].end() ; 
            ++pi) {
            jouer( (*pi).depart(), dep, (*pi).arrivee(), arr, (*pi).dessus());
            double ab = ennemi_ab(d, alpha, beta, ordi_color);
            remettre( (*pi).depart(), dep, (*pi).arrivee(), arr );
            if (ab > alpha) alpha = ab;
            if (alpha >= beta) 
                return beta;   
        }
        return alpha;
    }

template<class Ints>
inline double Agora<Ints>::ennemi_ab(int depth, double alpha, double beta, bool ordi_color) {
            // always : A < B
        if ( depth <= 0 ) return (ordi_color?-eval():eval());
        int d  = depth -1 ;
        bool cenemy = !ordi_color;
        CoupsPossibles( _PM[d], cenemy);
        if ( _PM[d].size() <= 0 )  return (WINNER+depth+(ordi_color?-eval():eval()));
        
        Pile_t dep, arr, ndep, narr;
        for(typename Possible_t::const_iterator pi = _PM[d].begin(); 
            pi != _PM[d].end() ; 
            ++pi) {
            jouer( (*pi).depart(), dep, ndep, (*pi).arrivee(), arr, narr, (*pi).dessus());
            double ab = ami_ab(d, alpha, beta, ordi_color, eval(), dep, ndep, arr, narr);
            remettre( (*pi).depart(), dep, (*pi).arrivee(), arr );
            if (ab < beta) beta = ab;
            if (alpha >= beta) 
                return alpha ;   
        }
        return beta;
    }



template<class Ints>
inline double Agora<Ints>::ami_ab(int depth, double alpha, double beta, bool ordi_color, double currev, const Pile_t ad, const Pile_t nd, const Pile_t aa, const Pile_t na) {
    eval( currev, ad, nd, aa, na );

          // always : A < B
        if ( depth <= 0 ) return (ordi_color?-currev:currev);
        int d  = depth -1 ;
        CoupsPossibles( _PM[d], ordi_color);
    
        if ( _PM[d].size() <= 0 )  return (LOOSER-depth+(ordi_color?-currev:currev));

        Pile_t dep, arr, ndep, narr;
        for(typename Possible_t::const_iterator pi = _PM[d].begin(); 
            pi != _PM[d].end() ; 
            ++pi) {
            jouer( (*pi).depart(), dep, ndep, (*pi).arrivee(), arr, narr, (*pi).dessus());
            double ab = ennemi_ab(d, alpha, beta, ordi_color, currev, dep, ndep, arr, narr);
            remettre( (*pi).depart(), dep, (*pi).arrivee(), arr );
            if (ab > alpha) alpha = ab;
            if (alpha >= beta) 
                return beta;   
        }
        return alpha;
    }

template<class Ints>
inline double Agora<Ints>::ennemi_ab(int depth, double alpha, double beta, bool ordi_color, double currev, const Pile_t ad, const Pile_t nd, const Pile_t aa, const Pile_t na) {
            // always : A < B
    eval( currev, ad, nd, aa, na );

        if ( depth <= 0 ) return (ordi_color?-currev:currev );
        int d  = depth -1 ;
        bool cenemy = !ordi_color;
        CoupsPossibles( _PM[d], cenemy);
        if ( _PM[d].size() <= 0 )  return (WINNER+depth+(ordi_color?-currev:currev));
        
        Pile_t dep, arr, ndep, narr;
        for(typename Possible_t::const_iterator pi = _PM[d].begin(); 
            pi != _PM[d].end() ; 
            ++pi) {
            jouer( (*pi).depart(), dep, ndep, (*pi).arrivee(), arr, narr, (*pi).dessus());
            double ab = ami_ab(d, alpha, beta, ordi_color, currev, dep, ndep, arr, narr);
            remettre( (*pi).depart(), dep, (*pi).arrivee(), arr );
            if (ab < beta) beta = ab;
            if (alpha >= beta) 
                return alpha ;   
        }
        return beta;
    }


template<class Ints>
inline double Agora<Ints>::MTDFdouble(int depth, double f, bool ordi_color) {
        double g = (f>LOOSER)?f:0;
        double lowerbound = MINFTY;
        double upperbound = INFTY;
        double beta; int count = 0;
        for(double diffbound = DINFTY;
            diffbound > 1 ;
            ++count, diffbound = upperbound-lowerbound)  {
            if (count > 3) {
                g = ennemi_ab(depth, lowerbound, upperbound, ordi_color);
                break;
            }
            if (g == lowerbound)
                beta = g+1;
            else if (g == upperbound)
                beta = g-1;
            else
                beta = g;
            g = ennemi_ab(depth, beta - 1, beta + 1, ordi_color);
            if (g < beta)
                upperbound = g;
            else if (g > beta)
                lowerbound = g;
            else
                break;
        }
        return g;
    }









template<class Ints>
inline double Agora<Ints>::BestPlay(Coup& bp, bool ordi_color, int depth) {
#ifdef __ERRORS__
        _count = 0;
#endif
#ifdef __DEPTHS__
        std::cerr << "d" << depth << " ";
#endif
        Size_t ls = TopPM.size();
        
        typename Possible_t::iterator beg_pi = TopPM.begin(), end_pi = TopPM.end();
        double e = MINFTY;
        bp = *beg_pi;

        if (ls > 1) {
            std::vector<double> e_choix; e_choix.resize( ls );
            std::vector<double>::iterator eci = e_choix.begin();
#ifdef DEGRESSIVE_DEPTH
            int _mmod = -1;
            int _mdiv = (depth<7)?(depth+10):7;
            int _mmid = depth /2;
#endif
            Pile_t dep, arr;
            for(typename Possible_t::iterator pi = beg_pi ; pi != end_pi; ++pi, ++eci) {
#ifdef DEGRESSIVE_DEPTH
                int d = (++_mmod / _mdiv)*2;
                d = (d<_mmid)?depth - 1 - d: _mmid;
#else
                int d = depth - 1;
#endif
#ifdef __DEPTHS__
                std::cerr << "[d: " << d << "] ";
#endif
                bool arr_coul = jouer( (*pi).depart(), dep, (*pi).arrivee(), arr, (*pi).dessus());
                double em = MTDFdouble(d, e, ordi_color);
                remettre( (*pi).depart(), dep, (*pi).arrivee(), arr);
#ifdef __DEPTHS__
#ifdef __ERRORS__
                std::cerr << *pi << ":" << em << " (" << _count << ")  " << std::endl;
#else
                std::cerr << *pi << ":" << em << "  ";
#endif
#endif

                if ( (em > e) 
                    // A jeu égal, on préfère un prisonnier
		    // || ((em == e) && (couleur(dep) != arr_coul)) 
                     )     
                {
                    e = em;
                    bp = *pi;
                }
                Coup temp(*pi);
                typename Possible_t::iterator sorti = pi, lpi = pi;
                std::vector<double>::iterator preci = eci, lci = eci;
                for(--preci, --sorti ; (lpi != beg_pi) && (em > *preci); --preci, --sorti, --lci, --lpi ) {
                    *lci = *preci;
                    *lpi = *sorti;
                }
                *lci = em;
                *lpi = temp;
           }
#ifdef __DEPTHS__
            std::cerr << std::endl;
#endif
        }
#ifdef __ERRORS__
        std::cerr << "Evals: " << _count << std::endl;
#endif

        return e;
    }



    
template<class Ints>
inline double Agora<Ints>::OnebyOneBP(Coup& bp, bool ordi_color, int depth, double temps_max, Timer& global) {
        Timer tim; tim.clear(); tim.start();

        int d = depth-1;
        Size_t ls = TopPM.size();
        
        typename Possible_t::iterator beg_pi = TopPM.begin(), end_pi = TopPM.end();
        double e = MINFTY;
        bp = *beg_pi;
        if (ls > 1) {
#ifdef __DEPTHS__
            std::cerr << "d" << depth << " ";
#endif

            typename Possible_t::iterator pi = beg_pi ;
            Pile_t dep, arr;
        
            bool arr_coul = jouer( (*pi).depart(), dep, (*pi).arrivee(), arr, (*pi).dessus());
            double em = MTDFdouble(d, e, ordi_color);
            remettre( (*pi).depart(), dep, (*pi).arrivee(), arr);
#ifdef __DEPTHS__
            std::cerr << *pi << ":" << em << "  ";
#endif
            if ( (em > e)
                 // A jeu égal, on préfère un prisonnier
	         // || ((em == e) && (couleur(dep) != arr_coul)) 
                 )     
            {
                e = em;
                bp = *pi;
            }
            tim.stop();
            global += tim;
            double devia = tim.realtime();

            for(++pi ; ((global.realtime()+devia) < temps_max) && (pi != end_pi) ; ++pi, global += tim, devia = (devia+tim.realtime())/2 ) {
                tim.start();
                bool arr_coul = jouer( (*pi).depart(), dep, (*pi).arrivee(), arr, (*pi).dessus());
                em = MTDFdouble(d, e, ordi_color);
                remettre( (*pi).depart(), dep, (*pi).arrivee(), arr);
#ifdef __DEPTHS__
                std::cerr << *pi << ":" << em << "  ";
#endif
                if ( (em > e)
                     // A jeu égal, on préfère un prisonnier
		     // || ((em == e) && (couleur(dep) != arr_coul)) 
                     )     
                {
                    e = em;
                    bp = *pi;
                }
                tim.stop();
            }
#ifdef __DEPTHS__
            std::cerr << std::endl;
#endif
        }
        return e;
    }


template<class Ints>
inline typename Agora<Ints>::Coup& Agora<Ints>::Suggest(Coup& bp, bool ordi_color, double temps_max, int depth) {
    if (depth > 0) {
        Timer tim; tim.clear();tim.start();
        CoupsPossibles( TopPM, ordi_color );
        std::random_shuffle(TopPM.begin(), TopPM.end() );
        BestPlay(bp, ordi_color, 1);
        _PM.resize(depth);
        BestPlay(bp, ordi_color, depth);
        tim.stop();
        if (tim.realtime() < temps_max)
            Iteratif(bp, ordi_color, temps_max-tim.realtime(), depth+1);
        return bp;
    } else {
        return Iteratif(bp, ordi_color, temps_max);
    }
}



template<class Ints>
inline typename Agora<Ints>::Coup& Agora<Ints>::Iteratif(Coup& bp, bool ordi_color, double temps_max, int StartProf = START_PROFONDEUR) {
        Timer tim, global; tim.clear(); global.clear(); global.start();
        double SEUIL =  22.0 / 4.0;
        SEUIL = (SEUIL < 3)? 3 : SEUIL ;
        CoupsPossibles( TopPM, ordi_color );
        double ev = BestPlay(bp, ordi_color, 1);
        global.stop();
        
        
        int profondeur = StartProf ;
        for(;   ( global.realtime()*SEUIL < temps_max ) 
                && (ev > MINFTYOT) 
                && (ev < INFTYOT)
                ;  ++profondeur, global += tim ) {
                
            tim.start();
            _PM.resize(profondeur);
            ev = BestPlay(bp, ordi_color, profondeur);
            tim.stop();
        }

        if ( ((global.realtime()*5) < (temps_max*4)) && (ev > MINFTYOT) && (ev < INFTYOT) ) {
            _PM.resize(profondeur);
            ev = OnebyOneBP(bp, ordi_color, profondeur, temps_max, global);
        }
#ifdef __DEPTHS__
        std::cerr << "time: " << global << std::endl;
#endif
        return  bp;
    }
    

#endif