Beispiel #1
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;
}
Beispiel #2
0
void StatsWrapper::updateStats(DeckDataWrapper *myDeck)
{
	if (!this->needUpdate || !myDeck) return;

	this->needUpdate = false;
    this->cardCount = myDeck->getCount(WSrcDeck::UNFILTERED_COPIES);
    this->countLands = myDeck->getCount(Constants::MTG_COLOR_LAND);
    this->totalPrice = myDeck->totalPrice();

    this->countManaProducers = 0;
    // Mana cost
    int currentCount, convertedCost;
    ManaCost * currentCost;
    this->totalManaCost = 0;
    this->totalCreatureCost = 0;
    this->totalSpellCost = 0;
    MTGCard * current = NULL;

    // Clearing arrays
    for (int i = 0; i <= Constants::STATS_MAX_MANA_COST; i++)
    {
        this->countCardsPerCost[i] = 0;
        this->countCreaturesPerCost[i] = 0;
        this->countSpellsPerCost[i] = 0;
    }

    for (int i = 0; i <= Constants::NB_Colors; i++)
    {
        this->totalCostPerColor[i] = 0;
        this->countLandsPerColor[i] = 0;
        this->countBasicLandsPerColor[i] = 0;
        this->countNonLandProducersPerColor[i] = 0;
    }

    for (int i = 0; i <= Constants::STATS_MAX_MANA_COST; i++)
    {
        for (int k = 0; k <= Constants::NB_Colors; k++)
        {
            this->countCardsPerCostAndColor[i][k] = 0;
            this->countCreaturesPerCostAndColor[i][k] = 0;
            this->countSpellsPerCostAndColor[i][k] = 0;
        }
    }

    for (int ic = 0; ic < myDeck->Size(true); ic++)
    {
        current = myDeck->getCard(ic, true);
        currentCost = current->data->getManaCost();
        convertedCost = currentCost->getConvertedCost();
        currentCount = myDeck->count(current);

        // Add to the cards per cost counters
        this->totalManaCost += convertedCost * currentCount;
        if (convertedCost > Constants::STATS_MAX_MANA_COST)
        {
            convertedCost = Constants::STATS_MAX_MANA_COST;
        }
        this->countCardsPerCost[convertedCost] += currentCount;
        if (current->data->isCreature())
        {
            this->countCreaturesPerCost[convertedCost] += currentCount;
            this->totalCreatureCost += convertedCost * currentCount;
        }
        else if (current->data->isSpell())
        {
            this->countSpellsPerCost[convertedCost] += currentCount;
            this->totalSpellCost += convertedCost * currentCount;
        }

        // Lets look for mana producing abilities

        //http://code.google.com/p/wagic/issues/detail?id=650
        //Basic lands are not producing their mana through regular abilities anymore,
        //but through a rule that is outside of the primitives. This block is a hack to address this
        const int colors[] = {Constants::MTG_COLOR_GREEN, Constants::MTG_COLOR_BLUE, Constants::MTG_COLOR_RED, Constants::MTG_COLOR_BLACK, Constants::MTG_COLOR_WHITE};
        const string lands[] = { "forest", "island", "mountain", "swamp", "plains" };
        for (unsigned int i = 0; i < sizeof(colors)/sizeof(colors[0]); ++i)
        {
            int colorId = colors[i];
            string type = lands[i];
            if (current->data->hasType(type.c_str()))
            {
                if (current->data->hasType("Basic"))
                {
                    this->countBasicLandsPerColor[colorId] += currentCount;
                }
                else
                {
                    this->countLandsPerColor[colorId] += currentCount;
                }
            }
        }

        vector<string> abilitiesVector;
        string thisstring = current->data->magicText;
        abilitiesVector = split(thisstring, '\n');

        for (int v = 0; v < (int) abilitiesVector.size(); v++)
        {
            string s = abilitiesVector[v];
            size_t t = s.find("add");
            if (t != string::npos)
            {
                s = s.substr(t + 3);
                ManaCost * mc = ManaCost::parseManaCost(s);
                for (int j = 0; j < Constants::NB_Colors; j++)
                {
                    if (mc->hasColor(j))
                    {
                        if (current->data->isLand())
                        {
                            if (current->data->hasType("Basic"))
                            {
                                this->countBasicLandsPerColor[j] += currentCount;
                            }
                            else
                            {
                                this->countLandsPerColor[j] += currentCount;
                            }
                        }
                        else
                        {
                            this->countNonLandProducersPerColor[j] += currentCount;
                        }
                    }
                }
                SAFE_DELETE(mc);
            }
        }

        // Add to the per color counters
        //  a. regular costs
        for (int j = 0; j < Constants::NB_Colors; j++)
        {
            this->totalCostPerColor[j] += currentCost->getCost(j) * currentCount;
            if (current->data->hasColor(j))
            {
                // Add to the per cost and color counter
                this->countCardsPerCostAndColor[convertedCost][j] += currentCount;
                if (current->data->isCreature())
                {
                    this->countCreaturesPerCostAndColor[convertedCost][j] += currentCount;
                }
                else if (current->data->isSpell())
                {
                    this->countSpellsPerCostAndColor[convertedCost][j] += currentCount;
                }
            }
        }

        //  b. Hybrid costs
        ManaCostHybrid * hybridCost;
        int i;
        i = 0;

        while ((hybridCost = currentCost->getHybridCost(i++)) != NULL)
        {
            this->totalCostPerColor[hybridCost->color1] += hybridCost->value1 * currentCount;
            this->totalCostPerColor[hybridCost->color2] += hybridCost->value2 * currentCount;
        }
    }

    this->totalColoredSymbols = 0;
    for (int j = 1; j < Constants::NB_Colors; j++)
    {
        this->totalColoredSymbols += this->totalCostPerColor[j];
    }

    this->countCardsPerCost[0] -= this->countLands;

    // Counts by type
    this->countCreatures = countCardsByType("Creature", myDeck);
    this->countInstants = countCardsByType("Instant", myDeck);
    this->countEnchantments = countCardsByType("Enchantment", myDeck);
    this->countSorceries = countCardsByType("Sorcery", myDeck);
    this->countSpells = this->countInstants + this->countEnchantments + this->countSorceries;
    //this->countArtifacts = countCardsByType("Artifact", myDeck);

    // Average mana costs
    this->avgManaCost = ((this->cardCount - this->countLands) <= 0) ? 0 : (float) this->totalManaCost / (this->cardCount
            - this->countLands);
    this->avgCreatureCost = (this->countCreatures <= 0) ? 0 : (float) this->totalCreatureCost / this->countCreatures;
    this->avgSpellCost = (this->countSpells <= 0) ? 0 : (float) this->totalSpellCost / this->countSpells;

    // Probabilities
    // TODO: this could be optimized by reusing results
    for (int i = 0; i < Constants::STATS_FOR_TURNS; i++)
    {
        this->noLandsProbInTurn[i] = noLuck(this->cardCount, this->countLands, 7 + i) * 100;
        this->noCreaturesProbInTurn[i] = noLuck(this->cardCount, this->countCreatures, 7 + i) * 100;
    }
}
Beispiel #3
0
//WCFilterCMC
bool WCFilterCMC::isMatch(MTGCard * c)
{
    if (!c || !c->data) return false;
    ManaCost * mc = c->data->getManaCost();
    return (mc->getConvertedCost() == number);
}
Beispiel #4
0
int AIMomirPlayer::computeActions()
{
    //Part of the strategy goes here. When should we put a land into play ?
    /*
     Another gift from Alex Majlaton on my first day playing Momir, and it has served me well ever since. It goes a little something like this: (a) if you are on the play, hit your Two through Four, skip your Five, and then hit all the way to Eight; (b) if you are on the draw and your opponent skips his One, you make Two through Eight; (c) if you are on the draw and your opponent hits a One, you match him drop-for-drop for the rest of the game.

     You skip your Five on the play because it is the weakest drop. There are plenty of serviceable guys there, but very few bombs compared to other drops
     the general rule is this: if you want to get to Eight, you have to skip two drops on the play and one drop on the draw.
     */

    Player * p = observer->currentPlayer;
    if (!(observer->currentlyActing() == this)) return 0;
    if (chooseTarget()) return 1;
    int currentGamePhase = observer->getCurrentGamePhase();
    if (observer->isInterrupting == this)
    {   // interrupting
        selectAbility();
        return 1;
    }
    else if (p == this && observer->mLayers->stackLayer()->count(0, NOT_RESOLVED) == 0)
    {   //standard actions
        CardDescriptor cd;
        MTGCardInstance * card = NULL;

        switch (currentGamePhase)
        {
        case MTG_PHASE_FIRSTMAIN:
        {
            ManaCost * potentialMana = getPotentialMana();
            int converted = potentialMana->getConvertedCost();
            SAFE_DELETE(potentialMana);

            if (converted < 8 || game->hand->nb_cards > 1)
            {
                //Attempt to put land into play
                cd.init();
                cd.setColor(Constants::MTG_COLOR_LAND);
                card = cd.match(game->hand);
                int canPutLandsIntoPlay = game->playRestrictions->canPutIntoZone(card, game->inPlay);
                if (card && (canPutLandsIntoPlay == PlayRestriction::CAN_PLAY))
                {
                    MTGAbility * putIntoPlay = observer->mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY);
                    AIAction * a = NEW AIAction(this, putIntoPlay, card); //TODO putinplay action
                    clickstream.push(a);
                    return 1;
                }
            }
            momir();
            return 1;
            break;
        }
        case MTG_PHASE_SECONDMAIN:
            selectAbility();
            return 1;
            break;
        default:
            return AIPlayerBaka::computeActions();
            break;
        }
    }
    return AIPlayerBaka::computeActions();
}
Beispiel #5
0
//if it's not part of a combo or there is more to gather, then return false
bool AIHints::canWeCombo(GameObserver* observer,MTGCardInstance * card,AIPlayerBaka * Ai)
{
    TargetChooserFactory tfc(observer);
    TargetChooser * hintTc = NULL;
    bool gotCombo = false;
    int comboPartsHold = 0;
    int comboPartsUntil = 0;
    int comboPartsRestriction = 0;
    for(unsigned int i = 0; i < hints.size();i++)
    {
        comboPartsHold = 0;
        comboPartsUntil = 0;
        comboPartsRestriction = 0;
        if(gotCombo)
            return gotCombo;//because more then one might be possible at any time.
        if (hints[i]->hold.size())
        {
            for(unsigned int hPart = 0; hPart < hints[i]->hold.size(); hPart++)
            {
                hintTc = tfc.createTargetChooser(hints[i]->hold[hPart],card);
                int TcCheck = hintTc->countValidTargets();
                if(hintTc && TcCheck >= hintTc->maxtargets)
                {
                    comboPartsHold +=1;
                }
                SAFE_DELETE(hintTc);
            }
        }
        if (hints[i]->until.size())
        {
            for(unsigned int hPart = 0; hPart < hints[i]->until.size(); hPart++)
            {
                hintTc = tfc.createTargetChooser(hints[i]->until[hPart],card);
                int TcCheck = hintTc->countValidTargets();
                if(hintTc && TcCheck >= hintTc->maxtargets)
                {
                    comboPartsUntil +=1;
                }
                SAFE_DELETE(hintTc);
            }
        }
        if (hints[i]->restrict.size())
        {
            for(unsigned int hPart = 0; hPart < hints[i]->restrict.size(); hPart++)
            {
                AbilityFactory af(observer);
                int checkCond = af.parseCastRestrictions(card,card->controller(),hints[i]->restrict[hPart]);
                if(checkCond >= 1)
                {
                    comboPartsRestriction +=1;
                }
            }
        }
        if( comboPartsUntil >= int(hints[i]->until.size()) && comboPartsHold >= int(hints[i]->hold.size()) && comboPartsRestriction >= int(hints[i]->restrict.size()) && hints[i]->combos.size() )
        {
            ManaCost * needed = ManaCost::parseManaCost(hints[i]->manaNeeded, NULL, card);
            if(Ai->canPayManaCost(card,needed).size()||!needed->getConvertedCost())
            {
                gotCombo = true;
                Ai->comboHint = hints[i];//set the combo we are doing.
            }
            SAFE_DELETE(needed);
        }
    }
    return gotCombo;
}