Пример #1
0
string AIHints::constraintsNotFulfilled(AIAction * action, AIHint * hint, ManaCost * potentialMana)
{
    std::stringstream out;

    if (!action)
    {
        if (hint->mCombatAttackTip.size())
        {
            out << "to see if this can attack[" << hint->mCombatAttackTip << "]";
            return out.str();
        }
        if (hint->mSourceId && !findSource(hint->mSourceId))
        {
            out << "needcardinplay[" << hint->mSourceId << "]";
            return out.str();
        }
        out << "needability[" << hint->mAction << "]";
        return out.str();      
    }

    MTGAbility * a = action->ability;
    if (!a)
        return "not supported";

    MTGCardInstance * card = action->click;
    if (!card)
        return "not supported";

    //dummy test: would the ability work if we were sure to fulfill its mana requirements?
    if (!a->isReactingToClick(card, a->getCost()))
    {
        DebugTrace("This shouldn't happen, this AIAction doesn't seem like a good choice");
        return "not supported";
    }
    
    if (!a->isReactingToClick(card, potentialMana))
    {
        //Not enough Mana, try to find which mana we should get in priority
        ManaCost * diff = potentialMana->Diff(a->getCost());
        for (int i = 0; i < Constants::NB_Colors; i++)
        {
            if(diff->getCost(i) < 0)
            {
                out << "needmana[" <<  Constants::MTGColorChars[i] << "]";
                if (Constants::MTGColorChars[i] == 'r')
                    DebugTrace("Got it");
                SAFE_DELETE(diff);
                return out.str();
            }

        }

        //TODO, handle more cases where the cost cannot be paid
        return "not supported, can't afford cost for some reason";
    }

    //No problem found, we believe this is a good action to perform
    return "";

}
Пример #2
0
int AIMomirPlayer::getEfficiency(OrderedAIAction * action)
{
    MTGAbility * ability = action->ability;
    ManaCost * cost = ability->getCost();
    if (cost && !(cost->isExtraPaymentSet())) return 0; //Does not handle abilities with sacrifice yet
    int efficiency = AIPlayerBaka::getEfficiency(action);

    if (observer->getCurrentGamePhase() < MTG_PHASE_FIRSTMAIN) return 0;
    return efficiency;
}
Пример #3
0
//Finds a mtgAbility matching the Hint description, and returns a valid AIAction matching this mtgability
RankingContainer AIHints::findActions(AIHint * hint)
{
    RankingContainer ranking;

    vector<MTGAbility *> abilities = findAbilities(hint);

    for (size_t i = 0; i < abilities.size(); ++i)
    {
        MTGAbility * a = abilities[i];

        for (int j = 0; j < mPlayer->game->inPlay->nb_cards; j++)
        {
            MTGCardInstance * card = mPlayer->game->inPlay->cards[j];
            if (a->isReactingToClick(card, a->getCost()))
            {
                mPlayer->createAbilityTargets(a, card, ranking); //TODO make that function static?
                break; //For performance... ?
            }
        }
    }

    return ranking;
}
Пример #4
0
int AIMomirPlayer::momir()
{
    if (!game->hand->nb_cards) return 0; //nothing to discard :/
    int result = 0;
    int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES);
    int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES );
    ManaCost * potentialMana = getPotentialMana();
    int converted = potentialMana->getConvertedCost();
    SAFE_DELETE(potentialMana);
    int efficiency = 100;
    int chance = 1 + (randomGenerator.random() % 100);
    if (converted == 5 && myCreatures > opponentCreatures && game->hand->nb_cards < 4) efficiency = 5; //Strategy: skip 5 drop
    if (converted == 7 && myCreatures > opponentCreatures && game->hand->nb_cards < 2) efficiency = 50; //Strategy: 7 drops have bad upkeep costs and the AI doesn't handle those right now...
    if (converted > 8) converted = 8;
    if (converted == 8) efficiency = 100 - (myCreatures - opponentCreatures);

    if (efficiency >= chance)
    {

        std::vector<int16_t> _cost;
        _cost.push_back(Constants::MTG_COLOR_ARTIFACT);
        _cost.push_back(converted);
        ManaCost * cost = NEW ManaCost(_cost);
        MTGAbility * ability = getMomirAbility();
        MTGCardInstance * card = game->hand->cards[0];
        if (ability->isReactingToClick(card, cost))
        {
            payTheManaCost(cost);
            AIAction * a = NEW AIAction(this, ability, card);
            clickstream.push(a);
            result = 1;
        }
        delete cost;
    }
    return result;
}
Пример #5
0
int Counters::removeCounter(const char * _name, int _power, int _toughness)
{
    for (int i = 0; i < mCount; i++)
    {
        if (counters[i]->sameAs(_name, _power, _toughness))
        {
            if (counters[i]->nb < 1)
                return 0;

            counters[i]->removed();
            counters[i]->nb--;
            GameObserver *g = target->getObserver();
            WEvent * e = NEW WEventCounters(this,_name,_power,_toughness,false,true);
            dynamic_cast<WEventCounters*>(e)->targetCard = this->target;
            g->receiveEvent(e);

            // special case: when the last time counter is removed from non-suspended card
            // sacrifice that card
            if (!target->suspended && counters[i]->name == "time" && counters[i]->nb == 0) {
                MTGCardInstance * beforeCard = target;
                target->controller()->game->putInGraveyard(target);
                WEvent * e = NEW WEventCardSacrifice(beforeCard, target);
                g->receiveEvent(e);
            }

            //special case:if a card is suspended and no longer has a time counter when the last is removed, the card is cast.
            if (target->suspended && !target->counters->hasCounter("time",0,0))
            {
                GameObserver * game = target->getObserver();
                MTGAbility *ac = NEW AACastCard(game, game->mLayers->actionLayer()->getMaxId(), target, target, false, false, true, "", "", false, false);
                MayAbility *ma1 = NEW MayAbility(game, game->mLayers->actionLayer()->getMaxId(), ac->clone(), target, true);
                MTGAbility *ga1 = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), target, NULL, ma1->clone());
                SAFE_DELETE(ac);
                SAFE_DELETE(ma1);
                ga1->resolve();
                SAFE_DELETE(ga1);
            }
            return mCount;
        }
    }
    return 0;
}
Пример #6
0
WEvent * REDrawReplacement::replace(WEvent *event)
{
    if (!event) return event;
    WEventDraw * e = dynamic_cast<WEventDraw*> (event);
    if (!e) return event;
    if (DrawerOfCard != e->player) return event;
    if(!replacementAbility) return event;
    //check for dredge
    TargetChooserFactory tf(e->player->getObserver());
    TargetChooser * tcb = NULL;
    tcb = tf.createTargetChooser("dredgeable",source->source);
    tcb->targetter = NULL;
    if(tcb->validTargetsExist())
    {
        if(e->player == DrawerOfCard && e->player == source->source->controller())
        {
            SAFE_DELETE(tcb);
            return event;
        }
    }
    SAFE_DELETE(tcb);

    vector<MTGAbility*>selection;
    //look for other draw replacement effects
    list<ReplacementEffect *>::iterator it;
    GameObserver * game = source->source->getObserver();
    if(replacementAbility->source->controller() == DrawerOfCard)
    for (it = game->replacementEffects->modifiers.begin(); it != game->replacementEffects->modifiers.end(); it++)
    {
        if(REDrawReplacement * DR = dynamic_cast<REDrawReplacement *>(*it))
        {
            MTGAbility * otherA = NULL;
            if(DR->DrawerOfCard == e->player)
            {
                if(DR->replacementAbility->oneShot)
                    selection.push_back(DR->replacementAbility->clone());
                else
                {
                    otherA = NEW GenericAddToGame(game, game->mLayers->actionLayer()->getMaxId(), source->source,NULL,DR->replacementAbility->clone());
                    selection.push_back(otherA);
                }
            }
        }
    }

    
    for(int j = 0; j < e->nb_cards; j++)
    {
        if(e->player != DrawerOfCard || selection.size() < 2)
        {
            MTGAbility * toResolve = replacementAbility->clone();
            if(replacementAbility->oneShot)
                toResolve->resolve();
            else
                toResolve->addToGame();
        }
        else
        {
            MTGAbility * menuChoice = NEW MenuAbility(game, 1, source->source, source->source,true,selection,NULL,"Choose Draw Replacement");
            menuChoice->addToGame();
        }
    }

    delete event;
    event = NULL;
    return event;
}
Пример #7
0
void Rules::addExtraRules(GameObserver* g)
{
    int id = g->mLayers->actionLayer()->getMaxId();
    MTGAllCards::sortSubtypeList();
    for (int i = 0; i < 2; ++i)
    {
        Player * p = g->players[i];
        //Trick so that the abilities don't die;
        g->ExtraRules[i].currentZone = p->game->inPlay;
        g->ExtraRules[i].lastController = p;
        g->ExtraRules[i].owner = p;
        for (size_t j = 0; j < initState.playerData[i].extraRules.size(); ++j)
        {
            AbilityFactory af(g);
            MTGPlayerCards * hand = NULL;
            int handsize = 7;
            int difficultyRating = 0;
            int Optimizedhandcheat = options[Options::OPTIMIZE_HAND].number;
            MTGAbility * a = af.parseMagicLine(initState.playerData[i].extraRules[j], id++, NULL, &(g->ExtraRules[i]));
            if (p->playMode != Player::MODE_TEST_SUITE && g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode
                != GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 && g->mRules->gamemode
                != GAME_TYPE_STORY && 
                g->mRules->gamemode != GAME_TYPE_DEMO && (!g->players[0] == PLAYER_TYPE_CPU && !g->players[1] == PLAYER_TYPE_CPU)
#ifdef NETWORK_SUPPORT
                && !g->players[1] == PLAYER_TYPE_REMOTE
#endif //NETWORK_SUPPORT
                    )//keep this out of momir and other game modes.
            {
                difficultyRating = g->getDeckManager()->getDifficultyRating(g->players[0], g->players[1]);
            }

            if (a)
            {
                //We make those non interruptible, so that they don't appear on the player's stack
                a->canBeInterrupted = false;
                if (a->oneShot)
                {
                    if (((p->isAI() && p->playMode
                        != Player::MODE_AI && p->opponent()->playMode
                        != Player::MODE_AI)||( !p->isAI() && Optimizedhandcheat)) && a->aType == MTGAbility::STANDARD_DRAW &&
                        difficultyRating != HARD && p->playMode
                        != Player::MODE_TEST_SUITE && g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode
                        != GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 && g->mRules->gamemode
                        != GAME_TYPE_STORY)//stupid protections to keep this out of mimor and other game modes.
                    {
                        handsize = ((AADrawer *)a)->getNumCards();
                        if(difficultyRating == EASY)
                        {
                            ((AIPlayer *) p)->forceBestAbilityUse = true;
                            ((AIPlayer *) p)->agressivity += 100;
                            hand->OptimizedHand(p,handsize, 3, 1, 3);//easy decks get a major boost, open hand is 2lands,1 creature under 3 mana,3spells under 3 mana.
                        }
                        else if (difficultyRating == NORMAL)
                        {
                            hand->OptimizedHand(p,handsize, 1, 0, 2);//give the Ai deck a tiny boost by giving it 1 land and 2 spells under 3 manacost.
                        }
                        else
                        {
                            hand->OptimizedHand(p,handsize, 3, 1, 3);//no rating fall out case.
                        }
                    }
                    else
                    {//resolve normally if the deck is listed as hard.
                        a->resolve();
                    }
                    delete (a);
                }
                else
                {
                    a->addToGame();
                }

            }
        }
    }

    for (size_t j = 0; j < extraRules.size(); ++j)
    {
        AbilityFactory af(g);
        MTGAbility * a = af.parseMagicLine(extraRules[j], id++, NULL, &(g->ExtraRules[0]));
        if (a)
        {
            if (a->oneShot)
            {
                a->resolve();
                delete (a);
            }
            else
            {
                a->addToGame();
            }
        }
    }
}