- Added Momir Basic mode :)
This commit is contained in:
wagic.the.homebrew@gmail.com
2009-04-04 12:52:36 +00:00
parent 82f418d0f3
commit 6582a1972a
24 changed files with 479 additions and 131 deletions
+192
View File
@@ -0,0 +1,192 @@
#include "../include/config.h"
#include "../include/AIMomirPlayer.h"
#include "../include/CardDescriptor.h"
#include "../include/DamageResolverLayer.h"
#include "../include/DamagerDamaged.h"
#include "../include/AIStats.h"
#include "../include/AllAbilities.h"
MTGAbility * AIMomirPlayer::momirAbility = NULL;
AIMomirPlayer::AIMomirPlayer(MTGPlayerCards * _deck, char * file, char * avatarFile): AIPlayerBaka(_deck,file, avatarFile){
// TODO count min and max number of mana (should probably be part of the gameobserver so that human players don't make mistakes)
momirAbility = NULL;
}
int AIMomirPlayer::getEfficiency(AIAction * action){
int efficiency = AIPlayerBaka::getEfficiency(action);
if (efficiency < 15) return 0;
GameObserver * g = GameObserver::GetInstance();
if (g->getCurrentGamePhase() < Constants::MTG_PHASE_FIRSTMAIN) return 0;
return efficiency;
}
MTGAbility * AIMomirPlayer::getMomirAbility(){
if (momirAbility) return momirAbility;
GameObserver * g = GameObserver::GetInstance();
momirAbility = g->mLayers->actionLayer()->getAbility(MTGAbility::MOMIR);
return momirAbility;
}
int AIMomirPlayer::momir(){
if (!game->hand->nb_cards) return 0; //nothing to discard :/
getPotentialMana();
int converted = potentialMana->getConvertedCost();
int efficiency = 100;
int chance = 1 + (rand() % 100);
if (converted == 5) efficiency = 5 ; //Strategy: skip 5 drop
if (converted == 7) efficiency = 50; //Strategy: 7 drops have bad upkeep costs and the AI doesn't handle those right now...
if (converted > 8 ) converted = 8;
if (converted == 8) efficiency = 100 - game->inPlay->nb_cards;
if (efficiency >= chance){
int _cost[] = {Constants::MTG_COLOR_ARTIFACT,converted};
ManaCost * cost = NEW ManaCost(_cost);
tapLandsForMana(potentialMana,cost);
delete cost;
MTGAbility * ability = getMomirAbility();
MTGCardInstance * card = game->hand->cards[0];
if (ability->isReactingToClick(card,cost)){
AIAction * a = NEW AIAction(ability,card);
clickstream.push(a);
return 1;
}
}
return 0;
}
int AIMomirPlayer::computeActions(){
//Part of the strategy goes here. When should we put a land into play ?
/*
Another gift from Alex Majlaton on my first day playing Momir, and it has served me well ever since. It goes a little something like this: (a) if you are on the play, hit your Two through Four, skip your Five, and then hit all the way to Eight; (b) if you are on the draw and your opponent skips his One, you make Two through Eight; (c) if you are on the draw and your opponent hits a One, you match him drop-for-drop for the rest of the game.
You skip your Five on the play because it is the weakest drop. There are plenty of serviceable guys there, but very few bombs compared to other drops
the general rule is this: if you want to get to Eight, you have to skip two drops on the play and one drop on the draw.
*/
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 && g->mLayers->stackLayer()->count(0,NOT_RESOLVED) == 0){ //standard actions
CardDescriptor cd;
MTGCardInstance * card = NULL;
//No mana, try to get some
getPotentialMana();
switch(currentGamePhase){
case Constants::MTG_PHASE_FIRSTMAIN:
if (canPutLandsIntoPlay && (potentialMana->getConvertedCost() <8 || game->hand->nb_cards > 1) ){
//Attempt to put land into play
cd.init();
cd.setColor(Constants::MTG_COLOR_LAND);
card = cd.match(game->hand);
if (card){
MTGAbility * putIntoPlay = g->mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY);
AIAction * a = NEW AIAction(putIntoPlay,card); //TODO putinplay action
clickstream.push(a);
return 1;
}
}
momir();
return 1;
break;
case Constants::MTG_PHASE_SECONDMAIN:
selectAbility();
return 1;
break;
default:
return AIPlayerBaka::computeActions();
break;
}
}else{
return AIPlayerBaka::computeActions();
}
}
/*
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 && g->mLayers->stackLayer()->count(0,NOT_RESOLVED) == 0){ //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;
}
return 1;
};
*/
+23 -17
View File
@@ -121,6 +121,10 @@ ManaCost * AIPlayer::getPotentialMana(){
}
int AIPlayer::getEfficiency(AIAction * action){
return action->getEfficiency();
}
int AIAction::getEfficiency(){
//TODO add multiplier according to what the player wants
if (efficiency != -1) return efficiency;
@@ -129,6 +133,7 @@ int AIAction::getEfficiency(){
ActionStack * s = g->mLayers->stackLayer();
Player * p = g->currentlyActing();
if (s->has(ability)) return 0;
if (ability->cost && !(ability->cost->isExtraPaymentSet())) return 0; //Does not handle abilities with sacrifice yet
switch (ability->aType){
case MTGAbility::DAMAGER:
{
@@ -226,7 +231,7 @@ int AIPlayer::selectAbility(){
OutputDebugString("We have a winner\n");
AIAction * a = ranking.begin()->first;
int chance = 1 + rand() % 100;
if (a->getEfficiency() < chance){
if (getEfficiency(a) < chance){
a = NULL;
}else{
OutputDebugString("We REALLY have a winner\n");
@@ -262,6 +267,8 @@ int AIPlayer::effectBadOrGood(MTGCardInstance * card){
return BAKA_EFFECT_DONTKNOW;
}
int AIPlayer::chooseTarget(TargetChooser * tc){
Targetable * potentialTargets[50];
int nbtargets = 0;
@@ -393,24 +400,25 @@ int AIPlayer::chooseBlockers(){
cd.setType("Creature");
cd.tapped = -1;
MTGCardInstance * card = NULL;
GameObserver * g = GameObserver::GetInstance();
while((card = cd.nextmatch(game->inPlay, card))){
GameObserver::GetInstance()->cardClick(card);
g->cardClick(card);
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
int set = 0;
while(!set){
if (!card->defenser){
set = 1;
set = 1;
}else{
MTGCardInstance * attacker = card->defenser;
map<MTGCardInstance *,int>::iterator it = opponentsToughness.find(attacker);
if ( it == opponentsToughness.end()){
opponentsToughness[attacker] = attacker->toughness;
it = opponentsToughness.find(attacker);
}
if (opponentsToughness[attacker] > 0 && getStats() && getStats()->isInTop(attacker,3,false)){
opponentsToughness[attacker]-= card->power;
set = 1;
}else{
GameObserver * g = GameObserver::GetInstance();
MTGCardInstance * attacker = card->defenser;
map<MTGCardInstance *,int>::iterator it = opponentsToughness.find(attacker);
if ( it == opponentsToughness.end()){
opponentsToughness[attacker] = attacker->toughness;
it = opponentsToughness.find(attacker);
}
if (opponentsToughness[attacker] > 0 && getStats() && getStats()->isInTop(attacker,3,false)){
opponentsToughness[attacker]-= card->power;
set = 1;
}else{
g->cardClick(card);
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
}
@@ -421,7 +429,7 @@ int AIPlayer::chooseBlockers(){
while((card = cd.nextmatch(game->inPlay, card))){
if (card->defenser && opponentsToughness[card->defenser] > 0){
while (card->defenser){
GameObserver * g = GameObserver::GetInstance();
g->cardClick(card);
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
}
@@ -430,7 +438,6 @@ int AIPlayer::chooseBlockers(){
card = NULL;
while((card = cd.nextmatch(game->inPlay, card))){
if(!card->defenser){
GameObserver * g = GameObserver::GetInstance();
g->cardClick(card);
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
int set = 0;
@@ -440,7 +447,6 @@ 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 * g = GameObserver::GetInstance();
g->cardClick(card);
if (g->mLayers->actionLayer()->menuObject) g->mLayers->actionLayer()->doReactTo(0);
}else{
+10
View File
@@ -4,6 +4,16 @@
#include "../include/Targetable.h"
#include "../include/WEvent.h"
MTGAbility* ActionLayer::getAbility(int type){
for (int i = 1; i < mCount; i++){
MTGAbility * a = ((MTGAbility *)mObjects[i]);
if (a->aType == type){
return a;
}
}
return NULL;
}
int ActionLayer::unstopableRenderInProgress(){
for (int i=0;i<mCount;i++){
+2 -2
View File
@@ -38,8 +38,8 @@ GameApp::GameApp(): JApp()
mShowDebugInfo = false;
players[0] = 0;
players[1] = 0;
gameType = GAME_TYPE_CLASSIC;
//gameType = GAME_TYPE_MOMIR;
}
+4
View File
@@ -109,6 +109,10 @@ void GameObserver::nextGamePhase(){
}
mLayers->stackLayer()->garbageCollect(); //clean stack history for this turn;
mLayers->actionLayer()->Update(0);
for (int i=0; i < 2; i++){
delete (players[i]->game->garbage);
players[i]->game->garbage = NEW MTGGameZone();
}
return nextGamePhase();
}
+63 -19
View File
@@ -3,9 +3,10 @@
#include "../include/GameOptions.h"
#include "../include/utils.h"
#include "../include/AIPlayer.h"
#include "../include/AIMomirPlayer.h"
#include "../include/PlayerData.h"
#include "../include/DeckStats.h"
#include "../include/MTGRules.h"
#ifdef TESTSUITE
#include "../include/TestSuiteAI.h"
@@ -89,18 +90,18 @@ void GameStateDuel::Start()
for (int i = 0; i<2; i ++){
if (mParent->players[i] == PLAYER_TYPE_HUMAN){
if (!deckmenu){
decksneeded = 1;
deckmenu = NEW SimpleMenu(DUEL_MENU_CHOOSE_DECK, this, mFont, 35, 25, "Choose a Deck");
char buffer[100];
for (int j=1; j<6; j++){
sprintf(buffer, RESPATH"/player/deck%i.txt",j);
std::ifstream file(buffer);
if(file){
deckmenu->Add(j, GameState::menuTexts[j]);
file.close();
decksneeded = 0;
}
}
decksneeded = 1;
deckmenu = NEW SimpleMenu(DUEL_MENU_CHOOSE_DECK, this, mFont, 35, 25, "Choose a Deck");
char buffer[100];
for (int j=1; j<6; j++){
sprintf(buffer, RESPATH"/player/deck%i.txt",j);
std::ifstream file(buffer);
if(file){
deckmenu->Add(j, GameState::menuTexts[j]);
file.close();
decksneeded = 0;
}
}
}
}
}
@@ -110,6 +111,19 @@ void GameStateDuel::Start()
}
void GameStateDuel::loadPlayerMomir(int playerId, int isAI){
char * deckFile = RESPATH"/player/momir.txt";
char * deckFileSmall = "momir";
MTGDeck * tempDeck = NEW MTGDeck(deckFile, NULL, mParent->collection);
deck[playerId] = NEW MTGPlayerCards(mParent->collection,tempDeck);
if (!isAI){ //Human Player
mPlayers[playerId] = NEW HumanPlayer(deck[playerId],deckFileSmall);
}else{
mPlayers[playerId] = NEW AIMomirPlayer(deck[playerId],deckFile,"");
}
delete tempDeck;
}
void GameStateDuel::loadPlayer(int playerId, int decknb, int isAI){
if (decknb){
if (!isAI){ //Human Player
@@ -197,7 +211,14 @@ void GameStateDuel::Update(float dt)
mParent->SetNextState(GAME_STATE_DECK_VIEWER);
break;
case DUEL_STATE_CHOOSE_DECK1:
if (mParent->players[0] == PLAYER_TYPE_HUMAN)
if (mParent->gameType == GAME_TYPE_MOMIR){
for (int i = 0; i < 2; i++){
int isAI = 1;
if (mParent->players[i] == PLAYER_TYPE_HUMAN) isAI = 0;
loadPlayerMomir(i, isAI);
}
mGamePhase = DUEL_STATE_PLAY;
}else if (mParent->players[0] == PLAYER_TYPE_HUMAN)
deckmenu->Update(dt);
#ifdef TESTSUITE
else if (mParent->players[1] == PLAYER_TYPE_TESTSUITE){
@@ -280,13 +301,19 @@ void GameStateDuel::Update(float dt)
case DUEL_STATE_PLAY:
//Stop the music before starting the game
if (GameApp::music){
JSoundSystem::GetInstance()->StopMusic(GameApp::music);
SAFE_DELETE(GameApp::music);
JSoundSystem::GetInstance()->StopMusic(GameApp::music);
SAFE_DELETE(GameApp::music);
}
if (!game){
GameObserver::Init(mPlayers, 2);
game = GameObserver::GetInstance();
game->startGame();
GameObserver::Init(mPlayers, 2);
game = GameObserver::GetInstance();
game->startGame();
if (mParent->gameType == GAME_TYPE_MOMIR){
game->addObserver(NEW MTGMomirRule(-1, mParent->collection));
for (int i = 0; i < 2; i++){
game->players[i]->life+=4;
}
}
}
game->Update(dt);
if (game->gameOver){
@@ -303,6 +330,16 @@ void GameStateDuel::Update(float dt)
unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96);
GameOptions::GetInstance()->values[OPTIONS_DIFFICULTY_MODE_UNLOCKED] = GameOption(1);
GameOptions::GetInstance()->save();
}else{
unlocked = isMomirUnlocked();
if (unlocked){
unlockedTex = JRenderer::GetInstance()->LoadTexture("graphics/momir_unlocked.png", TEX_TYPE_USE_VRAM);
unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96);
GameOptions::GetInstance()->values[OPTIONS_MOMIR_MODE_UNLOCKED] = GameOption(1);
GameOptions::GetInstance()->save();
}
}
if (unlocked){
JSample * sample = SampleCache::GetInstance()->getSample("sound/sfx/bonus.wav");
if (sample) JSoundSystem::GetInstance()->PlaySample(sample);
}
@@ -496,4 +533,11 @@ int GameStateDuel::isDifficultyUnlocked(){
}
}
return 0;
}
int GameStateDuel::isMomirUnlocked(){
if (GameOptions::GetInstance()->values[OPTIONS_MOMIR_MODE_UNLOCKED].getIntValue()) return 0;
Player *p = mPlayers[0];
if (p->game->inPlay->countByType("land") == 8) return 1;
return 0;
}
+44 -31
View File
@@ -47,7 +47,9 @@ enum
SUBMENUITEM_2PLAYER,
SUBMENUITEM_DEMO,
SUBMENUITEM_CANCEL,
SUBMENUITEM_TESTSUITE
SUBMENUITEM_TESTSUITE,
SUBMENUITEM_MOMIR,
SUBMENUITEM_CLASSIC,
};
@@ -55,6 +57,7 @@ GameStateMenu::GameStateMenu(GameApp* parent): GameState(parent)
{
mGuiController = NULL;
subMenuController = NULL;
gameTypeMenu = NULL;
mIconsTexture = NULL;
//bgMusic = NULL;
timeIndex = 0;
@@ -118,6 +121,7 @@ void GameStateMenu::Destroy()
{
SAFE_DELETE(mGuiController);
SAFE_DELETE(subMenuController);
SAFE_DELETE(gameTypeMenu);
SAFE_DELETE(mIconsTexture);
for (int i = 0; i < 10 ; i++){
@@ -148,6 +152,9 @@ void GameStateMenu::Start(){
JSoundSystem::GetInstance()->StopMusic(GameApp::music);
SAFE_DELETE(GameApp::music);
}
hasChosenGameType = 1;
if (GameOptions::GetInstance()->values[OPTIONS_MOMIR_MODE_UNLOCKED].getIntValue()) hasChosenGameType =0;
}
@@ -176,13 +183,7 @@ int GameStateMenu::nextCardSet(){
void GameStateMenu::End()
{
//mEngine->EnableVSync(false);
// if (bgMusic)
// {
//JSoundSystem::GetInstance()->StopMusic(bgMusic);
//SAFE_DELETE(bgMusic);
// }
JRenderer::GetInstance()->EnableVSync(false);
}
@@ -190,14 +191,6 @@ void GameStateMenu::End()
void GameStateMenu::Update(float dt)
{
/*
if (GameApp::music){
if (mVolume < 2*GameOptions::GetInstance()->values[OPTIONS_MUSICVOLUME]){
mVolume++;
JSoundSystem::GetInstance()->SetVolume(mVolume/2);
}
}
*/
timeIndex += dt * 2;
switch (MENU_STATE_MAJOR & currentState)
@@ -258,8 +251,19 @@ void GameStateMenu::Update(float dt)
case MENU_STATE_MAJOR_DUEL :
if (MENU_STATE_MINOR_NONE == (currentState & MENU_STATE_MINOR))
{
mParent->SetNextState(GAME_STATE_DUEL);
currentState = MENU_STATE_MAJOR_MAINMENU;
if (!hasChosenGameType){
currentState = MENU_STATE_MAJOR_SUBMENU;
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT);
subMenuController = NEW SimpleMenu(102, this, mFont, 150,60);
if (subMenuController){
subMenuController->Add(SUBMENUITEM_CLASSIC,"Classic");
subMenuController->Add(SUBMENUITEM_MOMIR, "Momir Basic");
subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel");
}
}else{
mParent->SetNextState(GAME_STATE_DUEL);
currentState = MENU_STATE_MAJOR_MAINMENU;
}
}
}
switch (MENU_STATE_MINOR & currentState)
@@ -423,23 +427,18 @@ JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT);
switch (controlId)
{
case MENUITEM_PLAY:
subMenuController = NEW SimpleMenu(102, this, mFont, 150,60);
if (subMenuController){
subMenuController->Add(SUBMENUITEM_1PLAYER,"1 Player");
subMenuController->Add(SUBMENUITEM_2PLAYER, "2 Players");
subMenuController->Add(SUBMENUITEM_DEMO,"Demo");
subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel");
#ifdef TESTSUITE
subMenuController = NEW SimpleMenu(102, this, mFont, 150,60);
#else
subMenuController = NEW SimpleMenu(102, this, mFont, 150,60);
#endif
if (subMenuController){
subMenuController->Add(SUBMENUITEM_1PLAYER,"1 Player");
subMenuController->Add(SUBMENUITEM_2PLAYER, "2 Players");
subMenuController->Add(SUBMENUITEM_DEMO,"Demo");
subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel");
#ifdef TESTSUITE
subMenuController->Add(SUBMENUITEM_TESTSUITE, "Test Suite");
subMenuController->Add(SUBMENUITEM_TESTSUITE, "Test Suite");
#endif
currentState = MENU_STATE_MAJOR_SUBMENU | MENU_STATE_MINOR_NONE;
}
break;
}
break;
case MENUITEM_DECKEDITOR:
mParent->SetNextState(GAME_STATE_DECK_VIEWER);
break;
@@ -474,6 +473,20 @@ JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT);
subMenuController->Close();
currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_SUBMENU_CLOSING;
break;
case SUBMENUITEM_CLASSIC:
this->hasChosenGameType = 1;
mParent->gameType = GAME_TYPE_CLASSIC;
subMenuController->Close();
currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING;
break;
case SUBMENUITEM_MOMIR:
this->hasChosenGameType = 1;
mParent->gameType = GAME_TYPE_MOMIR;
subMenuController->Close();
currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING;
break;
#ifdef TESTSUITE
case SUBMENUITEM_TESTSUITE:
mParent->players[0] = PLAYER_TYPE_TESTSUITE;
+3 -2
View File
@@ -54,6 +54,7 @@ MTGPlayerCards::~MTGPlayerCards(){
SAFE_DELETE(inPlay);
SAFE_DELETE(stack);
SAFE_DELETE(removedFromGame);
SAFE_DELETE(garbage);
}
void MTGPlayerCards::setOwner(Player * player){
@@ -82,6 +83,7 @@ void MTGPlayerCards::init(){
inPlay = NEW MTGInPlay();
stack = NEW MTGStack();
removedFromGame = NEW MTGRemovedFromGame();
garbage = NEW MTGGameZone();
}
@@ -130,8 +132,7 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
if (card->isToken){
if (to != g->players[0]->game->inPlay && to != g->players[1]->game->inPlay){
//Token leaves play: we destroy it
//TODO DELETE Object
garbage->addCard(copy);
return NULL;
}
}
+74 -1
View File
@@ -2,7 +2,7 @@
#include "../include/MTGRules.h"
MTGPutInPlayRule::MTGPutInPlayRule(int _id):MTGAbility(_id, NULL){
aType=MTGAbility::PUT_INTO_PLAY;
}
int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
@@ -78,6 +78,7 @@ int MTGPutInPlayRule::testDestroy(){
}
MTGAttackRule::MTGAttackRule(int _id):MTGAbility(_id,NULL){
aType=MTGAbility::MTG_ATTACK_RULE;
}
int MTGAttackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
@@ -102,6 +103,7 @@ int MTGAttackRule::testDestroy(){
MTGBlockRule::MTGBlockRule(int _id):MTGAbility(_id,NULL){
aType=MTGAbility::MTG_BLOCK_RULE;
}
int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
@@ -134,3 +136,74 @@ int MTGBlockRule::reactToClick(MTGCardInstance * card){
int MTGBlockRule::testDestroy(){
return 0;
}
//
// * Momir
//
MTGMomirRule::MTGMomirRule(int _id, MTGAllCards * _collection):MTGAbility(_id, NULL){
collection = _collection;
alreadyplayed = 0;
aType=MTGAbility::MOMIR;
}
int MTGMomirRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){
if (alreadyplayed) return 0;
Player * player = game->currentlyActing();
Player * currentPlayer = game->currentPlayer;
LOG("CANPUTINPLAY- check if card belongs to current player\n");
if (!player->game->hand->hasCard(card)) return 0;
LOG("CANPUTINPLAY- check if card is land or can be played\n");
if (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)){
LOG("CANPUTINPLAY- correct time to play\n");
return 1;
}
return 0;
}
int MTGMomirRule::reactToClick(MTGCardInstance * card_to_discard){
if (!isReactingToClick(card_to_discard)) return 0;
Player * player = game->currentlyActing();
ManaCost * cost = player->getManaPool();
int converted = cost->getConvertedCost();
player->getManaPool()->pay(cost);
player->game->putInZone(card_to_discard, player->game->hand, player->game->graveyard);
MTGCardInstance * card = genRandomCreature(converted); //TODO code this function
player->game->stack->addCard(card);
Spell * spell = NEW Spell(card);
spell->resolve();
spell->source->isToken = 1;
delete spell;
alreadyplayed = 1;
return 1;
}
MTGCardInstance * MTGMomirRule::genRandomCreature(int convertedCost){
Player * p = game->currentlyActing();
int total_cards = collection->totalCards();
int start = (rand() % total_cards);
int id2 = start;
while (id2 < total_cards){
MTGCard * card = collection->collection[id2];
if (card->isACreature() && card->getManaCost()->getConvertedCost() == convertedCost){
return NEW MTGCardInstance(card,p->game);
}
id2++;
if (id2 == start) return NULL;
if (id2 == total_cards) id2 = 0;
}
return NULL;
}
//The Momir rule is never destroyed
int MTGMomirRule::testDestroy(){
return 0;
}
void MTGMomirRule::Update(float dt){
if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UNTAP){
alreadyplayed = 0;
}
MTGAbility::Update(dt);
}