コード例 #1
0
/** Choose which Card to play, using different algorithms.
 *
 * This function chooses which card to play, using different
 * levels of complexity.
 * The main concepts are of the algorithms are:
 * - BASE:        play lowest card
 * - FINAL RUSH:  play highest card
 * - SAVE:        do not play
 *
 * Every option generated by an algorithms has a level, based on:
 * - value of the Card object
 * - count of the Card object
 * - level of the Card object
 * - Cards in the Deck
 * - algorithm relevance
 *
 * This method is declared as static so that it can be used
 * in every situation (e.g.: advice to user)
 *
 * @param state         state of current game
 * @param hand          player's Deck
 * @param brainLevel    player's cleverness
 *                      HUMAN: player is the user
 *                      ...
 *                      AI_MAX: player is AI with full capability
 * @return copy of the Card chosen, NULL if he decided not to play
 */
Card *Role::chooseCard(gameState_t *state,Deck *hand,int brainLevel)
{
    int algorithmLevel;
    Choice possibilities;
    Choice *cards;
    Card *chosen,*max1,*max2,*tmp;
    bool first=false;

    if(state->winning==NULL)
        first=true;

    if(state==NULL)
    {
        cerr <<"Error: argument \"state\" can't be NULL\n";
        return NULL;
    }

    if(!first && (state->winning->getValue()==2  ||  (state->winning->getValue()==1 && state->aces==0)) )
        return NULL;  //se non si può superare
    else{
        if(brainLevel==HUMAN)
        {
            cards=selectCard(state,hand,FOUR_CARDS);
            if(!cards) return NULL;
            chosen=cards->popCard();
            delete cards;
            while(chosen->isPlayable(state->winning)==false)
            {
                msg_rejectCard();
                msg_printState(state);
                cards=selectCard(state,hand,FOUR_CARDS);
                if(!cards) return NULL;
                chosen=cards->popCard();
                delete cards;
            }
            return chosen;
        }else{
            // in base al loro livello BRAIN, i giocatori hanno più o meno opzioni
            // fra le quali scegliere. Ogni opzione è data da un algoritmo, che
            // può essere più o meno vantaggioso in base alla situazione delle carte.

            //____________________________ALGORITMO:"Base"____________________________
            //gioco le carte di valore più basso possibile
            chosen=hand->getFirstPlayable(state->winning);

            if(chosen != NULL)
            {
                //...............calcolo del livello dell'opzione.............
                algorithmLevel = 10;   //livello di base dell'algoritmo

                switch(chosen->getCount() - (first? 1 : state->winning->getCount()))   //se aumento il numero (es. da coppia a tris)
                {
                    case 0: algorithmLevel += 5;    break;   //buona
                    case 1: algorithmLevel -= 2;    break;
                    case 2: algorithmLevel -= 5;    break;
                    case 3: algorithmLevel -= 10;   break;   //molto svantaggiosa
                }

                if(chosen == hand->getLast())   //se la carta è alta
                {
                    if(state->n < 4)  algorithmLevel -= 5;   //se sono alle prime giocate è svantaggioso
                    if(state->n < 2)  algorithmLevel -= 5;   //giocare subito una carta alta!
                }
                //............................................................

                possibilities.addOption(new Card(chosen),algorithmLevel);   //mi salvo l'opzione nella lista
            }else
                return NULL;   //non può giocare nulla, deve per forza passare
            //_________________________________________________________________________

            //____________________________ALGORITMO:"Base++"____________________________
            //gioco le carte di livello più basso possibile

            if(brainLevel > 1)
            {
                chosen=hand->getLowerPlayable(state->winning,state);   //parto dalla carta più bassa giocabile, trovata prima

                //...............calcolo del livello dell'opzione.............
                algorithmLevel = 16;   //livello di base dell'algoritmo

                switch(chosen->getCount() - (first? 1 : state->winning->getCount()))   //se aumento il numero (es. da coppia a tris)
                {
                    case 0: algorithmLevel += 5;  break;   //buona
                    case 1: algorithmLevel -= 2;  break;
                    case 2: algorithmLevel -= 5;  break;
                    case 3: algorithmLevel -= 10;  break;   //molto svantaggiosa
                }

                if(chosen == hand->getLast())   //se la carta è alta
                {
                    if(state->n < 4)  algorithmLevel -= 5;   //se sono alle prime giocate è svantaggioso
                    if(state->n < 2)  algorithmLevel -= 5;   //      giocare subito una carta alta!
                }
                //............................................................

                possibilities.addOption(new Card(chosen),algorithmLevel);   //mi salvo l'opzione nella lista
            }
            //_________________________________________________________________________

            //____________________________ALGORITMO:"Final Rush"____________________________
            //se ho una carta bassa, e una che prende sicuramente, gioco prima la seconda

            if(brainLevel > 1)
            {
                if(hand->getTotGroups()==2  &&  hand->getFirst()==hand->getFirstPlayable(state->winning))   //se ci sono carte di 2 valori
                {
                    chosen=hand->getLast();   //passo alla più alta

                    if(chosen->getValue()==2)   //se è un 2
                    {
                        if(!chosen->isPlayable(state->winning))
                            chosen=NULL;
                    }else{
                        //se è un asso            e    i 2 sono finiti
                        if(chosen->getValue()==1  &&  state->twos==0)
                            if(!chosen->isPlayable(state->winning))
                                chosen=NULL;
                    }

                    if(chosen!=NULL)   //se le condizioni sono soddisfatte
                    {
                        //...............calcolo del livello dell'opzione.............
                        algorithmLevel = 40;   //livello di base dell'algoritmo
                        //............................................................
                        possibilities.addOption(new Card(chosen),algorithmLevel);   //mi salvo l'opzione nella lista
                    }
                }
            }
            //_________________________________________________________________________

            //____________________________ALGORITMO:"Final Rush++"____________________________
            //se ho solo una carta di livello basso, gioco prima le alte

            if(brainLevel > 2)
            {
                if(hand->countCheapCards()<2)   //se c'è al massimo una carta bassa
                {
                    chosen=hand->getFirstPlayable(state->winning);
                    while(chosen)
                    {
                        if(chosen->getLevel() >= TWO_LEV)   //se la carta è alta
                        {
                            if(chosen->isPlayable(state->winning))   //se posso giocarla
                            {
                                //...............calcolo del livello dell'opzione.............
                                algorithmLevel = 30;   //livello di base dell'algoritmo
                                //............................................................
                                possibilities.addOption(new Card(chosen),algorithmLevel);   //mi salvo l'opzione nella lista
                                chosen=NULL;
                            }
                        }
                        if(chosen)
                            chosen=hand->getNext();
                    }
                }
            }
            //_________________________________________________________________________


            //____________________________ALGORITMO:"Save Last"____________________________
            //se posso giocare solo la mia carta più alta e ho ancora tante carte, passo

            if(brainLevel > 2)
            {
                if(hand->getFirstPlayable(state->winning) == hand->getLast())   //se posso giocare solo la mia carta più alta
                {
                    if(hand->countCheapCards()>3)   //se ho ancora tante carte
                    {
                        //...............calcolo del livello dell'opzione.............
                        algorithmLevel = 20 + hand->getTotGroups();   //più carte mi restano, più conviene passare
                        //............................................................
                        possibilities.addOption(NULL,algorithmLevel);   //mi salvo l'opzione nella lista
                    }
                }
            }
            //_________________________________________________________________________



            //____________________________ALGORITMO:"Save More"____________________________

            if(brainLevel > 2)
            {

                //__________________________Save Pre____________________________
                //se posso giocare solo la seconda carta più alta, passo

                hand->getFirstPlayable(state->winning);
                if(hand->getNext() == hand->getLast())   //se dovrei giocare la penultima carta più alta
                {
                    if(hand->countCheapCards()>4)   //se ho ancora tante carte
                    {
                        //...............calcolo del livello dell'opzione.............
                        algorithmLevel = 15 + hand->getTotGroups();   //più carte mi restano, più conviene passare
                        //............................................................
                        possibilities.addOption(NULL,algorithmLevel);   //mi salvo l'opzione nella lista
                    }
                }


                max1=hand->getFirst();
                max2=hand->getFirst();

                for(tmp=hand->getNext(); tmp!=NULL; tmp=hand->getNext())
                {
                    if(tmp->getLevel() >= max1->getLevel())   //se il livello è più alto del massimo
                    {
                        max2=max1;   //faccio scalare il secondo massimo
                        max1=tmp;
                    }else{
                        if(tmp->getLevel() >= max2->getLevel())   //se il livello è più alto del secondo massimo
                            max2=tmp;
                    }
                }

                //__________________________Save Last++____________________________
                //se posso giocare solo la carta di livello più alto, passo
                if(hand->getFirstPlayable(state->winning)==max1)   //se dovrei giocare la carta di livello più alto
                {
                    if(hand->countCheapCards()>3)   //se ho ancora tante carte
                    {
                        //...............calcolo del livello dell'opzione.............
                        algorithmLevel = 18 + hand->getTotGroups();   //più carte mi restano, più conviene passare
                        //............................................................
                        possibilities.addOption(NULL,algorithmLevel);   //mi salvo l'opzione nella lista
                    }
                }else{

                    //__________________________Save Pre++____________________________
                    //se posso giocare solo la seconda carta di livello più alto, passo
                    if(hand->getFirstPlayable(state->winning)==max2)   //se dovrei giocare la seconda carta di livello più alto
                    {
                        if(hand->countCheapCards()>4)   //se ho ancora tante carte
                        {
                            //...............calcolo del livello dell'opzione.............
                            algorithmLevel = 15 + hand->getTotGroups();   //più carte mi restano, più conviene passare
                            //............................................................
                            possibilities.addOption(NULL,algorithmLevel);   //mi salvo l'opzione nella lista
                        }
                    }
                }

                //__________________________Save Last3____________________________
                //se giocherei la carta più alta o di livello più alto, passo
                if(possibilities.getBest()==max1  ||  possibilities.getBest()==hand->getLast())   //se dovrei giocare la carta di livello più alto
                {
                    if(hand->countCheapCards()>2)   //se ho ancora carte
                    {
                        //...............calcolo del livello dell'opzione.............
                        algorithmLevel = 20 + hand->getTotGroups();   //livello più basso di final rush
                        //............................................................
                        possibilities.addOption(NULL,algorithmLevel);   //mi salvo l'opzione nella lista
                    }
                }





            }


            /*
            cout <<"\nQuesto è il mazzo:\n";
            hand->print(true);
            cout <<"\nQueste sono le possibilità:\n";
            possibilities.print(true);
            //*/

            chosen=possibilities.getBest();

            /*
            if(chosen)
                cout <<"\nQuesta è la carta scelta: " <<chosen->getShortName() <<endl;
            else
                cout <<"\nPassa\n";
            //*/

            possibilities.reset();
            if(chosen)
            {
                if(state->winning  &&  chosen->getCount()>state->winning->getCount()
                    && ((chosen->getValue()==2) || (chosen->getValue()==1 && state->twos==0)))
                {
                    Card *tmp=new Card(chosen);
                    chosen=tmp->divide(state->winning->getCount());
                    delete tmp;
                }
                return new Card(chosen);
            }
            else
                return NULL;
        }
    }
}