Implemented Commander mode and rules, added Command Zone to game, added/fixed primitives, increased the major release version.

This commit is contained in:
valfieri
2020-12-06 20:11:51 +01:00
parent 6ef9ecc147
commit ced2c85076
33 changed files with 588 additions and 78 deletions
+133 -4
View File
@@ -1908,7 +1908,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
for (int i = 0; i < 2; i++)
{
Player * p = observer->players[i];
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay,p->game->stack,p->game->exile, p->game->reveal, p->game->sideboard };
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay,p->game->stack,p->game->exile, p->game->reveal, p->game->sideboard, p->game->commandzone };
if(a->getActionTc()->canTarget((Targetable*)p))
{
if(a->getActionTc()->maxtargets == 1)
@@ -1919,7 +1919,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
else
potentialTargets.push_back(p);
}
for (int j = 0; j < 6; j++)
for (int j = 0; j < 9; j++)
{
MTGGameZone * zone = playerZones[j];
for (int k = 0; k < zone->nb_cards; k++)
@@ -2395,8 +2395,8 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
}
}
MTGPlayerCards * playerZones = target->game;
MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack,playerZones->exile,playerZones->reveal, playerZones->sideboard };
for (int j = 0; j < 8; j++)
MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack,playerZones->exile,playerZones->reveal, playerZones->sideboard, playerZones->commandzone };
for (int j = 0; j < 9; j++)
{
MTGGameZone * zone = zones[j];
for (int k = 0; k < zone->nb_cards; k++)
@@ -3054,6 +3054,135 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
maxCost = pMana->getConvertedCost();
}
}
//play from commandzone
while ((card = cd.nextmatch(game->commandzone, card)))
{
if (!CanHandleCost(card->getManaCost(),card))
continue;
if (game->playRestrictions->canPutIntoZone(card, game->stack) == PlayRestriction::CANT_PLAY)
continue;
if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name))
continue;
if(hints && hints->HintSaysItsForCombo(observer,card))
{
if(hints->canWeCombo(observer,card,this))
{
AbilityFactory af(observer);
int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions());
if(!canPlay)
continue;
nextCardToPlay = card;
gotPayments.clear();
if((!pMana->canAfford(nextCardToPlay->getManaCost()) || nextCardToPlay->getManaCost()->getKicker()))
gotPayments = canPayMana(nextCardToPlay,nextCardToPlay->getManaCost());
return activateCombo();
}
else
{
nextCardToPlay = NULL;
continue;
}
}
int currentCost = card->getManaCost()->getConvertedCost();
int hasX = card->getManaCost()->hasX();
gotPayments.clear();
if((!pMana->canAfford(card->getManaCost()) || card->getManaCost()->getKicker()))
gotPayments = canPayMana(card,card->getManaCost());
//for preformence reason we only look for specific mana if the payment couldn't be made with pmana.
if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(card->getManaCost())))
{
TargetChooserFactory tcf(observer);
TargetChooser * tc = tcf.createTargetChooser(card);
int shouldPlayPercentage = 0;
if (tc)
{
int hasTarget = chooseTarget(tc,NULL,NULL,true);
if(
(tc->maxtargets > hasTarget && tc->maxtargets > 1 && !tc->targetMin && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS) ||//target=<3>creature
(tc->maxtargets == TargetChooser::UNLITMITED_TARGETS && hasTarget < 1)//target=creatures
)
hasTarget = 0;
if (!hasTarget)//single target covered here.
{
SAFE_DELETE(tc);
continue;
}
shouldPlayPercentage = 90;
if(tc->targetMin && hasTarget < tc->maxtargets)
shouldPlayPercentage = 0;
if(tc->maxtargets > 1 && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS && hasTarget <= tc->maxtargets)
{
int maxA = hasTarget-tc->maxtargets;
shouldPlayPercentage += (10*maxA);//reduce the chances of playing multitarget if we are not above max targets.
}
if(tc->maxtargets == TargetChooser::UNLITMITED_TARGETS)
{
shouldPlayPercentage = 40 + (10*hasTarget);
int totalCost = pMana->getConvertedCost()-currentCost;
int totalTargets = hasTarget+hasTarget;
if(hasX && totalCost <= totalTargets)// {x} spell with unlimited targeting tend to divide damage, we want atleast 1 damage per target before casting.
{
shouldPlayPercentage = 0;
}
}
SAFE_DELETE(tc);
}
else
{
int shouldPlay = effectBadOrGood(card);
if (shouldPlay == BAKA_EFFECT_GOOD) {
shouldPlayPercentage = 90;
}
else if (BAKA_EFFECT_DONTKNOW == shouldPlay) {
//previously shouldPlayPercentage = 80;, I found this a little to high
//for cards which AI had no idea how to use.
shouldPlayPercentage = 60;
}
else {
// shouldPlay == baka_effect_bad giving it a 10 for odd ball lottery chance.
shouldPlayPercentage = 10;
}
}
//Reduce the chances of playing a spell with X cost if available mana is low
if (hasX)
{
int xDiff = pMana->getConvertedCost() - currentCost;
if (xDiff < 0)
xDiff = 0;
shouldPlayPercentage = shouldPlayPercentage - static_cast<int> ((shouldPlayPercentage * 1.9f) / (1 + xDiff));
}
if(card->getManaCost() && card->getManaCost()->getKicker() && card->getManaCost()->getKicker()->isMulti)
{
shouldPlayPercentage = 10* size_t(gotPayments.size())/int(1+(card->getManaCost()->getConvertedCost()+card->getManaCost()->getKicker()->getConvertedCost()));
if(shouldPlayPercentage <= 10)
shouldPlayPercentage = shouldPlayPercentage/3;
}
DebugTrace("Should I play from commandzone" << (card ? card->name : "Nothing" ) << "?" << endl
<<"shouldPlayPercentage = "<< shouldPlayPercentage);
if(card->getRestrictions().size())
{
AbilityFactory af(observer);
int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions());
if(!canPlay)
continue;
}
int randomChance = randomGenerator.random();
int chance = randomChance % 100;
if (chance > shouldPlayPercentage)
continue;
if(shouldPlayPercentage <= 10)
{
DebugTrace("shouldPlayPercentage was less than 10 this was a lottery roll on RNG");
}
nextCardToPlay = card;
maxCost = currentCost;
if (hasX)
maxCost = pMana->getConvertedCost();
}
}
if(nextCardToPlay)
{
if(!pMana->canAfford(nextCardToPlay->getManaCost()) || nextCardToPlay->getManaCost()->getKicker())
+2 -2
View File
@@ -1152,10 +1152,10 @@ int AAAlterMonarch::resolve()
{
if(!pTarget->monarch){
pTarget->monarch = 1;
pTarget->opponent()->monarch = 0;
pTarget->opponent()->monarch = 0;
WEvent * e = NEW WEventplayerMonarch(pTarget);
game->receiveEvent(e);
}
}
}
}
return 0;
+4
View File
@@ -256,6 +256,8 @@ int Damage::resolve()
else
{
((MTGCardInstance*)source)->damageToOpponent = true;
if(((MTGCardInstance*)source)->basicAbilities[Constants::ISCOMMANDER])
((MTGCardInstance*)source)->damageInflictedAsCommander += damage;
}
target->lifeLostThisTurn += damage;
if ( typeOfDamage == 1 && target == source->controller()->opponent() )//add vector prowledtypes.
@@ -271,6 +273,8 @@ int Damage::resolve()
}
WEvent * lifed = NEW WEventLife((Player*)target,-damage, source);
observer->receiveEvent(lifed);
if(((MTGCardInstance*)source)->damageInflictedAsCommander > 20) // if a Commander has dealt 21 or more damages to a player, he loose game.
observer->setLoser(((MTGCardInstance*)source)->controller()->opponent());
}
}
+2
View File
@@ -1346,6 +1346,8 @@ void GameObserver::ButtonPressed(PlayGuiObject * target)
graveyard->toggleDisplay();
else if (GuiExile* exile = dynamic_cast<GuiExile*>(target))
exile->toggleDisplay();
else if (GuiCommandZone* commandzone = dynamic_cast<GuiCommandZone*>(target))
commandzone->toggleDisplay();
//opponenthand
else if (GuiOpponentHand* opponentHand = dynamic_cast<GuiOpponentHand*>(target))
if (opponentHand->showCards)
+30 -15
View File
@@ -16,6 +16,8 @@ GuiAvatars::GuiAvatars(DuelLayers* duelLayers) :
Add(selfLibrary = NEW GuiLibrary(SCREEN_WIDTH - GuiAvatar::Width - GuiGameZone::Width / 2 - 11, SCREEN_HEIGHT - GuiAvatar::Height - 5 + GuiGameZone::Height + 5, false, mpDuelLayers->getRenderedPlayer(), this));
//myexile
Add(selfExile = NEW GuiExile(SCREEN_WIDTH - GuiAvatar::Width - GuiGameZone::Width / 2 - 11, SCREEN_HEIGHT - GuiAvatar::Height - 30, false, mpDuelLayers->getRenderedPlayer(), this));
//mycommandZone
Add(selfCommandZone = NEW GuiCommandZone(SCREEN_WIDTH - GuiAvatar::Width - GuiGameZone::Width / 2 + 9, SCREEN_HEIGHT - GuiAvatar::Height - 30, false, mpDuelLayers->getRenderedPlayer(), this));
Add(opponent = NEW GuiAvatar(0, 0, false, mpDuelLayers->getRenderedPlayerOpponent(), GuiAvatar::TOP_LEFT, this));
opponent->zoom = 0.9f;
@@ -29,19 +31,24 @@ GuiAvatars::GuiAvatars(DuelLayers* duelLayers) :
Add(opponentHand = NEW GuiOpponentHand(-15 + GuiAvatar::Width * 1.4 - GuiGameZone::Width / 2, 43 + GuiGameZone::Height - 10, false,
mpDuelLayers->getRenderedPlayerOpponent(), this));
//opponentLibrary
Add(opponentLibrary = NEW GuiLibrary(-30 + GuiAvatar::Width * 1.2 - GuiGameZone::Width / 2, 43 + GuiGameZone::Height - 10,
false, mpDuelLayers->getRenderedPlayerOpponent(), this));
Add(opponentLibrary = NEW GuiLibrary(-30 + GuiAvatar::Width * 1.2 - GuiGameZone::Width / 2, 43 + GuiGameZone::Height - 10, false,
mpDuelLayers->getRenderedPlayerOpponent(), this));
//opponentCommandZone
Add(opponentCommandZone = NEW GuiCommandZone(5 + GuiAvatar::Width * 1.4 - GuiGameZone::Width / 2, 43 + GuiGameZone::Height -10, false,
mpDuelLayers->getRenderedPlayerOpponent(), this));
observer->getCardSelector()->Add(self);
observer->getCardSelector()->Add(selfGraveyard);
observer->getCardSelector()->Add(selfExile);
observer->getCardSelector()->Add(selfCommandZone);
observer->getCardSelector()->Add(selfLibrary);
observer->getCardSelector()->Add(opponent);
observer->getCardSelector()->Add(opponentGraveyard);
observer->getCardSelector()->Add(opponentExile);
observer->getCardSelector()->Add(opponentCommandZone);
observer->getCardSelector()->Add(opponentLibrary);
observer->getCardSelector()->Add(opponentHand);
selfGraveyard->alpha = selfExile->alpha = opponentExile->alpha = selfLibrary->alpha = opponentGraveyard->alpha = opponentLibrary->alpha = opponentHand->alpha = 0;
selfGraveyard->alpha = selfExile->alpha = selfCommandZone->alpha = opponentCommandZone->alpha = opponentExile->alpha = selfLibrary->alpha = opponentGraveyard->alpha = opponentLibrary->alpha = opponentHand->alpha = 0;
}
float GuiAvatars::LeftBoundarySelf()
@@ -58,15 +65,15 @@ void GuiAvatars::Activate(PlayGuiObject* c)
c->zoom = 1.2f;
c->mHasFocus = true;
if ((opponentGraveyard == c) || (opponentExile == c) || (opponentLibrary == c) || (opponent == c) || (opponentHand == c))
if ((opponentGraveyard == c) || (opponentExile == c) || (opponentCommandZone == c) || (opponentLibrary == c) || (opponent == c) || (opponentHand == c))
{
opponentGraveyard->alpha = opponentExile->alpha = opponentLibrary->alpha = opponentHand->alpha = 128.0f;
opponentGraveyard->alpha = opponentExile->alpha = opponentCommandZone->alpha = opponentLibrary->alpha = opponentHand->alpha = 128.0f;
active = opponent;
opponent->zoom = 1.2f;
}
else if ((selfGraveyard == c) || (selfExile == c) || (selfLibrary == c) || (self == c))
else if ((selfGraveyard == c) || (selfExile == c) || (selfCommandZone == c) || (selfLibrary == c) || (self == c))
{
selfGraveyard->alpha = selfExile->alpha = selfLibrary->alpha = 128.0f;
selfGraveyard->alpha = selfExile->alpha = selfCommandZone->alpha = selfLibrary->alpha = 128.0f;
self->zoom = 1.0f;
active = self;
}
@@ -77,15 +84,15 @@ void GuiAvatars::Deactivate(PlayGuiObject* c)
{
c->zoom = 1.0;
c->mHasFocus = false;
if ((opponentGraveyard == c) || (opponentExile == c) || (opponentLibrary == c) || (opponentHand == c) || (opponent == c))
if ((opponentGraveyard == c) || (opponentExile == c) || (opponentCommandZone == c) || (opponentLibrary == c) || (opponentHand == c) || (opponent == c))
{
opponentGraveyard->alpha = opponentExile->alpha = opponentLibrary->alpha = opponentHand->alpha = 0;
opponentGraveyard->alpha = opponentExile->alpha = opponentCommandZone->alpha = opponentLibrary->alpha = opponentHand->alpha = 0;
opponent->zoom = 0.9f;
active = NULL;
}
else if ((selfGraveyard == c) || (selfExile == c) || (selfLibrary == c) || (self == c))
else if ((selfGraveyard == c) || (selfExile == c) || (selfCommandZone == c) || (selfLibrary == c) || (self == c))
{
selfGraveyard->alpha = selfExile->alpha = selfLibrary->alpha = 0;
selfGraveyard->alpha = selfExile->alpha = selfCommandZone->alpha = selfLibrary->alpha = 0;
self->zoom = 0.5f;
active = NULL;
}
@@ -93,15 +100,17 @@ void GuiAvatars::Deactivate(PlayGuiObject* c)
int GuiAvatars::receiveEventPlus(WEvent* e)
{
return selfGraveyard->receiveEventPlus(e) | selfExile->receiveEventPlus(e) | opponentExile->receiveEventPlus(e) | opponentGraveyard->receiveEventPlus(e) | opponentHand->receiveEventPlus(e);
return selfGraveyard->receiveEventPlus(e) | selfExile->receiveEventPlus(e) | selfCommandZone->receiveEventPlus(e) | opponentExile->receiveEventPlus(e) | opponentCommandZone->receiveEventPlus(e) | opponentGraveyard->receiveEventPlus(e) | opponentHand->receiveEventPlus(e);
}
int GuiAvatars::receiveEventMinus(WEvent* e)
{
selfGraveyard->receiveEventMinus(e);
selfExile->receiveEventMinus(e);
selfCommandZone->receiveEventMinus(e);
opponentGraveyard->receiveEventMinus(e);
opponentExile->receiveEventMinus(e);
opponentCommandZone->receiveEventMinus(e);
opponentHand->receiveEventMinus(e);
return 1;
}
@@ -116,10 +125,14 @@ bool GuiAvatars::CheckUserInput(JButton key)
return true;
if (selfExile->CheckUserInput(key))
return true;
if (selfCommandZone->CheckUserInput(key))
return true;
if (opponentGraveyard->CheckUserInput(key))
return true;
if (opponentExile->CheckUserInput(key))
return true;
if (opponentCommandZone->CheckUserInput(key))
return true;
if (opponentHand->CheckUserInput(key))
return true;
if (selfLibrary->CheckUserInput(key))
@@ -135,9 +148,11 @@ void GuiAvatars::Update(float dt)
opponent->Update(dt);
selfGraveyard->Update(dt);
selfExile->Update(dt);
selfCommandZone->Update(dt);
opponentHand->Update(dt);
opponentGraveyard->Update(dt);
opponentExile->Update(dt);
opponentCommandZone->Update(dt);
selfLibrary->Update(dt);
opponentLibrary->Update(dt);
}
@@ -150,12 +165,12 @@ void GuiAvatars::Render()
if (opponent == active)
{
r->FillRect(opponent->actX, opponent->actY, 40 * opponent->actZ, h+25 * opponent->actZ, ARGB(200,0,0,0));
r->FillRect(opponent->actX, opponent->actY, w * opponent->actZ, h * opponent->actZ, ARGB(200,0,0,0));
r->FillRect(opponent->actX, opponent->actY, w * opponent->actZ, h+25 * opponent->actZ, ARGB(200,0,0,0));
}
else if (self == active)
{
r->FillRect(self->actX - w * self->actZ - 4.5f, self->actY - h-28 * self->actZ, 24 * self->actZ, h+28 * self->actZ, ARGB(200,0,0,0));
r->FillRect(self->actX - w * self->actZ - 4.5f, self->actY - h * self->actZ, w * self->actZ, h * self->actZ, ARGB(200,0,0,0));
r->FillRect(self->actX - w * self->actZ - 4.5f, self->actY - h-28 * self->actZ, 24 * self->actZ + 19, h+28 * self->actZ, ARGB(200,0,0,0));
//r->FillRect(self->actX - w * self->actZ - 4.5f, self->actY - h * self->actZ, w * self->actZ, h * self->actZ, ARGB(200,0,0,0));
}
GuiLayer::Render();
+57 -2
View File
@@ -207,7 +207,7 @@ void GuiGameZone::Render()
bool showopponenttop = (zone && zone->owner->opponent()->game->battlefield->nb_cards && zone->owner->opponent()->game->battlefield->hasAbility(Constants::SHOWOPPONENTTOPLIBRARY))?true:false;
quad->SetColor(ARGB((int)(actA),255,255,255));
if(type == GUI_EXILE)
if(type == GUI_EXILE || type == GUI_COMMANDZONE)
{
quad->SetColor(ARGB((int)(actA),255,240,255));
}
@@ -217,7 +217,8 @@ void GuiGameZone::Render()
JQuadPtr iconhand = WResourceManager::Instance()->RetrieveTempQuad("iconhand.png");
JQuadPtr iconlibrary = WResourceManager::Instance()->RetrieveTempQuad("iconlibrary.png");
JQuadPtr iconexile = WResourceManager::Instance()->RetrieveTempQuad("iconexile.png");
JQuadPtr iconcommandzone = WResourceManager::Instance()->RetrieveTempQuad("iconcommandzone.png");
if(iconlibrary && type == GUI_LIBRARY)
{
scale2 = defaultHeight / iconlibrary->mHeight;
@@ -250,6 +251,14 @@ void GuiGameZone::Render()
iconexile->SetColor(ARGB((int)(actA),255,255,255));
quad = iconexile;
}
if(iconcommandzone && type == GUI_COMMANDZONE)
{
scale2 = defaultHeight / iconcommandzone->mHeight;
modx = -0.f;
mody = -2.f;
iconcommandzone->SetColor(ARGB((int)(actA),255,255,255));
quad = iconcommandzone;
}
//
if(type == GUI_LIBRARY && zone->nb_cards && !showCards)
@@ -520,6 +529,52 @@ ostream& GuiExile::toString(ostream& out) const
return out << "GuiExile :::";
}
GuiCommandZone::GuiCommandZone(float x, float y, bool hasFocus, Player * player, GuiAvatars* parent) :
GuiGameZone(x, y, hasFocus, player->game->commandzone, parent), player(player)
{
type = GUI_COMMANDZONE;
}
int GuiCommandZone::receiveEventPlus(WEvent* e)
{
if (WEventZoneChange* event = dynamic_cast<WEventZoneChange*>(e))
if (event->to == zone)
{
CardView* t;
if (event->card->view)
t = NEW CardView(CardView::nullZone, event->card, *(event->card->view));
else
t = NEW CardView(CardView::nullZone, event->card, x, y);
t->x = x + Width / 2;
t->y = y + Height / 2;
t->zoom = 0.6f;
t->alpha = 0;
cards.push_back(t);
return 1;
}
return 0;
}
int GuiCommandZone::receiveEventMinus(WEvent* e)
{
if (WEventZoneChange* event = dynamic_cast<WEventZoneChange*>(e))
if (event->from == zone)
for (vector<CardView*>::iterator it = cards.begin(); it != cards.end(); ++it)
if (event->card->previous == (*it)->card)
{
CardView* cv = *it;
cards.erase(it);
zone->owner->getObserver()->mTrash->trash(cv);
return 1;
}
return 0;
}
ostream& GuiCommandZone::toString(ostream& out) const
{
return out << "GuiCommandZone :::";
}
//opponenthand begins
GuiOpponentHand::GuiOpponentHand(float x, float y, bool hasFocus, Player * player, GuiAvatars* parent) :
GuiGameZone(x, y, hasFocus, player->game->hand, parent), player(player)
+4 -4
View File
@@ -6506,8 +6506,8 @@ void ListMaintainerAbility::updateTargets()
for (int i = 0; i < 2; i++)
{
Player * p = game->players[i];
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile ,p->game->reveal, p->game->sideboard };
for (int k = 0; k < 8; k++)
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile ,p->game->reveal, p->game->sideboard, p->game->commandzone };
for (int k = 0; k < 9; k++)
{
MTGGameZone * zone = zones[k];
if (canTarget(zone))
@@ -6578,8 +6578,8 @@ void ListMaintainerAbility::checkTargets()
for (int i = 0; i < 2; i++)
{
Player * p = game->players[i];
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile, p->game->reveal, p->game->sideboard };
for (int k = 0; k < 8; k++)
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->stack, p->game->exile, p->game->reveal, p->game->sideboard, p->game->commandzone };
for (int k = 0; k < 9; k++)
{
MTGGameZone * zone = zones[k];
if (canTarget(zone))
+2
View File
@@ -238,6 +238,8 @@ void MTGCardInstance::initMTGCI()
sunburst = 0;
equipment = 0;
mutation = 0;
damageInflictedAsCommander = 0;
numofcastfromcommandzone = 0;
auras = 0;
combatdamageToOpponent = false;
damageToOpponent = false;
+68 -2
View File
@@ -887,10 +887,76 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on
meta_unlockRequirements = s.substr(found + 7);
continue;
}
found = s.find("SB:");
found = s.find("SB:"); // Now it's possible to add cards to Sideboard even using their Name instead of ID such as normal deck cards.
if (found != string::npos)
{
Sideboard.push_back(s.substr(found + 3));
s = s.substr(found + 3);
s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1);
s.erase(0, s.find_first_not_of("\t\n\v\f\r "));
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
if(!s.empty() && it == s.end())
Sideboard.push_back(s);
else {
int numberOfCopies = 1;
size_t found = s.find(" *");
if (found != string::npos){
numberOfCopies = atoi(s.substr(found + 2).c_str());
s = s.substr(0, found);
}
MTGCard * card = database->getCardByName(s);
if (card){
for (int i = 0; i < numberOfCopies; i++){
std::stringstream str_id;
str_id << card->getId();
Sideboard.push_back(str_id.str());
}
}else {
DebugTrace("could not add to Sideboard any card with name: " << s);
}
}
continue;
}
found = s.find("CMD:"); // Now it's possible to add a card to Command Zone even using their Name instead of ID such as normal deck cards.
if (found != string::npos)
{
s = s.substr(found + 4);
s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1);
s.erase(0, s.find_first_not_of("\t\n\v\f\r "));
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
if(!s.empty() && it == s.end()){
MTGCard * newcard = database->getCardById(atoi(s.c_str()));
if(!CommandZone.size() && newcard->data->hasType("Legendary") && (newcard->data->hasType("Creature") || newcard->data->basicAbilities[Constants::CANBECOMMANDER])) // If no commander has been added you can add one.
CommandZone.push_back(s);
else if(CommandZone.size() == 1 && newcard->data->hasType("Legendary") && (newcard->data->hasType("Creature") || newcard->data->basicAbilities[Constants::CANBECOMMANDER])){ // If a commander has been added you can add a new one just if both have partner ability.
if(newcard && newcard->data->basicAbilities[Constants::PARTNER]){
MTGCard * oldcard = database->getCardById(atoi((CommandZone.at(0)).c_str()));
if(oldcard && oldcard->data->basicAbilities[Constants::PARTNER] && oldcard->data->name != newcard->data->name)
CommandZone.push_back(s);
}
}
}else {
size_t found = s.find(" *");
if (found != string::npos)
s = s.substr(0, found);
MTGCard * newcard = database->getCardByName(s);
if (newcard){
std::stringstream str_id;
str_id << newcard->getId();
if(!CommandZone.size() && newcard->data->hasType("Legendary") && (newcard->data->hasType("Creature") || newcard->data->basicAbilities[Constants::CANBECOMMANDER])) // If no commander has been added you can add one.
CommandZone.push_back(str_id.str());
else if(CommandZone.size() == 1 && newcard->data->hasType("Legendary") && (newcard->data->hasType("Creature") || newcard->data->basicAbilities[Constants::CANBECOMMANDER])){ // If a commander has been added you can add a new one just if both have partner ability.
if(newcard->data->basicAbilities[Constants::PARTNER]){
MTGCard * oldcard = database->getCardById(atoi((CommandZone.at(0)).c_str()));
if(oldcard && oldcard->data->basicAbilities[Constants::PARTNER] && oldcard->data->name != newcard->data->name)
CommandZone.push_back(str_id.str());
}
}
}else {
DebugTrace("could not add to CommandZone any card with name: " << s);
}
}
continue;
}
continue;
+4 -2
View File
@@ -194,8 +194,10 @@ const char* Constants::MTGBasicAbilities[] = {
"mentor",
"prowess",
"nofizzle alternative", //No fizzle if card has been paid with alternative cost.
"hasotherkicker", //Kicker cost is expressed with "other" keyword (es. not mana kicker such as life and/or tap a creature),
"partner" //Has partner ability
"hasotherkicker", //Kicker cost is expressed with "other" keyword (eg. not mana kicker such as life and/or tap a creature),
"partner", //Has partner ability
"canbecommander", //Can be a commander (eg. some planeswalkers can)
"iscommander" //It's the current commander
};
map<string,int> Constants::MTGBasicAbilitiesMap;
+62 -2
View File
@@ -78,6 +78,22 @@ void MTGPlayerCards::initDeck(MTGDeck * deck)
}
}
}
//commander zone init
if(deck->CommandZone.size())
{
for(unsigned int j = 0; j < deck->CommandZone.size(); j++)
{
string cardID = deck->CommandZone[j];
MTGCard * card = MTGCollection()->getCardById(atoi(cardID.c_str()));
if(card)
{
MTGCardInstance * newCard = NEW MTGCardInstance(card, this);
//commander zone
newCard->basicAbilities[Constants::ISCOMMANDER] = 1;
commandzone->addCard(newCard);
}
}
}
}
MTGPlayerCards::~MTGPlayerCards()
@@ -91,6 +107,7 @@ MTGPlayerCards::~MTGPlayerCards()
SAFE_DELETE(garbage);
SAFE_DELETE(reveal);
SAFE_DELETE(sideboard);
SAFE_DELETE(commandzone);
SAFE_DELETE(temp);
SAFE_DELETE(playRestrictions);
}
@@ -110,6 +127,7 @@ void MTGPlayerCards::beforeBeginPhase()
garbage->beforeBeginPhase();
reveal->beforeBeginPhase();
sideboard->beforeBeginPhase();
commandzone->beforeBeginPhase();
temp->beforeBeginPhase();
}
@@ -126,6 +144,7 @@ void MTGPlayerCards::setOwner(Player * player)
garbageLastTurn->setOwner(player);
reveal->setOwner(player);
sideboard->setOwner(player);
commandzone->setOwner(player);
temp->setOwner(player);
}
@@ -301,6 +320,7 @@ void MTGPlayerCards::init()
garbageLastTurn = garbage;
reveal = NEW MTGGameZone();
sideboard = NEW MTGGameZone();
commandzone = NEW MTGGameZone();
temp = NEW MTGGameZone();
playRestrictions = NEW PlayRestrictions();
@@ -393,7 +413,7 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
}
//close the currently open MAIN display.
if (from == g->players[i]->game->library || from == g->players[i]->game->graveyard || from == g->players[i]->game->exile)
if (from == g->players[i]->game->library || from == g->players[i]->game->graveyard || from == g->players[i]->game->exile || from == g->players[i]->game->commandzone)
{
if (g->guiOpenDisplay)
{
@@ -418,6 +438,12 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
inplaytoinplay = true;//try sending different event...
}
//Increase the number of time this card has been casted from commandzone to recalculate cost.
if(from == g->players[0]->game->commandzone || from == g->players[1]->game->commandzone){
card->numofcastfromcommandzone++;
card->controller()->numOfCommandCast++;
}
if (!(copy = from->removeCard(card, doCopy)))
return NULL; //ERROR
@@ -430,6 +456,12 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
}
}
//Commander is going back to Command Zone, so we recalculate cost according to how many times it has been casted from there.
if(to == g->players[0]->game->commandzone || to == g->players[1]->game->commandzone){
for(int i = 0; i < copy->numofcastfromcommandzone; i++)
copy->getManaCost()->add(Constants::MTG_COLOR_ARTIFACT,2);
}
if (card->miracle)
{
copy->miracle = true;
@@ -713,6 +745,9 @@ MTGCardInstance * MTGGameZone::removeCard(MTGCardInstance * card, int createCopy
copy->storedSourceCard = card->storedSourceCard;
copy->lastController = card->controller();
copy->previousController = card->controller();
copy->basicAbilities[Constants::ISCOMMANDER] = card->basicAbilities[Constants::ISCOMMANDER];
copy->damageInflictedAsCommander = card->damageInflictedAsCommander;
copy->numofcastfromcommandzone = card->numofcastfromcommandzone;
for (int i = 0; i < ManaCost::MANA_PAID_WITH_BESTOW +1; i++)
copy->alternateCostPaid[i] = card->alternateCostPaid[i];
@@ -1237,6 +1272,13 @@ MTGGameZone * MTGGameZone::intToZone(int zoneId, Player * p, Player * p2)
case SIDEBOARD:
return p->game->sideboard;
case MY_COMMANDZONE:
return p->game->commandzone;
case OPPONENT_COMMANDZONE:
return p->opponent()->game->commandzone;
case COMMANDZONE:
return p->game->commandzone;
}
if (!p2) return NULL;
switch (zoneId)
@@ -1265,6 +1307,9 @@ MTGGameZone * MTGGameZone::intToZone(int zoneId, Player * p, Player * p2)
case TARGET_CONTROLLER_SIDEBOARD:
return p2->game->sideboard;
case TARGET_CONTROLLER_COMMANDZONE:
return p2->game->commandzone;
default:
return NULL;
}
@@ -1385,6 +1430,17 @@ MTGGameZone * MTGGameZone::intToZone(GameObserver *g, int zoneId, MTGCardInstanc
return source->playerTarget->game->sideboard;
else return source->controller()->game->sideboard;
case TARGET_OWNER_COMMANDZONE:
return target->owner->game->commandzone;
case COMMANDZONE:
return target->owner->game->commandzone;
case OWNER_COMMANDZONE:
return target->owner->game->commandzone;
case TARGETED_PLAYER_COMMANDZONE:
if (source->playerTarget)
return source->playerTarget->game->commandzone;
else return source->controller()->game->commandzone;
default:
return NULL;
}
@@ -1416,6 +1472,8 @@ int MTGGameZone::zoneStringToId(string zoneName)
"mysideboard", "opponentsideboard", "targetownersideboard", "targetcontrollersideboard", "ownersideboard", "sideboard","targetedpersonssideboard",
"mycommandzone", "opponentcommandzone", "targetownercommandzone", "targetcontrollercommandzone", "ownercommandzone", "commandzone","targetedpersonscommandzone",
};
int values[] = { MY_GRAVEYARD, OPPONENT_GRAVEYARD, TARGET_OWNER_GRAVEYARD, TARGET_CONTROLLER_GRAVEYARD, OWNER_GRAVEYARD,
@@ -1439,7 +1497,9 @@ int MTGGameZone::zoneStringToId(string zoneName)
MY_REVEAL, OPPONENT_REVEAL, TARGET_OWNER_REVEAL, TARGET_CONTROLLER_REVEAL, OWNER_REVEAL, REVEAL,TARGETED_PLAYER_REVEAL,
MY_SIDEBOARD, OPPONENT_SIDEBOARD, TARGET_OWNER_SIDEBOARD, TARGET_CONTROLLER_SIDEBOARD, OWNER_SIDEBOARD, SIDEBOARD,TARGETED_PLAYER_SIDEBOARD };
MY_SIDEBOARD, OPPONENT_SIDEBOARD, TARGET_OWNER_SIDEBOARD, TARGET_CONTROLLER_SIDEBOARD, OWNER_SIDEBOARD, SIDEBOARD,TARGETED_PLAYER_SIDEBOARD,
MY_COMMANDZONE, OPPONENT_COMMANDZONE, TARGET_OWNER_COMMANDZONE, TARGET_CONTROLLER_COMMANDZONE, OWNER_COMMANDZONE, COMMANDZONE,TARGETED_PLAYER_COMMANDZONE };
int max = sizeof(values) / sizeof *(values);
+1 -1
View File
@@ -304,7 +304,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
int cardsinhand = game->players[0]->game->hand->nb_cards;
defaultPlayName = card->isLand()?"Play Land":"Cast Card Normally";
Player * player = game->currentlyActing();
if (!player->game->hand->hasCard(card) && !player->game->graveyard->hasCard(card) && !player->game->exile->hasCard(card) && !player->game->library->hasCard(card))
if (!player->game->hand->hasCard(card) && !player->game->graveyard->hasCard(card) && !player->game->exile->hasCard(card) && !player->game->library->hasCard(card) && !player->game->commandzone->hasCard(card))
return 0;
if ((player->game->library->hasCard(card) && !card->canPlayFromLibrary()) || (player->game->graveyard->hasCard(card) && !card->has(Constants::CANPLAYFROMGRAVEYARD)) || (player->game->exile->hasCard(card) && !card->has(Constants::CANPLAYFROMEXILE)))
return 0;
+1
View File
@@ -36,6 +36,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
drawCounter = 0;
energyCount = 0;
yidaroCount = 0;
numOfCommandCast = 0;
monarch = 0;
surveilOffset = 0;
epic = 0;
+4 -2
View File
@@ -598,20 +598,22 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
p->preventable = initState.playerData[i].player->preventable;
p->energyCount = initState.playerData[i].player->energyCount;
p->yidaroCount = initState.playerData[i].player->yidaroCount;
p->numOfCommandCast = initState.playerData[i].player->numOfCommandCast;
p->monarch = initState.playerData[i].player->monarch;
p->surveilOffset = initState.playerData[i].player->surveilOffset;
if (initState.playerData[i].player->mAvatarName.size())
{
p->mAvatarName = initState.playerData[i].player->mAvatarName;
}
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay, p->game->exile , p->game->reveal, p->game->sideboard };
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay, p->game->exile , p->game->reveal, p->game->sideboard, p->game->commandzone };
MTGGameZone * loadedPlayerZones[] = { initState.playerData[i].player->game->graveyard,
initState.playerData[i].player->game->library,
initState.playerData[i].player->game->hand,
initState.playerData[i].player->game->inPlay,
initState.playerData[i].player->game->exile,
initState.playerData[i].player->game->reveal,
initState.playerData[i].player->game->sideboard };
initState.playerData[i].player->game->sideboard,
initState.playerData[i].player->game->commandzone };
for (int j = 0; j < 5; j++)
{
MTGGameZone * zone = playerZones[j];
+20 -4
View File
@@ -175,6 +175,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
zones[nbzones++] = MTGGameZone::MY_SIDEBOARD;
zones[nbzones++] = MTGGameZone::OPPONENT_SIDEBOARD;
}
else if (zoneName.compare("commandzone") == 0)
{
zones[nbzones++] = MTGGameZone::MY_COMMANDZONE;
zones[nbzones++] = MTGGameZone::OPPONENT_COMMANDZONE;
}
else if (zoneName.compare("reveal") == 0)
{
zones[nbzones++] = MTGGameZone::MY_REVEAL;
@@ -210,6 +215,8 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
zones[nbzones++] = MTGGameZone::OPPONENT_HAND;
zones[nbzones++] = MTGGameZone::MY_EXILE;
zones[nbzones++] = MTGGameZone::OPPONENT_EXILE;
zones[nbzones++] = MTGGameZone::MY_COMMANDZONE;
zones[nbzones++] = MTGGameZone::OPPONENT_COMMANDZONE;
}
else if (zoneName.compare("stack") == 0)
{
@@ -228,6 +235,7 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
zones[nbzones++] = MTGGameZone::MY_HAND;
zones[nbzones++] = MTGGameZone::MY_EXILE;
zones[nbzones++] = MTGGameZone::MY_SIDEBOARD;
zones[nbzones++] = MTGGameZone::MY_COMMANDZONE;
}
else if (zoneName.compare("opponentcastingzone") == 0)
{
@@ -235,18 +243,22 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
zones[nbzones++] = MTGGameZone::OPPONENT_LIBRARY;
zones[nbzones++] = MTGGameZone::OPPONENT_HAND;
zones[nbzones++] = MTGGameZone::OPPONENT_EXILE;
zones[nbzones++] = MTGGameZone::OPPONENT_SIDEBOARD;
zones[nbzones++] = MTGGameZone::OPPONENT_COMMANDZONE;
}
else if (zoneName.compare("mynonplaynonexile") == 0)
{
zones[nbzones++] = MTGGameZone::MY_GRAVEYARD;
zones[nbzones++] = MTGGameZone::MY_LIBRARY;
zones[nbzones++] = MTGGameZone::MY_HAND;
zones[nbzones++] = MTGGameZone::MY_COMMANDZONE;
}
else if (zoneName.compare("opponentnonplaynonexile") == 0)
{
zones[nbzones++] = MTGGameZone::OPPONENT_GRAVEYARD;
zones[nbzones++] = MTGGameZone::OPPONENT_LIBRARY;
zones[nbzones++] = MTGGameZone::OPPONENT_HAND;
zones[nbzones++] = MTGGameZone::OPPONENT_COMMANDZONE;
}
else if (zoneName.compare("myzones") == 0)
{
@@ -256,6 +268,8 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
zones[nbzones++] = MTGGameZone::MY_LIBRARY;
zones[nbzones++] = MTGGameZone::MY_HAND;
zones[nbzones++] = MTGGameZone::MY_EXILE;
zones[nbzones++] = MTGGameZone::MY_SIDEBOARD;
zones[nbzones++] = MTGGameZone::MY_COMMANDZONE;
}
else if (zoneName.compare("opponentzones") == 0)
{
@@ -265,6 +279,8 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
zones[nbzones++] = MTGGameZone::OPPONENT_LIBRARY;
zones[nbzones++] = MTGGameZone::OPPONENT_HAND;
zones[nbzones++] = MTGGameZone::OPPONENT_EXILE;
zones[nbzones++] = MTGGameZone::OPPONENT_SIDEBOARD;
zones[nbzones++] = MTGGameZone::OPPONENT_COMMANDZONE;
}
else
{
@@ -1154,8 +1170,8 @@ bool TargetChooser::validTargetsExist(int maxTargets)
int maxAmount = 0;
Player *p = observer->players[i];
if (canTarget(p)) return true;
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack, p->game->reveal, p->game->sideboard };
for (int k = 0; k < 8; k++)
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack, p->game->reveal, p->game->sideboard, p->game->commandzone };
for (int k = 0; k < 9; k++)
{
MTGGameZone * z = zones[k];
if (targetsZone(z))
@@ -1188,8 +1204,8 @@ int TargetChooser::countValidTargets(bool withoutProtections)
Player *p = observer->players[i];
if(canTarget(p))
result++;
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack, p->game->reveal, p->game->sideboard };
for (int k = 0; k < 8; k++)
MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile, p->game->stack, p->game->reveal, p->game->sideboard, p->game->commandzone };
for (int k = 0; k < 9; k++)
{
MTGGameZone * z = zones[k];
if (targetsZone(z))