added optimizing of opponents hand if the opponent deck is listed as "easy". slight optimize if listed as "normal" none if listed as "hard" this provides slightly more challange from even poorly constructed Ai decks. taught Ai to pump creatures during combat, and more so if its heading directly at player, taught Ai that its better to use "becomes" and "transforms" during first main. this allow its to actually attack with the manlands ect.
new ability lord...teach(whatever[whatever]) ability. teach is a targeted lord, it takes the cards current target and lords it the ability. im aware of a tiny memleak it contains, but the leak is happening on parser lvl, so i need more eyes to look at it. teach is ideally used for equipment, and was designed to fix issue 244 taught abilities are not given to the source cards. forced Ai to pay for sunburst correctly. it was choosing to pay with all of one type of mana. now it pays either max or 1 from max sunburst. added a tiny double check for Ai to try and find something to use if it suddenly has mana in its pool. it is only a single check in a turn, but i notice it actually does slightly improve the usages of dark ritual and foreach mana producers. ideally i wanted it to check EVERYTIME. but i could not achieve it without putting the game in danger of looping. so once is better then none :/ fixed a bug with affinity where it was not counting duel lands, this is becuase of not setting it up correctly for lands with multiple types SORRY!
This commit is contained in:
@@ -14,6 +14,9 @@ using std::queue;
|
||||
|
||||
#define INFO_NBCREATURES 0
|
||||
#define INFO_CREATURESPOWER 1
|
||||
#define INFO_CREATURESRANK 2
|
||||
#define INFO_CREATURESTOUGHNESS 3
|
||||
#define INFO_CREATURESATTACKINGPOWER 4
|
||||
|
||||
|
||||
class AIStats;
|
||||
@@ -27,6 +30,7 @@ public:
|
||||
NestedAbility * nability;
|
||||
Player * player;
|
||||
int id;
|
||||
bool checked;
|
||||
MTGCardInstance * click;
|
||||
MTGCardInstance * target; // TODO Improve
|
||||
AIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL):ability(a),click(c),target(t){player = NULL; efficiency = -1; id = currentId++;};
|
||||
@@ -51,7 +55,6 @@ class CmpAbilities { // compares Abilities efficiency
|
||||
class AIPlayer: public Player{
|
||||
protected:
|
||||
MTGCardInstance * nextCardToPlay;
|
||||
int agressivity;
|
||||
queue<AIAction *> clickstream;
|
||||
void tapLandsForMana(ManaCost * cost, MTGCardInstance * card = NULL);
|
||||
int orderBlockers();
|
||||
@@ -65,6 +68,8 @@ class AIPlayer: public Player{
|
||||
AIStats * getStats();
|
||||
//Variables used by Test suite
|
||||
public:
|
||||
int agressivity;
|
||||
bool Checked;
|
||||
bool forceBestAbilityUse;
|
||||
void End(){};
|
||||
virtual int displayStack() {return 0;};
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <JGui.h>
|
||||
#include <hge/hgeparticle.h>
|
||||
|
||||
|
||||
#include <map>
|
||||
using std::map;
|
||||
|
||||
@@ -1078,6 +1077,8 @@ class AADrawer:public ActivatedAbilityTP{
|
||||
public:
|
||||
WParsedInt *nbcards;
|
||||
AADrawer(int _id, MTGCardInstance * card,Targetable * _target,ManaCost * _cost, WParsedInt * _nbcards, int _tap = 0, int who=TargetChooser::UNSET):ActivatedAbilityTP(_id, card,_target,_cost,_tap,who),nbcards(_nbcards){
|
||||
aType = MTGAbility::STANDARD_DRAW;
|
||||
nbcardAmount = nbcards->getValue();
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
@@ -1647,78 +1648,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//equipment
|
||||
class AEquip:public TargetAbility{
|
||||
public:
|
||||
vector<MTGAbility *> currentAbilities;
|
||||
AEquip(int _id, MTGCardInstance * _source, ManaCost * _cost=NULL, int doTap=0, int restrictions = ActivatedAbility::AS_SORCERY):TargetAbility(_id, _source,NULL,_cost,restrictions,doTap){
|
||||
aType = MTGAbility::STANDARD_EQUIP;
|
||||
}
|
||||
|
||||
int unequip(){
|
||||
if(source->target){source->target->equipment -= 1;}
|
||||
source->target = NULL;
|
||||
for (size_t i = 0; i < currentAbilities.size(); ++i){
|
||||
MTGAbility * a = currentAbilities[i];
|
||||
if(dynamic_cast<AEquip *>(a)){
|
||||
SAFE_DELETE(a);
|
||||
continue;
|
||||
}
|
||||
GameObserver::GetInstance()->removeObserver(currentAbilities[i]);
|
||||
}
|
||||
currentAbilities.clear();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int equip(MTGCardInstance * equipped){
|
||||
source->target = equipped;
|
||||
source->target->equipment += 1;
|
||||
AbilityFactory af;
|
||||
af.getAbilities(¤tAbilities,NULL,source);
|
||||
for (size_t i = 0; i < currentAbilities.size(); ++i){
|
||||
MTGAbility * a = currentAbilities[i];
|
||||
if(dynamic_cast<AEquip *>(a)) continue;
|
||||
a->addToGame();
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int resolve(){
|
||||
MTGCardInstance * mTarget = tc->getNextCardTarget();
|
||||
if (!mTarget) return 0;
|
||||
if (mTarget == source) return 0;
|
||||
unequip();
|
||||
equip(mTarget);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char * getMenuText(){
|
||||
return "Equip";
|
||||
}
|
||||
|
||||
|
||||
int testDestroy(){
|
||||
if (source->target && !game->isInPlay(source->target))
|
||||
unequip();
|
||||
return TargetAbility::testDestroy();
|
||||
}
|
||||
|
||||
int destroy(){
|
||||
unequip();
|
||||
return TargetAbility::destroy();
|
||||
}
|
||||
|
||||
AEquip * clone() const{
|
||||
AEquip * a = NEW AEquip(*this);
|
||||
a->isClone = 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*Gives life each time a spell matching CardDescriptor's criteria are match . Optionnal manacost*/
|
||||
class ASpellCastLife:public MTGAbility{
|
||||
public:
|
||||
@@ -1890,7 +1819,7 @@ class APowerToughnessModifier: public MTGAbility{
|
||||
public:
|
||||
WParsedPT * wppt;
|
||||
APowerToughnessModifier(int id, MTGCardInstance * _source, MTGCardInstance * _target, WParsedPT * wppt):MTGAbility(id,_source,_target),wppt(wppt){
|
||||
|
||||
aType = MTGAbility::STANDARD_PUMP;
|
||||
}
|
||||
|
||||
int addToGame(){
|
||||
@@ -1925,6 +1854,7 @@ class AInstantPowerToughnessModifierUntilEOT: public InstantAbility{
|
||||
public:
|
||||
WParsedPT * wppt;
|
||||
AInstantPowerToughnessModifierUntilEOT(int _id, MTGCardInstance * _source, MTGCardInstance * _target, WParsedPT * wppt): InstantAbility(_id, _source, _target), wppt(wppt){
|
||||
aType = MTGAbility::STANDARD_PUMP;
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
@@ -1969,6 +1899,7 @@ public:
|
||||
counters = 0;
|
||||
target=_target;
|
||||
ability = NEW AInstantPowerToughnessModifierUntilEOT(id,_source,_target,wppt);
|
||||
aType = MTGAbility::STANDARD_PUMP;
|
||||
}
|
||||
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * cost = NULL){
|
||||
@@ -2446,8 +2377,155 @@ public:
|
||||
return a;
|
||||
}
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//a different lord for auras and enchantments. http://code.google.com/p/wagic/issues/detail?id=244
|
||||
class ATeach:public ListMaintainerAbility, public NestedAbility{
|
||||
public:
|
||||
int includeSelf;
|
||||
map<Damageable *, MTGAbility *> skills;
|
||||
|
||||
ATeach(int _id, MTGCardInstance * card, TargetChooser * _tc, int _includeSelf, MTGAbility * a):ListMaintainerAbility(_id,card), NestedAbility(a){
|
||||
tc = _tc;
|
||||
tc->targetter = NULL;
|
||||
includeSelf = NULL;
|
||||
}
|
||||
|
||||
int canBeInList(MTGCardInstance * card){
|
||||
if ((tc->source->hasSubtype("aura") || tc->source->hasSubtype("equipment") || tc->source->hasSubtype("instant") || tc->source->hasSubtype("sorcery"))&& tc->canTarget(card) && card == tc->source->target && card != tc->source) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
updateTargets();
|
||||
cards.clear();
|
||||
players.clear();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int added(MTGCardInstance * card){
|
||||
return _added(card);
|
||||
}
|
||||
|
||||
int removed(MTGCardInstance * card){
|
||||
if(skills.find(card) != skills.end()){
|
||||
game->removeObserver(skills[card]);
|
||||
skills.erase(card);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _added(Damageable * d){
|
||||
MTGAbility * a = ability->clone();
|
||||
|
||||
if(a->source->hasSubtype("aura") || a->source->hasSubtype("equipment") || a->source->hasSubtype("instant") || a->source->hasSubtype("sorcery"))
|
||||
{
|
||||
a->target = a->source->target;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a->oneShot){
|
||||
a->resolve();
|
||||
delete(a);
|
||||
}else{
|
||||
if (d->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){
|
||||
a->source = (MTGCardInstance *)d;
|
||||
}
|
||||
if (oneShot){
|
||||
MTGAbility * wrapper = NEW GenericInstantAbility(1,source,d,a);
|
||||
wrapper->addToGame();
|
||||
}else{
|
||||
skills[d] = a;
|
||||
a->addToGame();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
~ATeach(){
|
||||
if (!isClone) SAFE_DELETE(ability);
|
||||
}
|
||||
|
||||
ATeach * clone() const{
|
||||
ATeach * a = NEW ATeach(*this);
|
||||
a->isClone = 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
};
|
||||
//
|
||||
|
||||
//equipment
|
||||
class AEquip:public TargetAbility{
|
||||
public:
|
||||
vector<MTGAbility *> currentAbilities;
|
||||
AEquip(int _id, MTGCardInstance * _source, ManaCost * _cost=NULL, int doTap=0, int restrictions = ActivatedAbility::AS_SORCERY):TargetAbility(_id,_source,NULL,_cost,restrictions,doTap){
|
||||
aType = MTGAbility::STANDARD_EQUIP;
|
||||
}
|
||||
|
||||
int unequip(){
|
||||
if(source->target){source->target->equipment -= 1;}
|
||||
source->target = NULL;
|
||||
for (size_t i = 0; i < currentAbilities.size(); ++i){
|
||||
MTGAbility * a = currentAbilities[i];
|
||||
if(dynamic_cast<AEquip *>(a)){
|
||||
SAFE_DELETE(a);
|
||||
continue;
|
||||
}
|
||||
GameObserver::GetInstance()->removeObserver(currentAbilities[i]);
|
||||
}
|
||||
currentAbilities.clear();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int equip(MTGCardInstance * equipped){
|
||||
source->target = equipped;
|
||||
source->target->equipment += 1;
|
||||
AbilityFactory af;
|
||||
af.getAbilities(¤tAbilities,NULL,source);
|
||||
for (size_t i = 0; i < currentAbilities.size(); ++i){
|
||||
MTGAbility * a = currentAbilities[i];
|
||||
if(dynamic_cast<AEquip *>(a)) continue;
|
||||
if(dynamic_cast<ATeach *>(a)) continue;
|
||||
a->addToGame();
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int resolve(){
|
||||
MTGCardInstance * mTarget = tc->getNextCardTarget();
|
||||
if (!mTarget) return 0;
|
||||
if (mTarget == source) return 0;
|
||||
unequip();
|
||||
equip(mTarget);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char * getMenuText(){
|
||||
return "Equip";
|
||||
}
|
||||
|
||||
|
||||
int testDestroy(){
|
||||
if (source->target && !game->isInPlay(source->target))
|
||||
unequip();
|
||||
return TargetAbility::testDestroy();
|
||||
}
|
||||
|
||||
int destroy(){
|
||||
unequip();
|
||||
return TargetAbility::destroy();
|
||||
}
|
||||
|
||||
AEquip * clone() const{
|
||||
AEquip * a = NEW AEquip(*this);
|
||||
a->isClone = 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
};
|
||||
//Foreach (plague rats...)
|
||||
class AForeach:public ListMaintainerAbility, public NestedAbility{
|
||||
public:
|
||||
@@ -3323,6 +3401,7 @@ public:
|
||||
list<int>types;
|
||||
list<int>colors;
|
||||
AForeverTransformer(int id, MTGCardInstance * source, MTGCardInstance * target, string stypes, string sabilities):MTGAbility(id,source,target){
|
||||
aType = MTGAbility::STANDARD_BECOMES;
|
||||
//TODO this is a copy/past of other code that's all around the place, everything should be in a dedicated parser class;
|
||||
MTGCardInstance * _target = (MTGCardInstance *)target;
|
||||
for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){
|
||||
@@ -3376,7 +3455,9 @@ class ATransformerUEOT: public InstantAbility{
|
||||
public:
|
||||
ATransformer * ability;
|
||||
ATransformerUEOT(int id, MTGCardInstance * source, MTGCardInstance * target, string types, string abilities):InstantAbility(id,source,target){
|
||||
ability = NEW ATransformer(id,source,target,types,abilities);}
|
||||
ability = NEW ATransformer(id,source,target,types,abilities);
|
||||
aType = MTGAbility::STANDARD_BECOMES;
|
||||
}
|
||||
int resolve(){
|
||||
ATransformer * a = ability->clone();
|
||||
GenericInstantAbility * wrapper = NEW GenericInstantAbility(1,source,(Damageable *)(this->target),a);
|
||||
@@ -3399,6 +3480,7 @@ public:
|
||||
AForeverTransformer * ability;
|
||||
ATransformerFOREVER(int id, MTGCardInstance * source, MTGCardInstance * target, string types, string abilities):InstantAbility(id,source,target){
|
||||
ability = NEW AForeverTransformer(id,source,target,types,abilities);
|
||||
aType = MTGAbility::STANDARD_BECOMES;
|
||||
}
|
||||
int resolve(){
|
||||
AForeverTransformer * a = ability->clone();
|
||||
@@ -3450,6 +3532,7 @@ public:
|
||||
WParsedPT * wppt;
|
||||
string menu;
|
||||
ABecomes(int id, MTGCardInstance * source, MTGCardInstance * target, string stypes, WParsedPT * wppt, string sabilities):MTGAbility(id,source,target),wppt(wppt){
|
||||
aType = MTGAbility::STANDARD_BECOMES;
|
||||
//TODO this is a copy/past of other code that's all around the place, everything should be in a dedicated parser class;
|
||||
|
||||
for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){
|
||||
@@ -3543,6 +3626,7 @@ public:
|
||||
ABecomes * ability;
|
||||
ABecomesUEOT(int id, MTGCardInstance * source, MTGCardInstance * target, string types, WParsedPT * wpt, string abilities):InstantAbility(id,source,target){
|
||||
ability = NEW ABecomes(id,source,target,types,wpt,abilities);
|
||||
aType = MTGAbility::STANDARD_BECOMES;
|
||||
}
|
||||
|
||||
int resolve(){
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "DeckMetaData.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -28,6 +29,11 @@ public:
|
||||
static DeckManager * GetInstance();
|
||||
static void EndInstance();
|
||||
|
||||
//convenience method to get the difficulty rating between two decks. This should be refined a little more
|
||||
//since the eventual move of all deck meta data should be managed by this class
|
||||
|
||||
static int getDifficultyRating( Player *statsPlayer, Player *player );
|
||||
|
||||
|
||||
~DeckManager()
|
||||
{
|
||||
|
||||
@@ -57,6 +57,7 @@ class MTGAbility: public ActionElement{
|
||||
Targetable * target;
|
||||
int aType;
|
||||
int naType;
|
||||
int nbcardAmount;
|
||||
MTGCardInstance * source;
|
||||
MTGAbility(int id, MTGCardInstance * card);
|
||||
MTGAbility(int id, MTGCardInstance * _source, Targetable * _target);
|
||||
@@ -95,6 +96,9 @@ class MTGAbility: public ActionElement{
|
||||
STANDARD_EQUIP = 14,
|
||||
STANDARD_LEVELUP = 15,
|
||||
FOREACH = 16,
|
||||
STANDARD_DRAW = 17,
|
||||
STANDARD_PUMP = 18,
|
||||
STANDARD_BECOMES = 19,
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -154,6 +154,7 @@ class MTGPlayerCards {
|
||||
MTGPlayerCards(MTGDeck * deck);
|
||||
~MTGPlayerCards();
|
||||
void initGame(int shuffle = 1, int draw = 1);
|
||||
void OptimizedHand(int amount = 7,int lands = 3,int creatures = 0,int othercards = 4);
|
||||
void setOwner(Player * player);
|
||||
void discardRandom(MTGGameZone * from,MTGCardInstance * source);
|
||||
void drawFromLibrary();
|
||||
|
||||
Reference in New Issue
Block a user