bool AIHints::HintSaysDontAttack(GameObserver* observer,MTGCardInstance * card) { TargetChooserFactory tfc(observer); TargetChooser * hintTc = NULL; for(unsigned int i = 0; i < hints.size();i++) { if (hints[i]->mCombatAttackTip.size()) { hintTc = tfc.createTargetChooser(hints[i]->mCombatAttackTip,card); if(hintTc && hintTc->canTarget(card,true)) { SAFE_DELETE(hintTc); return true; } SAFE_DELETE(hintTc); } } return false; }
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(); } } }
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; }
//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; }
bool AIHints::HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card) { TargetChooserFactory tfc(observer); TargetChooser * hintTc = NULL; bool forCombo = false; for(unsigned int i = 0; i < hints.size();i++) { if (hints[i]->combos.size()) { //time to find the parts and condiations of the combo. string part = ""; if(!hints[i]->partOfCombo.size() && hints[i]->combos.size()) { for(unsigned int cPart = 0; cPart < hints[i]->combos.size(); cPart++) { //here we disect the different parts of a given combo part = hints[i]->combos[cPart]; hints[i]->partOfCombo = split(part,'^'); for(unsigned int dPart = 0; dPart < hints[i]->partOfCombo.size(); dPart++) { vector<string>asTc; asTc = parseBetween(hints[i]->partOfCombo[dPart],"hold(",")"); if(asTc.size()) { hints[i]->hold.push_back(asTc[1]); asTc.clear(); } asTc = parseBetween(hints[i]->partOfCombo[dPart],"until(",")"); if(asTc.size()) { hints[i]->until.push_back(asTc[1]); asTc.clear(); } asTc = parseBetween(hints[i]->partOfCombo[dPart],"restriction{","}"); if(asTc.size()) { hints[i]->restrict.push_back(asTc[1]); asTc.clear(); } asTc = parseBetween(hints[i]->partOfCombo[dPart],"cast(",")"); if(asTc.size()) { hints[i]->cardTargets[asTc[1]] = parseBetween(hints[i]->partOfCombo[dPart],"targeting(",")")[1]; } asTc = parseBetween(hints[i]->partOfCombo[dPart],"totalmananeeded(",")"); if(asTc.size()) { hints[i]->manaNeeded = asTc[1]; asTc.clear(); } } } }//we collect the peices of a combo on first run. for(unsigned int hPart = 0; hPart < hints[i]->hold.size(); hPart++) { hintTc = tfc.createTargetChooser(hints[i]->hold[hPart],card); if(hintTc && hintTc->canTarget(card,true) && hintTc->countValidTargets() <= hintTc->maxtargets) { forCombo = true; } SAFE_DELETE(hintTc); } } } return forCombo;//return forCombo that way all hints that are combos are predisected. }