Example #1
0
void StackAbility::Render()
{
    string action = ability->getMenuText();
    MTGCardInstance * source = ability->source;
    string alt1 = source->getName();

    Targetable * _target = ability->target;
    if (ability->getActionTc())
    {
        Targetable * t = ability->getActionTc()->getNextTarget();
        if (t)
            _target = t;
    }
    Damageable * target = NULL;
    if (_target != ability->source && (dynamic_cast<MTGCardInstance *>(_target) || dynamic_cast<Player *>(_target)))
    {
        target = (Damageable *) _target;
    }

    JQuadPtr quad;
    string alt2 = "";
    if (target)
    {
        quad = target->getIcon();
        if (target->type_as_damageable == Damageable::DAMAGEABLE_MTGCARDINSTANCE)
        {
            alt2 = ((MTGCardInstance *) target)->name;
        }
    }

    Interruptible::Render(source, quad.get(), alt1, alt2, action);
}
Example #2
0
int MTGGameZone::seenThisTurn(TargetChooser * tc, int castMethod, bool lastTurn)
{
    //The following 2 lines modify the passed TargetChooser. Call this function with care :/
    tc->setAllZones(); // This is to allow targetting cards without caring about the actual zone
    tc->targetter = NULL;

    int count = 0;
    if (lastTurn)
    {
        for (vector<MTGCardInstance *>::iterator iter = cardsSeenLastTurn.begin(); iter != cardsSeenLastTurn.end(); ++iter)
        {
            MTGCardInstance * c = (*iter);
            if (c && c->matchesCastFilter(castMethod) &&  tc->canTarget(c))
                count++;
        }
    }
    else
    {
        for (vector<MTGCardInstance *>::iterator iter = cardsSeenThisTurn.begin(); iter != cardsSeenThisTurn.end(); ++iter)
        {
            MTGCardInstance * c = (*iter);
            if (c->matchesCastFilter(castMethod) &&  tc->canTarget(c))
                count++;
        }
    }
    return count;
}
Example #3
0
void AIStats::updateStatsCard(MTGCardInstance * cardInstance, Damage * damage, float multiplier)
{
    MTGCard * card = cardInstance->model;
    if (!card)
        return; //card can be null because some special cardInstances (such as ExtraRules) don't have a "model"

    AIStat * stat = find(card);
    if (!stat)
    {
        stat = NEW AIStat(card->getMTGId(), 0, 1, 0);
        stats.push_back(stat);
    }
    if (damage->target == player)
    {
        stat->value += static_cast<int>(multiplier * STATS_PLAYER_MULTIPLIER * damage->damage);
    }
    else if (damage->target->type_as_damageable == Damageable::DAMAGEABLE_MTGCARDINSTANCE)
    {
        MTGCardInstance * target = (MTGCardInstance *) damage->target;
        if (target->controller() == player && !target->isInPlay(player->getObserver()))
        {
            //One of my creatures got lethal damage...
            stat->value += static_cast<int>(multiplier * STATS_CREATURE_MULTIPLIER * damage->damage);
        }
    }
}
Example #4
0
MTGCardInstance * TestSuiteAI::getCard(string action)
{
    int mtgid = Rules::getMTGId(action);
    if (mtgid) return Rules::getCardByMTGId(observer, mtgid);

    //This mostly handles tokens
    std::transform(action.begin(), action.end(), action.begin(), ::tolower);
    for (int i = 0; i < 2; i++)
    {
        Player * p = observer->players[i];
        MTGGameZone * zones[] = { p->game->library, p->game->hand, p->game->inPlay, p->game->graveyard };
        for (int j = 0; j < 4; j++)
        {
            MTGGameZone * zone = zones[j];
            for (int k = 0; k < zone->nb_cards; k++)
            {
                MTGCardInstance * card = zone->cards[k];
                if (!card) return NULL;
                string name = card->getLCName();
                if (name.compare(action) == 0) return card;
            }
        }
    }
    DebugTrace("TESTUISTEAI: Can't find card:" << action.c_str());
    return NULL;
}
Example #5
0
int GuiCombat::resolve() // Returns the number of damage objects dealt this turn.
{
    DamageStack* stack = NEW DamageStack(observer);
    for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
    {
        MTGCardInstance * attacker = (*it)->card;
        signed dmg = attacker->stepPower(step);
        for (vector<DefenserDamaged*>::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q)
        {
            for (vector<Damage>::iterator d = (*q)->damages.begin(); d != (*q)->damages.end(); ++d)
                stack->Add(NEW Damage(*d));
            dmg -= (*q)->sumDamages();
        }

        if (dmg > 0 && ((!attacker->isBlocked()) || attacker->has(Constants::TRAMPLE)))
            stack->Add(NEW Damage(observer, (*it)->card, (Damageable*)attacker->isAttacking?(Damageable*)attacker->isAttacking:observer->opponent(), dmg, DAMAGE_COMBAT));

        for (vector<Damage>::iterator d = (*it)->damages.begin(); d != (*it)->damages.end(); ++d)
            stack->Add(NEW Damage(*d));
    }
    int v = stack->mObjects.size();
    if (v > 0)
    {
        observer->mLayers->stackLayer()->Add(stack);
        observer->mLayers->stackLayer()->resolve(); // This will delete the damage stack which will in turn delete the Damage it contains
    }
    else
        SAFE_DELETE(stack);
    return v;
}
Example #6
0
//Returns true if a card with the given MTG ID exists
bool AIHints::findSource(int sourceId)
{
    for (int i = 0; i < mPlayer->game->inPlay->nb_cards; i++)
    {
        MTGCardInstance * c = mPlayer->game->inPlay->cards[i];
        if (c->getMTGId() == sourceId)
            return true;
    }
    return false;
}
Example #7
0
MTGCardInstance * MTGInPlay::findALurer()
{
    for (int i = 0; i < nb_cards; i++)
    {
        MTGCardInstance * current = cards[i];
        if (current->isAttacker() && current->has(Constants::LURE))
        {
            return current;
        }
    }
    return NULL;
}
Example #8
0
bool Player::hasPossibleAttackers()
{
    MTGGameZone * z = game->inPlay;
    int nbcards = z->nb_cards;
    for (int j = 0; j < nbcards; ++j)
    {
        MTGCardInstance * c = z->cards[j];
        if (!c->isTapped() &&
            !c->hasSummoningSickness() &&
            c->isCreature())
            return true;
    }
    return false;
}
Example #9
0
bool Player::DeadLifeState(bool check)
{
    if ((life <= 0)||(poisonCount >= 10))
    {
        int cantlosers = 0;
        MTGGameZone * z = game->inPlay;
        int nbcards = z->nb_cards;
        for (int j = 0; j < nbcards; ++j)
        {
            MTGCardInstance * c = z->cards[j];
            if (c->has(Constants::CANTLOSE) || (c->has(Constants::CANTLIFELOSE) && poisonCount < 10))
            {
                cantlosers++;
            }
        }
        MTGGameZone * k = opponent()->game->inPlay;
        int onbcards = k->nb_cards;
        for (int m = 0; m < onbcards; ++m)
        {
            MTGCardInstance * e = k->cards[m];
            if (e->has(Constants::CANTWIN))
            {
            cantlosers++;
            }
        }
        if (cantlosers < 1)
        {
            if(!check)
            {
                ActionStack * stack = getObserver()->mLayers->stackLayer();
                for (int i = stack->mObjects.size() - 1; i >= 0; i--)
                {
                    Interruptible * current = ((Interruptible *) stack->mObjects[i]);
                    Spell * spell = (Spell *) current;
                    if (current->type == ACTION_SPELL)
                        spell->source->controller()->game->putInGraveyard(spell->source);

                    current->state = RESOLVED_NOK;
                }
            }
            if(check)
                game->owner->getObserver()->setLoser(this);
            return true;
        }
    }
    return false;
}
Example #10
0
//Returns opponents to this card for this turn. This * should * take into account banding
MTGCardInstance * MTGCardInstance::getNextOpponent(MTGCardInstance * previous)
{
    int foundprevious = 0;
    if (!previous)
        foundprevious = 1;
    if (attacker)
    {
        MTGInPlay * inPlay = observer->opponent()->game->inPlay;
        for (int i = 0; i < inPlay->nb_cards; i++)
        {
            MTGCardInstance * current = inPlay->cards[i];
            if (current == previous)
            {
                foundprevious = 1;
            }
            else if (foundprevious)
            {
                MTGCardInstance * defensersOpponent = current->isDefenser();
                if (defensersOpponent && (defensersOpponent == this || (banding && defensersOpponent->banding == banding)))
                {
                    return current;
                }
            }
        }
    }
    else if (defenser)
    {
        MTGInPlay * inPlay = observer->currentPlayer->game->inPlay;
        for (int i = 0; i < inPlay->nb_cards; i++)
        {
            MTGCardInstance * current = inPlay->cards[i];
            if (current == previous)
            {
                foundprevious = 1;
            }
            else if (foundprevious)
            {
                if (defenser == current || (current->banding && defenser->banding == current->banding))
                {
                    return current;
                }
            }
        }
    }
    return NULL;
}
Example #11
0
void MTGPlayerCards::drawFromLibrary()
{
    if (!library->nb_cards)
    {
        if (inPlay->hasAbility(Constants::CANTLOSE)
            || inPlay->hasAbility(Constants::CANTMILLLOSE)
            || owner->opponent()->game->inPlay->hasAbility(Constants::CANTWIN))
        {
            return;
        }

        library->owner->getObserver()->setLoser(library->owner);
        return;
    }
    MTGCardInstance * toMove = library->cards[library->nb_cards - 1];
    library->lastCardDrawn = toMove;
    if (!library->miracle)
    {
        library->miracle = true;
        toMove->miracle = true;
    }

    // useability tweak - assume that the user is probably going to want to see the new card,
    // so prefetch it.

    // if we're not in text mode, always get the thumb
    if (library->owner->getObserver()->getCardSelector()->GetDrawMode() != DrawMode::kText
            && library->owner->getObserver()->getResourceManager())
    {
        DebugTrace("Prefetching AI card going into play: " << toMove->getImageName());
        library->owner->getObserver()->getResourceManager()->RetrieveCard(toMove, RETRIEVE_THUMB);

        // also cache the large image if we're using kNormal mode
        if (library->owner->getObserver()->getCardSelector()->GetDrawMode() == DrawMode::kNormal)
        {
            library->owner->getObserver()->getResourceManager()->RetrieveCard(toMove);
        }
    }

    if(putInZone(toMove, library, hand))
    {
        toMove->currentZone = hand;
        }
}
Example #12
0
MTGCardInstance * Rules::getCardByMTGId(GameObserver* g, int mtgid)
{
    for (int i = 0; i < 2; i++)
    {
        Player * p = g->players[i];
        MTGGameZone * zones[] = { p->game->library, p->game->hand, p->game->inPlay, p->game->graveyard };
        for (int j = 0; j < 4; j++)
        {
            MTGGameZone * zone = zones[j];
            for (int k = 0; k < zone->nb_cards; k++)
            {
                MTGCardInstance * card = zone->cards[k];
                if (!card) return NULL;
                if (card->getMTGId() == mtgid) return card;
            }
        }
    }
    return NULL;
}
Example #13
0
void MTGInPlay::untapAll()
{
    int i;
    for (i = 0; i < nb_cards; i++)
    {
        MTGCardInstance * card = cards[i];
        card->setUntapping();
        if (!card->basicAbilities[(int)Constants::DOESNOTUNTAP])
        {
            if (card->frozen < 1)
            {
                card->attemptUntap();
            }
            if (card->frozen >= 1)
            {
                card->frozen = 0;
            }

        }
    }
}
Example #14
0
MTGCardInstance * MTGInPlay::getNextLurer(MTGCardInstance * previous)
{
    int foundprevious = 0;
    if (previous == NULL)
    {
        foundprevious = 1;
    }
    for (int i = 0; i < nb_cards; i++)
    {
        MTGCardInstance * current = cards[i];
        if (current == previous)
        {
            foundprevious = 1;
        }
        else if (foundprevious && current->isAttacker() && current->has(Constants::LURE))
        {
            return current;
        }
    }
    return NULL;
}
Example #15
0
void ActionStack::Update(float dt)
{
    //This is a hack to avoid updating the stack while tuto messages are being shown
    //Ideally, the tuto messages should be moved to a layer above this one
    //No need for Tuto when no human in game
    if (getCurrentTutorial() && (observer->players[0]->isHuman() || observer->players[1]->isHuman() ) )
        return;

    askIfWishesToInterrupt = NULL;
    //modal = 0;

    TargetChooser * tc = observer->getCurrentTargetChooser();
    int newState = observer->getCurrentGamePhase();
    currentState = newState;
    if (!tc)
        checked = 0;

    //Select Stack's display mode
    if (mode == ACTIONSTACK_STANDARD && tc && !checked)
    {
        checked = 1;

        for (size_t i = 0; i < mObjects.size(); i++)
        {
            Interruptible * current = (Interruptible *) mObjects[i];
            if (tc->canTarget(current))
            {
                if (mCurr < (int) mObjects.size() && mObjects[mCurr])
                    mObjects[mCurr]->Leaving(JGE_BTN_UP);
                current->display = 1;
                mCurr = i;
                mObjects[mCurr]->Entering();
                mode = ACTIONSTACK_TARGET;
                modal = 1;
            }
            else
            {
                current->display = 0;
            }
        }
        if (mode != ACTIONSTACK_TARGET)
        {
        }
    }
    else if (mode == ACTIONSTACK_TARGET && !tc)
    {
        mode = ACTIONSTACK_STANDARD;
        checked = 0;
    }

    if (mode == ACTIONSTACK_STANDARD)
    {
        modal = 0;
        if (getLatest(NOT_RESOLVED) && !tc)
        {
            Interruptible * currentSpell = (Interruptible *)getLatest(NOT_RESOLVED);
            MTGCardInstance * card = currentSpell->source;
            if(card && card->has(Constants::SPLITSECOND))
            {
                resolve();
            }
            else
            {
                int currentPlayerId = 0;
                int otherPlayerId = 1;
                if (observer->currentlyActing() != observer->players[0])
                {
                    currentPlayerId = 1;
                    otherPlayerId = 0;
                }
                if (interruptDecision[currentPlayerId] == NOT_DECIDED)
                {
                    askIfWishesToInterrupt = observer->players[currentPlayerId];
                    observer->isInterrupting = observer->players[currentPlayerId];
                    modal = 1;
                }
                else if (interruptDecision[currentPlayerId] == INTERRUPT)
                {
                    observer->isInterrupting = observer->players[currentPlayerId];

                }
                else
                {
                    if (interruptDecision[otherPlayerId] == NOT_DECIDED)
                    {
                        askIfWishesToInterrupt = observer->players[otherPlayerId];
                        observer->isInterrupting = observer->players[otherPlayerId];
                        modal = 1;
                    }
                    else if (interruptDecision[otherPlayerId] == INTERRUPT)
                    {
                        observer->isInterrupting = observer->players[otherPlayerId];
                    }
                    else
                    {
                        resolve();
                    }
                }
            }
        }
    }
    else if (mode == ACTIONSTACK_TARGET)
    {
        GuiLayer::Update(dt);
    }
    if (askIfWishesToInterrupt)
    {
        // WALDORF - added code to use a game option setting to determine how
        // long the Interrupt timer should be. If it is set to zero (0), the
        // game will wait for ever for the user to make a selection.
        if (options[Options::INTERRUPT_SECONDS].number > 0)
        {
            int extraTime = 0;
            //extraTime is a multiplier, it counts the number of unresolved stack actions
            //then is used to extend the time you have to interupt.
            //this prevents you from "running out of time" while deciding.
            //before this int was added, it was possible to run out of time if you had 10 stack actions
            //and set the timer to 4 secs. BUG FIX //http://code.google.com/p/wagic/issues/detail?id=464
            extraTime = count(0, NOT_RESOLVED, 0);
            if (extraTime == 0)
                extraTime = 1;//we never want this int to be 0.

            if (timer < 0)
                timer = static_cast<float>(options[Options::INTERRUPT_SECONDS].number * extraTime);
            timer -= dt;
            if (timer < 0)
                cancelInterruptOffer();
        }
    }
}
Example #16
0
void TestSuiteGame::assertGame()
{
    mMutex.lock();
    //compare the game state with the results
    char result[4096];
    sprintf(result, "<h3>%s</h3>", filename.c_str());
    Log(result);

    int error = 0;
    bool wasAI = false;

	if (observer->getCurrentGamePhase() != endState.phase)
    {
        sprintf(result, "<span class=\"error\">==phase problem. Expected [ %s ](%i), got [ %s ](%i)==</span><br />", 
            Constants::MTGPhaseNames[endState.phase],endState.phase,
            Constants::MTGPhaseNames[observer->getCurrentGamePhase()], observer->getCurrentGamePhase());
        Log(result);
        error++;
    }
    for (int i = 0; i < 2; i++)
    {
        TestSuiteAI * p = (TestSuiteAI *) (observer->players[i]);
        if (p->playMode == Player::MODE_AI) wasAI = true;

        if (p->life != endState.players[i]->life)
        {
            sprintf(result, "<span class=\"error\">==life problem for player %i. Expected %i, got %i==</span><br />", i,
                            endState.players[i]->life, p->life);
            Log(result);
            error++;
        }
        if (p->poisonCount != endState.players[i]->poisonCount)
        {
            sprintf(result, "<span class=\"error\">==poison counter problem for player %i. Expected %i, got %i==</span><br />", i,
                            endState.players[i]->poisonCount, p->poisonCount);
            Log(result);
            error++;
        }        if (!p->getManaPool()->canAfford(endState.players[i]->getManaPool()))
        {
            sprintf(result, "<span class=\"error\">==Mana problem. Was expecting %i but got %i for player %i==</span><br />",
                            endState.players[i]->getManaPool()->getConvertedCost(), p->getManaPool()->getConvertedCost(), i);
            Log(result);
            error++;
        }
        if (!endState.players[i]->getManaPool()->canAfford(p->getManaPool()))
        {
            sprintf(result, "<span class=\"error\">==Mana problem. Was expecting %i but got %i for player %i==</span><br />",
                            endState.players[i]->getManaPool()->getConvertedCost(), p->getManaPool()->getConvertedCost(), i);
            Log(result);

            if ( endState.players[i]->getManaPool()->getConvertedCost() == p->getManaPool()->getConvertedCost())
            {
                sprintf(result, "<span class=\"error\">====(Apparently Mana Color issues since converted cost is the same)==</span><br />");
                Log(result);
            }
            error++;

        }
        MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay };
        MTGGameZone * endstateZones[] = { endState.players[i]->game->graveyard,
                                         endState.players[i]->game->library,
                                         endState.players[i]->game->hand,
                                         endState.players[i]->game->inPlay };
        for (int j = 0; j < 4; j++)
        {
            MTGGameZone * zone = playerZones[j];
            if (zone->nb_cards != endstateZones[j]->nb_cards)
            {
                sprintf(
                                result,
                                "<span class=\"error\">==Card number not the same in player %i's %s==, expected %i, got %i</span><br />",
                                i, zone->getName(), endstateZones[j]->nb_cards, zone->nb_cards);
                Log(result);
                error++;
            }
            for (size_t k = 0; k < (size_t)endstateZones[j]->nb_cards; k++)
            {
                MTGCardInstance* cardToCheck = (k<endstateZones[j]->cards.size())?endstateZones[j]->cards[k]:0;
                if(cardToCheck)
                {   // Can be NULL if used "*" in the testcase.
                    MTGCardInstance* card = Rules::getCardByMTGId(observer, cardToCheck->getId());
                    if (card != 0 && !zone->hasCard(card))
                    {
                        sprintf(result, "<span class=\"error\">==Card ID not the same. Didn't find %i</span><br />", card->getId());
                        Log(result);
                        error++;
                    }
                }
            }
        }
    }
    handleResults(wasAI, error);

    if(!error)
        Log("<span class=\"success\">==Test Succesful !==</span>");
    else
        Log("<span class=\"error\">==Test Failed !==</span>");
    mMutex.unlock();
}