Erwan
- the AI can now use activated abilities (stupidly though...) - a few card bugfixes
This commit is contained in:
73
projects/mtg/bin/Res/ai/baka/deck16.txt
Normal file
73
projects/mtg/bin/Res/ai/baka/deck16.txt
Normal file
@@ -0,0 +1,73 @@
|
||||
#Black/White Deck 10E/RV
|
||||
#4x The hive
|
||||
135253
|
||||
135253
|
||||
135253
|
||||
135253
|
||||
#4x pestilence
|
||||
1172
|
||||
1172
|
||||
1172
|
||||
1172
|
||||
#4x Ancestor chosen
|
||||
130550
|
||||
130550
|
||||
130550
|
||||
130550
|
||||
#4x assassinate
|
||||
135194
|
||||
135194
|
||||
135194
|
||||
135194
|
||||
#4x bottle gnomes
|
||||
129495
|
||||
129495
|
||||
129495
|
||||
129495
|
||||
#4x Drudge skelettons
|
||||
129529
|
||||
129529
|
||||
129529
|
||||
129529
|
||||
#4x Glorious Anthem
|
||||
129572
|
||||
129572
|
||||
129572
|
||||
129572
|
||||
#4x Paladin en Vec
|
||||
129668
|
||||
129668
|
||||
129668
|
||||
129668
|
||||
#2 x Deathmark
|
||||
129910
|
||||
129910
|
||||
#2x Demistify
|
||||
129524
|
||||
129524
|
||||
#12 swamps
|
||||
129754
|
||||
129756
|
||||
129755
|
||||
129757
|
||||
129754
|
||||
129756
|
||||
129755
|
||||
129757
|
||||
129754
|
||||
129756
|
||||
129755
|
||||
129757
|
||||
#12x plains
|
||||
129680
|
||||
129681
|
||||
129682
|
||||
129683
|
||||
129680
|
||||
129681
|
||||
129682
|
||||
129683
|
||||
129680
|
||||
129681
|
||||
129682
|
||||
129683
|
||||
@@ -122,7 +122,7 @@ type=Creature
|
||||
subtype=Zombie
|
||||
power=2
|
||||
toughness=2
|
||||
abilites=swampwalk
|
||||
abilities=swampwalk
|
||||
[/card]
|
||||
[card]
|
||||
text=Swampwalk (This creature is unblockable as long as defending player controls a Swamp.)
|
||||
@@ -271,12 +271,12 @@ type=Instant
|
||||
[card]
|
||||
text=Return target sorcery card from your graveyard to your hand.
|
||||
target=sorcery|myGraveyard
|
||||
alias=1263
|
||||
auto=moveTo(myHand)
|
||||
id=4259
|
||||
name=Deja vu
|
||||
rarity=C
|
||||
mana={2}{B}
|
||||
type=sorcery
|
||||
type=Sorcery
|
||||
[/card]
|
||||
[card]
|
||||
text=Flying
|
||||
@@ -288,7 +288,7 @@ type=Creature
|
||||
subtype=Drake
|
||||
power=2
|
||||
toughness=2
|
||||
abilites=flying
|
||||
abilities=flying
|
||||
[/card]
|
||||
[card]
|
||||
text=Destroy all creatures and lands
|
||||
@@ -824,7 +824,7 @@ type=Creature
|
||||
subtype=Illusion Warrior
|
||||
power=2
|
||||
toughness=2
|
||||
abilites=unblockable
|
||||
abilities=unblockable
|
||||
[/card]
|
||||
[card]
|
||||
text={T}: Add {W} to your mana pool.
|
||||
@@ -872,7 +872,7 @@ type=Creature
|
||||
subtype=Illusion Warrior
|
||||
power=2
|
||||
toughness=2
|
||||
abilites=unblockable
|
||||
abilities=unblockable
|
||||
[/card]
|
||||
[card]
|
||||
text=Pyroclasm deals 2 damage to each creature.
|
||||
|
||||
@@ -1630,7 +1630,7 @@ name=Prodigal Sorcerer
|
||||
auto={T}:damage:1 target(creature,player)
|
||||
rarity=C
|
||||
type=Creature
|
||||
mana={2}{U}
|
||||
mana={U}
|
||||
power=1
|
||||
subtype=Human Wizard
|
||||
toughness=1
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "Player.h"
|
||||
|
||||
#include <queue>
|
||||
using std::queue;
|
||||
|
||||
#define INFO_NBCREATURES 0
|
||||
#define INFO_CREATURESPOWER 1
|
||||
@@ -16,13 +18,40 @@
|
||||
|
||||
class AIStats;
|
||||
|
||||
class AIAction{
|
||||
protected:
|
||||
int efficiency;
|
||||
public:
|
||||
MTGAbility * ability;
|
||||
Player * player;
|
||||
MTGCardInstance * click;
|
||||
MTGCardInstance * target; // TODO Improve
|
||||
AIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL):ability(a),click(c),target(t){player = NULL; efficiency = -1;};
|
||||
AIAction(MTGCardInstance * c, MTGCardInstance * t = NULL):click(c),target(t){player = NULL; ability = NULL; efficiency = -1;};
|
||||
AIAction(Player * p):player(p){ability = NULL; target = NULL; click = NULL; efficiency = -1;};
|
||||
int getEfficiency();
|
||||
int Act();
|
||||
|
||||
};
|
||||
|
||||
class CmpAbilities { // compares Abilities efficiency
|
||||
public:
|
||||
bool operator()(AIAction * a1, AIAction * a2) const {
|
||||
int e1 = a1->getEfficiency();
|
||||
int e2 = a2->getEfficiency();
|
||||
if (e1 == e2) return a1 > a2; //TODO improve
|
||||
return (e1 > e2);
|
||||
}
|
||||
};
|
||||
|
||||
class AIPlayer: public Player{
|
||||
protected:
|
||||
MTGCardInstance * nextCardToPlay;
|
||||
ManaCost * potentialMana;
|
||||
queue<AIAction *> clickstream;
|
||||
void tapLandsForMana(ManaCost * potentialMana, ManaCost * cost);
|
||||
int checkInterrupt();
|
||||
int combatDamages();
|
||||
int interruptIfICan();
|
||||
int chooseAttackers();
|
||||
int chooseBlockers();
|
||||
int effectBadOrGood(MTGCardInstance * card);
|
||||
@@ -30,7 +59,7 @@ class AIPlayer: public Player{
|
||||
AIStats * getStats();
|
||||
public:
|
||||
void End(){};
|
||||
virtual int displayStack(){return 0;};
|
||||
virtual int displayStack(){return 1;};
|
||||
AIStats * stats;
|
||||
ManaCost * getPotentialMana();
|
||||
AIPlayer(MTGPlayerCards * _deck, string deckFile);
|
||||
@@ -39,6 +68,9 @@ class AIPlayer: public Player{
|
||||
virtual int chooseTarget(TargetChooser * tc = NULL);
|
||||
virtual int Act(float dt);
|
||||
int isAI(){return 1;};
|
||||
int selectAbility();
|
||||
int createAbilityTargets(MTGAbility * a, MTGCardInstance * c, map<AIAction *, int,CmpAbilities> * ranking);
|
||||
int useAbility();
|
||||
|
||||
};
|
||||
|
||||
@@ -52,6 +84,7 @@ class AIPlayerBaka: public AIPlayer{
|
||||
AIPlayerBaka(MTGPlayerCards * _deck, char * deckFile, char * avatarFile);
|
||||
virtual int Act(float dt);
|
||||
void initTimer();
|
||||
int computeActions();
|
||||
};
|
||||
|
||||
class AIPlayerFactory{
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
|
||||
class MTGCardInstance;
|
||||
class ManaCost;
|
||||
class Targetable;
|
||||
class TargetChooser;
|
||||
class WEvent;
|
||||
@@ -37,9 +38,10 @@ class ActionElement: public JGuiObject{
|
||||
virtual int destroy(){return 0;};
|
||||
virtual bool CheckUserInput(u32 key){return false;};
|
||||
ActionElement(int id);
|
||||
virtual ~ActionElement();
|
||||
virtual int isReactingToTargetClick(Targetable * card);
|
||||
virtual int reactToTargetClick(Targetable * card);
|
||||
virtual int isReactingToClick(MTGCardInstance * card){return 0;};
|
||||
virtual int isReactingToClick(MTGCardInstance * card, ManaCost * man = NULL){return 0;};
|
||||
virtual int stillInUse(MTGCardInstance * card){return 0;};
|
||||
virtual int receiveEvent(WEvent * event){return 0;};
|
||||
virtual int reactToClick(MTGCardInstance * card){return 0;};
|
||||
|
||||
@@ -396,7 +396,7 @@ class ASpellCastLife:public MTGAbility{
|
||||
trigger.setColor(color);
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * _card){
|
||||
int isReactingToClick(MTGCardInstance * _card, ManaCost * mana = NULL){
|
||||
if (_card == source && game->currentlyActing()->game->inPlay->hasCard(source)){
|
||||
if (game->currentlyActing()->getManaPool()->canAfford(cost)){
|
||||
Interruptible * laststackitem = game->mLayers->stackLayer()->_(-1);
|
||||
@@ -430,7 +430,7 @@ class AUnBlocker:public MTGAbility{
|
||||
}
|
||||
|
||||
|
||||
int isReactingToClick(MTGCardInstance * _card){
|
||||
int isReactingToClick(MTGCardInstance * _card,ManaCost * mana = NULL){
|
||||
if (_card == target && game->currentlyActing()->game->inPlay->hasCard(source) && (MTGCardInstance *) _card->isTapped()){
|
||||
if (game->currentlyActing()->getManaPool()->canAfford(cost)){
|
||||
return 1;
|
||||
@@ -462,10 +462,10 @@ class AUntaperOnceDuringTurn:public AUnBlocker{
|
||||
AUnBlocker::Update(dt);
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
if (onlyPlayerTurn && game->currentPlayer!=source->controller()) return 0;
|
||||
if (untappedThisTurn) return 0;
|
||||
return AUnBlocker::isReactingToClick(card);
|
||||
return AUnBlocker::isReactingToClick(card,mana);
|
||||
}
|
||||
|
||||
int reactToClick(MTGCardInstance * card){
|
||||
@@ -578,8 +578,8 @@ class APowerToughnessModifierUntilEndOfTurn: public ActivatedAbility{
|
||||
return resolve();
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
if (!ActivatedAbility::isReactingToClick(card)) return 0;
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
if (!ActivatedAbility::isReactingToClick(card,mana)) return 0;
|
||||
return (!maxcounters || (counters < maxcounters));
|
||||
}
|
||||
|
||||
@@ -694,6 +694,7 @@ class AStandardRegenerate:public ActivatedAbility{
|
||||
public:
|
||||
AStandardRegenerate(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost):ActivatedAbility(_id,_source,_cost,0,0){
|
||||
target = _target;
|
||||
aType = MTGAbility::STANDARD_REGENERATE;
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
@@ -933,6 +934,7 @@ class ADamager:public TargetAbility{
|
||||
int damage;
|
||||
ADamager(int id, MTGCardInstance * card, ManaCost * _cost, int _damage, TargetChooser * _tc = NULL, int _tap = 1):TargetAbility(id,card, _tc, _cost,0,_tap),damage(_damage){
|
||||
if (!tc) tc = NEW DamageableTargetChooser(card);
|
||||
aType = MTGAbility::DAMAGER;
|
||||
}
|
||||
int resolve(){
|
||||
Damageable * _target = tc->getNextDamageableTarget();
|
||||
@@ -1271,7 +1273,7 @@ class AArmageddonClock:public MTGAbility{
|
||||
}
|
||||
}
|
||||
}
|
||||
int isReactingToClick(MTGCardInstance * _card){
|
||||
int isReactingToClick(MTGCardInstance * _card, ManaCost * mana = NULL){
|
||||
if (counters > 0 && _card == source && currentPhase == Constants::MTG_PHASE_UPKEEP){
|
||||
if (game->currentlyActing()->getManaPool()->canAfford( & cost)){
|
||||
return 1;
|
||||
@@ -1357,7 +1359,7 @@ class AClockworkBeast:public MTGAbility{
|
||||
}
|
||||
}
|
||||
}
|
||||
int isReactingToClick(MTGCardInstance * _card){
|
||||
int isReactingToClick(MTGCardInstance * _card, ManaCost * mana = NULL){
|
||||
if (counters < 7 && _card == source && currentPhase == Constants::MTG_PHASE_UPKEEP && game->currentPlayer->game->inPlay->hasCard(source)){
|
||||
if (game->currentlyActing()->getManaPool()->canAfford( & cost)){
|
||||
return 1;
|
||||
@@ -1423,7 +1425,7 @@ class AConservator: public MTGAbility{
|
||||
alterDamage();
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * _card){
|
||||
int isReactingToClick(MTGCardInstance * _card, ManaCost * mana = NULL){
|
||||
if ( _card == source && game->currentlyActing()->game->inPlay->hasCard(source) && !_card->isTapped()){
|
||||
if (game->currentlyActing()->getManaPool()->canAfford( & cost)){
|
||||
return 1;
|
||||
@@ -1560,8 +1562,8 @@ class AFarmstead:public ActivatedAbility{
|
||||
target = _target;
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
if (!ActivatedAbility::isReactingToClick(card)) return 0;
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
if (!ActivatedAbility::isReactingToClick(card,mana)) return 0;
|
||||
if (currentPhase == Constants::MTG_PHASE_UPKEEP) return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1605,7 +1607,7 @@ class AGlassesOfUrza:public MTGAbility{
|
||||
}
|
||||
|
||||
}
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
if ( card == source){
|
||||
if (game->currentlyActing()->game->isInPlay(card) && !source->isTapped()){
|
||||
return 1;
|
||||
@@ -1674,7 +1676,7 @@ class ALivingArtifact:public MTGAbility{
|
||||
}
|
||||
}
|
||||
|
||||
int isReactingtoclick(MTGCardInstance * card){
|
||||
int isReactingtoclick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
if (currentPhase == Constants::MTG_PHASE_UPKEEP && card == source && game->currentPlayer == source->controller() && counters && !usedThisTurn){
|
||||
return 1;
|
||||
}
|
||||
@@ -1709,9 +1711,9 @@ class ALordOfThePit: public TargetAbility{
|
||||
TargetAbility::Update(dt);
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
if (currentPhase != Constants::MTG_PHASE_UPKEEP || paidThisTurn) return 0;
|
||||
return TargetAbility::isReactingToClick(card);
|
||||
return TargetAbility::isReactingToClick(card,mana);
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
@@ -1867,9 +1869,9 @@ class AJandorsRing:public ActivatedAbility{
|
||||
cost->add(Constants::MTG_COLOR_ARTIFACT, 2);
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
if (!source->controller()->game->hand->hasCard(source->controller()->game->library->lastCardDrawn)) return 0;
|
||||
return ActivatedAbility::isReactingToClick(card);
|
||||
return ActivatedAbility::isReactingToClick(card,mana);
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
@@ -1909,7 +1911,7 @@ class AKudzu: public TargetAbility{
|
||||
TargetAbility::Update(dt);
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
MTGCardInstance * _target = (MTGCardInstance *)target;
|
||||
if (card == source && (!_target || !_target->isInPlay())){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
@@ -2073,7 +2075,7 @@ class APowerLeak:public TriggeredAbility{
|
||||
TriggeredAbility::Update(dt);
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
if (damagesToDealThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && card==source && _target->controller() == game->currentPlayer){
|
||||
if (game->currentPlayer->getManaPool()->canAfford(& cost)) return 1;
|
||||
@@ -2186,7 +2188,7 @@ class AScavengingGhoul:public MTGAbility{
|
||||
//TODO
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * _card){
|
||||
int isReactingToClick(MTGCardInstance * _card, ManaCost * mana = NULL){
|
||||
if (counters > 0 && _card == source && game->currentlyActing()->game->inPlay->hasCard(source)){
|
||||
return 1;
|
||||
}
|
||||
@@ -2391,8 +2393,8 @@ class AForceOfNature:public ActivatedAbility{
|
||||
ActivatedAbility::Update(dt);
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
return (dealDamageThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card));
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
return (dealDamageThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card,mana));
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
@@ -2509,7 +2511,7 @@ class AIslandSanctuary:public MTGAbility{
|
||||
}
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
if (card==source && game->currentPlayer == card->controller() && currentPhase == Constants::MTG_PHASE_DRAW){
|
||||
Interruptible * action = game->mLayers->stackLayer()->_(-1);
|
||||
if (action->type == ACTION_DRAW) return 1;
|
||||
@@ -2582,10 +2584,10 @@ class ASoulNet:public ActivatedAbility{
|
||||
newDead = latest;
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
newDead = ((PutInGraveyard *) GameObserver::GetInstance()->mLayers->stackLayer()->getPrevious(NULL,ACTION_PUTINGRAVEYARD,RESOLVED_OK));
|
||||
if (newDead && newDead != latest && newDead->card->isACreature())
|
||||
return ActivatedAbility::isReactingToClick(card);
|
||||
return ActivatedAbility::isReactingToClick(card,mana);
|
||||
return 0;
|
||||
}
|
||||
int resolve(){
|
||||
@@ -2624,8 +2626,8 @@ class AStasis:public ActivatedAbility{
|
||||
ActivatedAbility::Update(dt);
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
return (!paidThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card));
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
return (!paidThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card,mana));
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
@@ -2769,9 +2771,9 @@ class AMinionofLeshrac: public TargetAbility{
|
||||
TargetAbility::Update(dt);
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card){
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
|
||||
if (currentPhase != Constants::MTG_PHASE_UPKEEP || paidThisTurn) return 0;
|
||||
return TargetAbility::isReactingToClick(card);
|
||||
return TargetAbility::isReactingToClick(card,mana);
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
|
||||
@@ -37,14 +37,16 @@ class MTGAbility: public ActionElement{
|
||||
|
||||
GameObserver * game;
|
||||
public:
|
||||
ManaCost * cost;
|
||||
Damageable * target;
|
||||
int aType;
|
||||
MTGCardInstance * source;
|
||||
MTGAbility(int id, MTGCardInstance * card);
|
||||
MTGAbility(int id, MTGCardInstance * _source, Damageable * _target);
|
||||
virtual int testDestroy();
|
||||
virtual ~MTGAbility();
|
||||
virtual void Render(){};
|
||||
virtual int isReactingToClick(MTGCardInstance * card){return 0;};
|
||||
virtual int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){return 0;};
|
||||
virtual int reactToClick(MTGCardInstance * card){return 0;};
|
||||
virtual int receiveEvent(WEvent * event){return 0;};
|
||||
virtual void Update(float dt){};
|
||||
@@ -52,7 +54,15 @@ class MTGAbility: public ActionElement{
|
||||
virtual int stillInUse(MTGCardInstance * card){if (card==source) return 1; return 0;};
|
||||
virtual int resolve(){return 0;};
|
||||
|
||||
/*Poor man's casting */
|
||||
enum {
|
||||
UNKNOWN = 0,
|
||||
MANA_PRODUCER = 1,
|
||||
MTG_ATTACK_RULE = 2,
|
||||
DAMAGER = 3,
|
||||
STANDARD_REGENERATE = 4,
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -69,12 +79,11 @@ class TriggeredAbility:public MTGAbility{
|
||||
|
||||
class ActivatedAbility:public MTGAbility{
|
||||
public:
|
||||
ManaCost * cost;
|
||||
int playerturnonly;
|
||||
int needsTapping;
|
||||
ActivatedAbility(int id, MTGCardInstance * card,ManaCost * _cost = NULL, int _playerturnonly = 0,int tap = 1);
|
||||
virtual int reactToClick(MTGCardInstance * card);
|
||||
virtual int isReactingToClick(MTGCardInstance * card);
|
||||
virtual int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
||||
virtual int reactToTargetClick(Targetable * object);
|
||||
virtual int resolve() = 0;
|
||||
virtual ~ActivatedAbility();
|
||||
@@ -230,7 +239,7 @@ class AManaProducer: public MTGAbility{
|
||||
AManaProducer(int id, MTGCardInstance * card, ManaCost * _output, ManaCost * _cost = NULL, int doTap = 1 );
|
||||
void Update(float dt);
|
||||
void Render();
|
||||
int isReactingToClick(MTGCardInstance * _card);
|
||||
int isReactingToClick(MTGCardInstance * _card, ManaCost * mana = NULL);
|
||||
int resolve();
|
||||
int reactToClick(MTGCardInstance * _card);
|
||||
const char * getMenuText();
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
class MTGPutInPlayRule:public MTGAbility{
|
||||
public:
|
||||
int isReactingToClick(MTGCardInstance * card);
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
||||
int reactToClick(MTGCardInstance * card);
|
||||
int testDestroy();
|
||||
MTGPutInPlayRule(int _id);
|
||||
@@ -20,7 +20,7 @@ class MTGPutInPlayRule:public MTGAbility{
|
||||
|
||||
class MTGAttackRule:public MTGAbility{
|
||||
public:
|
||||
int isReactingToClick(MTGCardInstance * card);
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
||||
int reactToClick(MTGCardInstance * card);
|
||||
int testDestroy();
|
||||
MTGAttackRule(int _id);
|
||||
@@ -30,7 +30,7 @@ class MTGAttackRule:public MTGAbility{
|
||||
|
||||
class MTGBlockRule:public MTGAbility{
|
||||
public:
|
||||
int isReactingToClick(MTGCardInstance * card);
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
||||
int reactToClick(MTGCardInstance * card);
|
||||
int testDestroy();
|
||||
MTGBlockRule(int _id);
|
||||
|
||||
@@ -4,9 +4,28 @@
|
||||
#include "../include/DamageResolverLayer.h"
|
||||
#include "../include/DamagerDamaged.h"
|
||||
#include "../include/AIStats.h"
|
||||
#include "../include/AllAbilities.h"
|
||||
|
||||
const char * const MTG_LAND_TEXTS[] = {"artifact","forest","island","mountain","swamp","plains","other lands"};
|
||||
|
||||
int AIAction::Act(){
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
if (player){
|
||||
g->cardClick(NULL, player);
|
||||
return 1;
|
||||
}
|
||||
if (ability){
|
||||
ability->reactToClick(click);
|
||||
if (target) g->cardClick(target);
|
||||
return 1;
|
||||
}else if (click){ //Shouldn't be used, really...
|
||||
g->cardClick(click);
|
||||
if (target) g->cardClick(target);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
AIPlayer::AIPlayer(MTGPlayerCards * _deck, string file): Player(_deck, file){
|
||||
potentialMana = NEW ManaCost();
|
||||
nextCardToPlay = NULL;
|
||||
@@ -45,7 +64,7 @@ void AIPlayer::tapLandsForMana(ManaCost * potentialMana, ManaCost * cost){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("tapping land for mana\n");
|
||||
#endif
|
||||
|
||||
if (!cost) return;
|
||||
ManaCost * diff = potentialMana->Diff(cost);
|
||||
GameObserver * gameObs = GameObserver::GetInstance();
|
||||
CardDescriptor cd;
|
||||
@@ -64,7 +83,8 @@ void AIPlayer::tapLandsForMana(ManaCost * potentialMana, ManaCost * cost){
|
||||
}
|
||||
}
|
||||
if (doTap){
|
||||
gameObs->cardClick(card);
|
||||
AIAction * a = NEW AIAction(card);
|
||||
clickstream.push(a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,22 +121,140 @@ ManaCost * AIPlayer::getPotentialMana(){
|
||||
}
|
||||
|
||||
|
||||
//Default AI does not interrupt
|
||||
int AIPlayer::checkInterrupt(){
|
||||
GameObserver * gameObs = GameObserver::GetInstance();
|
||||
if (gameObs->mLayers->stackLayer()->askIfWishesToInterrupt == this){
|
||||
gameObs->mLayers->stackLayer()->cancelInterruptOffer();
|
||||
int AIAction::getEfficiency(){
|
||||
//TODO add multiplier according to what the player wants
|
||||
if (efficiency != -1) return efficiency;
|
||||
if (!ability) return 0;
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
ActionStack * s = g->mLayers->stackLayer();
|
||||
Player * p = g->currentlyActing();
|
||||
if (s->has(ability)) return 0;
|
||||
switch (ability->aType){
|
||||
case MTGAbility::DAMAGER:
|
||||
{
|
||||
ADamager * a = (ADamager *) ability;
|
||||
if ( p == target->controller()){
|
||||
efficiency = 0;
|
||||
}else if (a->damage >= target->toughness){
|
||||
efficiency = 100;
|
||||
}else if (target->toughness){
|
||||
efficiency = (100 * a->damage) / target->toughness;
|
||||
}else{
|
||||
efficiency = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MTGAbility::STANDARD_REGENERATE:
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *)(ability->target);
|
||||
PutInGraveyard * action = ((PutInGraveyard *) g->mLayers->stackLayer()->getNext(NULL,ACTION_PUTINGRAVEYARD,NOT_RESOLVED));
|
||||
int i = 0;
|
||||
while(action){
|
||||
i++;
|
||||
if (action->card == _target){
|
||||
efficiency = 95;
|
||||
action = NULL;
|
||||
}else{
|
||||
action = ((PutInGraveyard *) g->mLayers->stackLayer()->getNext(action,ACTION_PUTINGRAVEYARD,NOT_RESOLVED));
|
||||
}
|
||||
}
|
||||
char buf[4096];
|
||||
sprintf(buf,"Graveyard : %i\n", i);
|
||||
OutputDebugString(buf);
|
||||
if (efficiency == -1) efficiency = 0;
|
||||
break;
|
||||
}
|
||||
case MTGAbility::MANA_PRODUCER: //can't use mana producers right now :/
|
||||
efficiency = 0;
|
||||
break;
|
||||
default:
|
||||
if (target){
|
||||
efficiency = rand() % 5; //Small percentage of chance for other abilities
|
||||
}else{
|
||||
efficiency = rand() % 10;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return efficiency;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int AIPlayer::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, map<AIAction *, int, CmpAbilities> * ranking){
|
||||
if (!a->tc){
|
||||
AIAction * as = NEW AIAction(a,c,NULL);
|
||||
(*ranking)[as] = 1;
|
||||
return 1;
|
||||
}
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
for (int i = 0; i < 2; i++){
|
||||
Player * p = g->players[i];
|
||||
MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay};
|
||||
for (int j = 0; j < 4; j++){
|
||||
MTGGameZone * zone = playerZones[j];
|
||||
for (int k=0; k < zone->nb_cards; k++){
|
||||
MTGCardInstance * t = zone->cards[k];
|
||||
if (a->tc->canTarget(t)){
|
||||
|
||||
AIAction * as = NEW AIAction(a,c,t);
|
||||
(*ranking)[as] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AIPlayer::selectAbility(){
|
||||
map<AIAction *, int,CmpAbilities>ranking;
|
||||
list<int>::iterator it;
|
||||
ManaCost * pMana = getPotentialMana();
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish
|
||||
//Make sure we can use the ability
|
||||
MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]);
|
||||
for (int j=0; j < game->inPlay->nb_cards; j++){
|
||||
MTGCardInstance * card = game->inPlay->cards[j];
|
||||
if (a->isReactingToClick(card,pMana)){
|
||||
createAbilityTargets(a, card, &ranking);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ranking.size()){
|
||||
OutputDebugString("We have a winner\n");
|
||||
AIAction * a = ranking.begin()->first;
|
||||
int chance = 1 + rand() % 100;
|
||||
if (a->getEfficiency() < chance){
|
||||
a = NULL;
|
||||
}else{
|
||||
OutputDebugString("We REALLY have a winner\n");
|
||||
tapLandsForMana(pMana, a->ability->cost);
|
||||
clickstream.push(a);
|
||||
}
|
||||
map<AIAction *, int, CmpAbilities>::iterator it2;
|
||||
for (it2 = ranking.begin(); it2!=ranking.end(); it2++){
|
||||
if (a != it2->first) delete(it2->first);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AIPlayer::interruptIfICan(){
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
|
||||
if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this){
|
||||
g->mLayers->stackLayer()->setIsInterrupting(this);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AIPlayer::effectBadOrGood(MTGCardInstance * card){
|
||||
int id = card->getMTGId();
|
||||
switch (id){
|
||||
default:
|
||||
break;
|
||||
}
|
||||
AbilityFactory * af = NEW AbilityFactory();
|
||||
int autoGuess = af->magicText(id,NULL,card);
|
||||
delete af;
|
||||
@@ -182,14 +320,14 @@ int AIPlayer::chooseTarget(TargetChooser * tc){
|
||||
case TARGET_CARD:
|
||||
{
|
||||
MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]);
|
||||
gameObs->cardClick(card);
|
||||
clickstream.push(NEW AIAction(card));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
case TARGET_PLAYER:
|
||||
{
|
||||
Player * player = ((Player *) potentialTargets[i]);
|
||||
gameObs->cardClick(NULL, player);
|
||||
clickstream.push(NEW AIAction(player));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
@@ -236,7 +374,9 @@ int AIPlayer::chooseAttackers(){
|
||||
cd.setType("creature");
|
||||
MTGCardInstance * card = NULL;
|
||||
while((card = cd.nextmatch(game->inPlay, card))){
|
||||
GameObserver::GetInstance()->cardClick(card);
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
g->cardClick(card);
|
||||
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@@ -270,7 +410,9 @@ int AIPlayer::chooseBlockers(){
|
||||
opponentsToughness[attacker]-= card->power;
|
||||
set = 1;
|
||||
}else{
|
||||
GameObserver::GetInstance()->cardClick(card);
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
g->cardClick(card);
|
||||
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,13 +420,19 @@ int AIPlayer::chooseBlockers(){
|
||||
card = NULL;
|
||||
while((card = cd.nextmatch(game->inPlay, card))){
|
||||
if (card->defenser && opponentsToughness[card->defenser] > 0){
|
||||
while (card->defenser) GameObserver::GetInstance()->cardClick(card);
|
||||
while (card->defenser){
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
g->cardClick(card);
|
||||
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
card = NULL;
|
||||
while((card = cd.nextmatch(game->inPlay, card))){
|
||||
if(!card->defenser){
|
||||
GameObserver::GetInstance()->cardClick(card);
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
g->cardClick(card);
|
||||
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
|
||||
int set = 0;
|
||||
while(!set){
|
||||
if (!card->defenser){
|
||||
@@ -292,7 +440,9 @@ int AIPlayer::chooseBlockers(){
|
||||
}else{
|
||||
MTGCardInstance * attacker = card->defenser;
|
||||
if (opponentsToughness[attacker] <= 0 || (card->toughness <= card->defenser->power && opponentForce*2 <life) || card->defenser->nbOpponents()>1){
|
||||
GameObserver::GetInstance()->cardClick(card);
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
g->cardClick(card);
|
||||
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
|
||||
}else{
|
||||
set = 1;
|
||||
}
|
||||
@@ -322,19 +472,19 @@ int AIPlayer::combatDamages(){
|
||||
#endif
|
||||
DamagerDamaged * current = (DamagerDamaged *) drl->mObjects[i];
|
||||
if (current->damageSelecter == this){
|
||||
result = 1;
|
||||
DamagerDamaged * canardEmissaire = NULL;
|
||||
for (int j = 0; j < drl->mCount; j++){
|
||||
DamagerDamaged * opponent = (DamagerDamaged *) drl->mObjects[j];
|
||||
if (drl->isOpponent(current, opponent)){
|
||||
if (!canardEmissaire) canardEmissaire = opponent;
|
||||
int over = opponent->hasLethalDamage();
|
||||
while(!over){
|
||||
if(!current->dealOneDamage(opponent)){
|
||||
over = 1;
|
||||
}else{
|
||||
over = opponent->hasLethalDamage();
|
||||
}
|
||||
result = 1;
|
||||
DamagerDamaged * canardEmissaire = NULL;
|
||||
for (int j = 0; j < drl->mCount; j++){
|
||||
DamagerDamaged * opponent = (DamagerDamaged *) drl->mObjects[j];
|
||||
if (drl->isOpponent(current, opponent)){
|
||||
if (!canardEmissaire) canardEmissaire = opponent;
|
||||
int over = opponent->hasLethalDamage();
|
||||
while(!over){
|
||||
if(!current->dealOneDamage(opponent)){
|
||||
over = 1;
|
||||
}else{
|
||||
over = opponent->hasLethalDamage();
|
||||
}
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "==========\n%s deals %i damages to %s\n=============\n", current->card->getName(), 1, opponent->card->getName());
|
||||
@@ -455,9 +605,127 @@ AIPlayerBaka::AIPlayerBaka(MTGPlayerCards * _deck, char * file, char * avatarFil
|
||||
}
|
||||
|
||||
void AIPlayerBaka::initTimer(){
|
||||
timer = 0.3;
|
||||
timer = 0.1;
|
||||
}
|
||||
|
||||
int AIPlayerBaka::computeActions(){
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
Player * p = g->currentPlayer;
|
||||
if (!(g->currentlyActing() == this)) return 0;
|
||||
if (chooseTarget()) return 1;
|
||||
int currentGamePhase = g->getCurrentGamePhase();
|
||||
if (g->isInterrupting == this){ // interrupting
|
||||
selectAbility();
|
||||
return 1;
|
||||
}else if (p == this){ //standard actions
|
||||
CardDescriptor cd;
|
||||
MTGCardInstance * card = NULL;
|
||||
switch(currentGamePhase){
|
||||
case Constants::MTG_PHASE_FIRSTMAIN:
|
||||
case Constants::MTG_PHASE_SECONDMAIN:
|
||||
if (canPutLandsIntoPlay){
|
||||
//Attempt to put land into play
|
||||
cd.init();
|
||||
cd.setColor(Constants::MTG_COLOR_LAND);
|
||||
card = cd.match(game->hand);
|
||||
if (card){
|
||||
AIAction * a = NEW AIAction(card);
|
||||
clickstream.push(a);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//No mana, try to get some
|
||||
getPotentialMana();
|
||||
if (potentialMana->getConvertedCost() > 0){
|
||||
|
||||
|
||||
//look for the most expensive creature we can afford
|
||||
nextCardToPlay = FindCardToPlay(potentialMana, "creature");
|
||||
//Let's Try an enchantment maybe ?
|
||||
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(potentialMana, "enchantment");
|
||||
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(potentialMana, "artifact");
|
||||
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(potentialMana, "instant");
|
||||
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(potentialMana, "sorcery");
|
||||
if (nextCardToPlay){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buffe[4096];
|
||||
sprintf(buffe, "Putting Card Into Play: %s", nextCardToPlay->getName());
|
||||
OutputDebugString(buffe);
|
||||
#endif
|
||||
|
||||
tapLandsForMana(potentialMana,nextCardToPlay->getManaCost());
|
||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
return 1;
|
||||
}else{
|
||||
selectAbility();
|
||||
}
|
||||
}else{
|
||||
selectAbility();
|
||||
}
|
||||
break;
|
||||
case Constants::MTG_PHASE_COMBATATTACKERS:
|
||||
chooseAttackers();
|
||||
break;
|
||||
default:
|
||||
selectAbility();
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
switch(currentGamePhase){
|
||||
case Constants::MTG_PHASE_COMBATBLOCKERS:
|
||||
chooseBlockers();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
int AIPlayerBaka::Act(float dt){
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
int currentGamePhase = g->getCurrentGamePhase();
|
||||
|
||||
if (currentGamePhase == Constants::MTG_PHASE_CLEANUP && currentGamePhase != oldGamePhase){
|
||||
if (getStats()) getStats()->updateStats();
|
||||
}
|
||||
oldGamePhase = currentGamePhase;
|
||||
|
||||
timer-= dt;
|
||||
if (AManaProducer::currentlyTapping || timer>0){
|
||||
return 0;
|
||||
}
|
||||
initTimer();
|
||||
if (combatDamages()){
|
||||
OutputDebugString("Damages and NOTHING ELSE\n");
|
||||
return 0;
|
||||
}
|
||||
interruptIfICan();
|
||||
if (!(g->currentlyActing() == this)){
|
||||
OutputDebugString("Cannot interrupt\n");
|
||||
return 0;
|
||||
}
|
||||
if (!clickstream.empty()){
|
||||
AIAction * action = clickstream.front();
|
||||
action->Act();
|
||||
SAFE_DELETE(action);
|
||||
clickstream.pop();
|
||||
}
|
||||
|
||||
if (clickstream.empty()) computeActions();
|
||||
if (clickstream.empty()){
|
||||
if (g->isInterrupting == this){
|
||||
g->mLayers->stackLayer()->cancelInterruptOffer(); //endOfInterruption();
|
||||
}else{
|
||||
g->userRequestNextGamePhase();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
int AIPlayerBaka::Act(float dt){
|
||||
GameObserver * gameObs = GameObserver::GetInstance();
|
||||
int currentGamePhase = gameObs->getCurrentGamePhase();
|
||||
@@ -472,13 +740,16 @@ int AIPlayerBaka::Act(float dt){
|
||||
|
||||
oldGamePhase = currentGamePhase;
|
||||
|
||||
if (checkInterrupt()) return 0;
|
||||
|
||||
//if (checkInterrupt()) return 0;
|
||||
|
||||
timer-= dt;
|
||||
if (timer>0){
|
||||
if (AManaProducer::currentlyTapping || timer>0){
|
||||
return 0;
|
||||
}
|
||||
initTimer();
|
||||
checkInterrupt();
|
||||
if (currentAbility) return (useAbility());
|
||||
if (combatDamages()) return 0;
|
||||
if (chooseTarget()) return 0;
|
||||
|
||||
@@ -575,3 +846,4 @@ int AIPlayerBaka::Act(float dt){
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,9 @@ ActionElement::ActionElement(int id):JGuiObject(id){
|
||||
tc = NULL;
|
||||
}
|
||||
|
||||
ActionElement::~ActionElement(){
|
||||
SAFE_DELETE(tc);
|
||||
}
|
||||
|
||||
int ActionElement::getActivity(){
|
||||
|
||||
|
||||
@@ -508,7 +508,7 @@ void ActionStack::Update(float dt){
|
||||
}
|
||||
|
||||
void ActionStack::cancelInterruptOffer(int cancelMode){
|
||||
if (askIfWishesToInterrupt == game->players[0]){
|
||||
if (game->isInterrupting == game->players[0]){
|
||||
interruptDecision[0] = cancelMode;
|
||||
}else{
|
||||
interruptDecision[1] = cancelMode;
|
||||
|
||||
@@ -54,8 +54,6 @@ MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card){
|
||||
}
|
||||
for (int i = 0; i< Constants::MTG_NB_COLORS; i++){
|
||||
if ((colors[i] == 1 && !card->hasColor(i))||(colors[i] == -1 && card->hasColor(i))){
|
||||
OutputDebugString ("Too bad for ");
|
||||
OutputDebugString(card->getName());
|
||||
match = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1609,12 +1609,16 @@ MTGAbility::MTGAbility(int id, MTGCardInstance * card):ActionElement(id){
|
||||
game = GameObserver::GetInstance();
|
||||
source = card;
|
||||
target = card;
|
||||
aType = MTGAbility::UNKNOWN;
|
||||
cost = NULL;
|
||||
}
|
||||
|
||||
MTGAbility::MTGAbility(int id, MTGCardInstance * _source,Damageable * _target ):ActionElement(id){
|
||||
game = GameObserver::GetInstance();
|
||||
source = _source;
|
||||
target = _target;
|
||||
aType = MTGAbility::UNKNOWN;
|
||||
cost = NULL;
|
||||
}
|
||||
|
||||
MTGAbility::~MTGAbility(){
|
||||
@@ -1644,16 +1648,21 @@ int MTGAbility::fireAbility(){
|
||||
|
||||
//
|
||||
|
||||
ActivatedAbility::ActivatedAbility(int id, MTGCardInstance * card, ManaCost * _cost, int _playerturnonly,int tap):MTGAbility(id,card), cost(_cost), playerturnonly(_playerturnonly), needsTapping(tap){
|
||||
ActivatedAbility::ActivatedAbility(int id, MTGCardInstance * card, ManaCost * _cost, int _playerturnonly,int tap):MTGAbility(id,card), playerturnonly(_playerturnonly), needsTapping(tap){
|
||||
cost = _cost;
|
||||
}
|
||||
|
||||
|
||||
int ActivatedAbility::isReactingToClick(MTGCardInstance * card){
|
||||
int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
|
||||
Player * player = game->currentPlayer;
|
||||
if (!playerturnonly) player = game->currentlyActing();
|
||||
if (card == source && source->controller()==player && player==game->currentlyActing() && (!needsTapping || (!source->isTapped() && !source->hasSummoningSickness()))){
|
||||
if (!cost) return 1;
|
||||
if (!player->getManaPool()->canAfford(cost)) return 0;
|
||||
if (!mana) mana = player->getManaPool();
|
||||
if (!mana->canAfford(cost)) return 0;
|
||||
char buf[4096];
|
||||
sprintf(buf, "Will react to Click : %i\n", aType);
|
||||
OutputDebugString(buf);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1751,11 +1760,9 @@ int TargetAbility::reactToClick(MTGCardInstance * card){
|
||||
return 1;
|
||||
}
|
||||
}else{
|
||||
if (card == source){
|
||||
if (tc->targetsReadyCheck() == TARGET_OK || tc->targetsReadyCheck() == TARGET_OK_FULL){
|
||||
waitingForAnswer = 0;
|
||||
return ActivatedAbility::reactToClick(source);
|
||||
}
|
||||
if (card == source && (tc->targetsReadyCheck() == TARGET_OK || tc->targetsReadyCheck() == TARGET_OK_FULL)){
|
||||
waitingForAnswer = 0;
|
||||
return ActivatedAbility::reactToClick(source);
|
||||
}else{
|
||||
if (tc->toggleTarget(card) == TARGET_OK_FULL){
|
||||
|
||||
@@ -2008,7 +2015,9 @@ other solutions need to be provided for abilities that add mana (ex: mana flare)
|
||||
|
||||
|
||||
AManaProducer::AManaProducer(int id, MTGCardInstance * card, ManaCost * _output, ManaCost * _cost , int doTap):MTGAbility(id, card), tap(doTap){
|
||||
LOG("==Creating ManaProducer Object");
|
||||
|
||||
LOG("==Creating ManaProducer Object");
|
||||
aType=MTGAbility::MANA_PRODUCER;
|
||||
cost = _cost;
|
||||
output=_output;
|
||||
x1 = 10;
|
||||
@@ -2072,10 +2081,11 @@ other solutions need to be provided for abilities that add mana (ex: mana flare)
|
||||
|
||||
}
|
||||
|
||||
int AManaProducer::isReactingToClick(MTGCardInstance * _card){
|
||||
int AManaProducer::isReactingToClick(MTGCardInstance * _card, ManaCost * mana){
|
||||
int result = 0;
|
||||
if (!mana) mana = game->currentlyActing()->getManaPool();
|
||||
if (_card == source && (!tap || !source->isTapped()) && game->currentlyActing()->game->inPlay->hasCard(source) && (source->hasType("land") || !tap || !source->hasSummoningSickness()) ){
|
||||
if (!cost || game->currentlyActing()->getManaPool()->canAfford(cost)) result = 1;
|
||||
if (!cost || mana->canAfford(cost)) result = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ MTGPutInPlayRule::MTGPutInPlayRule(int _id):MTGAbility(_id, NULL){
|
||||
|
||||
}
|
||||
|
||||
int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card){
|
||||
int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
|
||||
Player * player = game->currentlyActing();
|
||||
Player * currentPlayer = game->currentPlayer;
|
||||
LOG("CANPUTINPLAY- check if card belongs to current player\n");
|
||||
@@ -80,7 +80,7 @@ int MTGPutInPlayRule::testDestroy(){
|
||||
MTGAttackRule::MTGAttackRule(int _id):MTGAbility(_id,NULL){
|
||||
}
|
||||
|
||||
int MTGAttackRule::isReactingToClick(MTGCardInstance * card){
|
||||
int MTGAttackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
|
||||
if (currentPhase == Constants::MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer && !card->isAttacker()){
|
||||
if (card->canAttack()) return 1;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ int MTGAttackRule::testDestroy(){
|
||||
MTGBlockRule::MTGBlockRule(int _id):MTGAbility(_id,NULL){
|
||||
}
|
||||
|
||||
int MTGBlockRule::isReactingToClick(MTGCardInstance * card){
|
||||
int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
|
||||
if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() == game->opponent()){
|
||||
if (card->canBlock()) return 1;
|
||||
}
|
||||
|
||||
@@ -109,11 +109,6 @@ ManaCost::ManaCost(int _cost[], int nb_elems){
|
||||
init();
|
||||
int i;
|
||||
int total = nb_elems;
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "Create New MAnaCost, total Colors : %i\n", total);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
for (i = 0; i < total; i++){
|
||||
cost[_cost[i*2]] = _cost[i*2 + 1];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user