Beispiel #1
0
void AIStats::Render()
{
    GameObserver * g = player->getObserver();
    float x0 = 10;
    if (player == g->players[1])
        x0 = 280;
    JRenderer::GetInstance()->FillRoundRect(x0, 10, 200, 180, 5, ARGB(50,0,0,0));

    WFont * f = g->getResourceManager()->GetWFont(Fonts::MAIN_FONT);
    int i = 0;
    char buffer[512];
    list<AIStat *>::iterator it;
    for (it = stats.begin(); it != stats.end(); ++it)
    {
        if (i > 10)
            break;
        AIStat * stat = *it;
        if (stat->value > 0)
        {
            MTGCard * card = MTGCollection()->getCardById(stat->source);
            if (card)
            {
                sprintf(buffer, "%s %i", card->data->getName().c_str(), stat->value);
                f->DrawString(buffer, x0 + 5, 10 + 16 * (float) i);
                i++;
            }
        }
    }
}
Beispiel #2
0
int Counters::addCounter(const char * _name, int _power, int _toughness)
{
    /*420.5n If a permanent has both a +1/+1 counter and a -1/-1 counter on it, N +1/+1 and N -1/-1 counters are removed from it, where N is the smaller of the number of +1/+1 and -1/-1 counters on it.*/
    GameObserver *g = target->getObserver();
    WEvent * e = NEW WEventCounters(this,_name,_power,_toughness);
    dynamic_cast<WEventCounters*>(e)->targetCard = this->target;
    if (e == g->replacementEffects->replace(e))
    {
        for (int i = 0; i < mCount; i++)
        {
            if (counters[i]->sameAs(_name, _power, _toughness))
            {
                counters[i]->added();
                counters[i]->nb++;
                WEvent * j = NEW WEventCounters(this,_name,_power,_toughness,true,false);
                dynamic_cast<WEventCounters*>(j)->targetCard = this->target;
                g->receiveEvent(j);
                delete(e);
                return mCount;
            }
        }
        Counter * counter = NEW Counter(target, _name, _power, _toughness);
        counters.push_back(counter);
        counter->added();
        WEvent * w = NEW WEventCounters(this,_name,_power,_toughness,true,false);
        dynamic_cast<WEventCounters*>(w)->targetCard = this->target;
        g->receiveEvent(w);
        mCount++;
        this->target->doDamageTest = 1;
        this->target->afterDamage();
    }
    delete(e);
    return mCount;
}
Beispiel #3
0
int AIAction::clickMultiAct(vector<Targetable*>& actionTargets)
{
    GameObserver * g = owner->getObserver();
    TargetChooser * tc = g->getCurrentTargetChooser();
    if(!tc) return 0;
    vector<Targetable*>::iterator ite = actionTargets.begin();
    while(ite != actionTargets.end())
    {
        MTGCardInstance * card = ((MTGCardInstance *) (*ite));
        if(card == (MTGCardInstance*)tc->source)//click source first.
        {
            g->cardClick(card);
            ite = actionTargets.erase(ite);
            continue;
        }
        ++ite;
    }

    //shuffle to make it less predictable, otherwise ai will always seem to target from right to left. making it very obvious.
    owner->getRandomGenerator()->random_shuffle(actionTargets.begin(), actionTargets.end());

    for(int k = 0 ;k < int(actionTargets.size()) && k < tc->maxtargets; k++)
    {
        if (MTGCardInstance * card = dynamic_cast<MTGCardInstance *>(actionTargets[k]))
        {
            if(k+1 == int(actionTargets.size()))
                tc->done = true;
            g->cardClick(card);
        }
    }
    tc->attemptsToFill++;
    return 1;
}
Beispiel #4
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: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();
                MTGCardInstance * copy = target->controller()->game->putInZone(target, target->currentZone, target->controller()->game->stack);

                game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, NULL,1, 0);
                game->targetChooser = NULL;
            }
            return mCount;
        }
    }
    return 0;
}
Beispiel #5
0
/*
 * Starts running the game or continues a last run that was stopped
 *
 * quit_at_step: -1 to ignore step count
 */
void Game::run(GameObserver& observer, bool pause_at_end_of_input, int stop_at_step) {
    REQUIRE(initialised);

    bool stop_at_end_of_input = !pause_at_end_of_input;
    while (!observer.should_stop() && stop_at_step != get_steps() && !get_state().is_game_over()) {
        if (!observer.is_paused()) {
            auto input = get_input();

            if (input.empty()) {
                if (stop_at_end_of_input) {
                    break;
                }
                else {
                    stop_at_end_of_input = true;
                    observer.pause();
                }
            }
            else {
                if (act(input)) {
                    observer.finished_step(get_state());
                }
            }
        }
    }
}
Beispiel #6
0
void MTGPlayerCards::discardRandom(MTGGameZone * from, MTGCardInstance *)
{
    if (!from->nb_cards)
        return;
    int r = owner->getObserver()->getRandomGenerator()->random() % (from->nb_cards);
    WEvent * e = NEW WEventCardDiscard(from->cards[r]);
    GameObserver * game = owner->getObserver();
    game->receiveEvent(e);
    putInZone(from->cards[r], from, graveyard);
}
Beispiel #7
0
int Counter::cancelCounter(int power, int toughness)
{
    while(this->target->counters->hasCounter(power,toughness) && this->target->counters->hasCounter(power*-1,toughness*-1))
    {
        GameObserver *g = this->target->getObserver();
        this->removed();
        this->nb--;
        WEvent * t = NEW WEventCounters(NULL,"",power*-1,toughness*-1,false,true);
        dynamic_cast<WEventCounters*>(t)->targetCard = this->target;
        g->receiveEvent(t);
        this->target->counters->removeCounter(power,toughness);
    }
    return 1;
}
Beispiel #8
0
int SacrificeCost::doPay()
{
    if (target)
    {
        MTGCardInstance * beforeCard = target;
        source->storedCard = target->createSnapShot();
        target->controller()->game->putInGraveyard(target);
        WEvent * e = NEW WEventCardSacrifice(beforeCard,target);
        GameObserver * game = target->owner->getObserver();
        game->receiveEvent(e);
        target = NULL;
        if (tc)
            tc->initTargets();
        return 1;
    }
    return 0;
}
Beispiel #9
0
int CycleCost::doPay()
{
    MTGCardInstance * _source = (MTGCardInstance *) source;
    if (_source)
    {
        WEvent * e = NEW WEventCardDiscard(target);//cycling sends 2 events one for the discard and one for the specific cycle trigger
        GameObserver * game = _source->owner->getObserver();
        game->receiveEvent(e);
        WEvent * e2 = NEW WEventCardCycle(_source);
        game->receiveEvent(e2);
        _source->controller()->game->putInGraveyard(_source);
        if (tc)
            tc->initTargets();
        return 1;
    }
    return 0;
}
Beispiel #10
0
int DiscardCost::doPay()
{
    MTGCardInstance * _target = (MTGCardInstance *) target;
    if (target)
    {
        source->storedCard = target->createSnapShot();
        WEvent * e = NEW WEventCardDiscard(target);
        GameObserver * game = target->owner->getObserver();
        game->receiveEvent(e);
        _target->controller()->game->putInGraveyard(_target);
        target = NULL;
        if (tc)
            tc->initTargets();
        return 1;
    }
    return 0;
}
Beispiel #11
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;
}
Beispiel #12
0
int AIAction::Act()
{
    GameObserver * g = owner->getObserver();
    if (player && !playerAbilityTarget)
    {
        g->cardClick(NULL, player);
        return 1;
    }
    if (ability)
    {
        g->cardClick(click, ability);
        if (target && !mAbilityTargets.size())
        {
            g->cardClick(target);
            return 1;
        }
        else if(playerAbilityTarget && !mAbilityTargets.size())
        {
            g->cardClick(NULL,(Player*)playerAbilityTarget);
            return 1;
        }
        if(mAbilityTargets.size())
        {
            return clickMultiAct(mAbilityTargets);
        }
    }
    else  if(mAbilityTargets.size())
    {
        return clickMultiAct(mAbilityTargets);
    }
    else if (click)
    { //Shouldn't be used, really...
        g->cardClick(click, click);
        if (target)
            g->cardClick(target);
        return 1;
    }
    return 0;
}
Beispiel #13
0
// Moves a card from one zone to another
// If the card is not actually in the expected "from" zone, does nothing and returns null 
MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to,bool asCopy)
{
    MTGCardInstance * copy = NULL;
    GameObserver *g = owner->getObserver();
    if (!from || !to)
        return card; //Error check

    int doCopy = 1;
    bool shufflelibrary = card->basicAbilities[(int)Constants::SHUFFLELIBRARYDEATH];
    bool inplaytoinplay = false;
    bool ripToken = false;
    if (g->players[0]->game->battlefield->hasName("Rest in Peace")||g->players[1]->game->battlefield->hasName("Rest in Peace"))
        ripToken = true;
    //Madness or Put in Play...
    for(int i = 0; i < 2; ++i)
    {
        if (card->discarded && (to == g->players[i]->game->graveyard) && (from == g->players[i]->game->hand))
        {
            if(card->basicAbilities[(int)Constants::MADNESS])
                to = g->players[i]->game->exile;
        }
    }
    //Darksteel Colossus, Legacy Weapon ... top priority since we replace destination directly automatically...
    for(int i = 0; i < 2; ++i)
    {
        if ((to == g->players[i]->game->graveyard) && (
        card->basicAbilities[(int)Constants::LIBRARYDEATH]||
        card->basicAbilities[(int)Constants::SHUFFLELIBRARYDEATH]))
        {
            to = g->players[i]->game->library;
        }
    }
    //Leyline of the Void, Yawgmoth's Agenda... effect...
    for(int i = 0; i < 2; ++i)
    {
        if ((to == g->players[i]->game->graveyard) && (
        (g->players[i]->game->battlefield->hasAbility(Constants::MYGCREATUREEXILER) && card->isCreature()) ||
        (g->players[i]->opponent()->game->battlefield->hasAbility(Constants::OPPGCREATUREEXILER) && card->isCreature())||
        g->players[i]->game->battlefield->hasAbility(Constants::MYGRAVEEXILER) ||
        g->players[i]->opponent()->game->battlefield->hasAbility(Constants::OPPGRAVEEXILER)))
        {
            if ((card->isToken && ripToken))
                to = g->players[i]->game->exile;
            if (!card->isToken)
                to = g->players[i]->game->exile;
        }
    }
    //When a card is moved from inPlay to inPlay (controller change, for example), it is still the same object
    if ((to == g->players[0]->game->inPlay || to == g->players[1]->game->inPlay) && (from == g->players[0]->game->inPlay || from
                    == g->players[1]->game->inPlay))
    {
        doCopy = 0;
        asCopy = true;//don't send zone change event so it will not destroy the GUI when multiple switching of control...
        inplaytoinplay = true;//try sending different event...
    }

    if (!(copy = from->removeCard(card, doCopy)))
        return NULL; //ERROR
    if (card->miracle)
    {
        copy->miracle = true;
    }
    if (card->discarded)
    {//set discarded for madness...
        if(from == g->players[0]->game->hand || from == g->players[1]->game->hand)
            copy->discarded = true;
        else//turn off discarded if its previous zone is not in hand...
            copy->discarded = false;
    }
    if (options[Options::SFXVOLUME].number > 0)
    {
        if (to == g->players[0]->game->graveyard || to == g->players[1]->game->graveyard)
        {
            if (card->isCreature() && g->getResourceManager())
            {
                g->getResourceManager()->PlaySample("graveyard.wav");
            }
        }
    }

    MTGCardInstance * ret = copy;
    for(int i = 0; i < 2; ++i)
    {
        if(to == g->players[i]->game->library && from == g->players[i]->game->library)//if its going to the library from the library we intend to put it on top.
        {
            g->players[i]->game->temp->addCard(copy);
            g->players[i]->game->library->placeOnTop.push_back(copy);
            return ret;//don't send event
        }
    }
    to->addCard(copy);
    //The "Temp" zone are purely for code purposes, and we don't want the abilities engine to
    //Trigger when cards move in this zone
    // Additionally, when they move "from" this zone,
    // we trick the engine into believing that they moved from the zone the card was previously in
    // See http://code.google.com/p/wagic/issues/detail?id=335
    {
        if (to == g->players[0]->game->temp || to == g->players[1]->game->temp)
        {
            //don't send event when moving to temp
            return ret;
        }

        if (from == g->players[0]->game->temp || from == g->players[1]->game->temp)
        {
            //remove temporary stuff
            MTGCardInstance * previous = copy->previous;
            MTGCardInstance * previous2 = previous->previous;
            from = previous->previousZone;
            copy->previous = previous2;
            if (previous2)
                previous2->next = copy;
            previous->previous = NULL;
            previous->next = NULL;
            SAFE_DELETE(previous);
        }
    }
    if(!asCopy)
    {
        if(shufflelibrary)
            copy->owner->game->library->shuffle();

    WEvent * e = NEW WEventZoneChange(copy, from, to);
    g->receiveEvent(e);
    }
    if(inplaytoinplay)
    {
    WEvent * ep = NEW WEventCardControllerChange(copy);
    g->receiveEvent(ep);
    }
    return ret;

}