* Fix almost all tests.
* This version "nearly" works.
This commit is contained in:
jean.chalard
2009-09-07 14:37:32 +00:00
parent 635c87202a
commit 5b473a1505
19 changed files with 160 additions and 106 deletions

View File

@@ -14,6 +14,7 @@ generic/legendary.txt
generic/lifelink.txt
generic/persist.txt
generic/persist2.txt
generic/phases.txt
generic/rampage.txt
generic/regenerate.txt
generic/sacrifice.txt
@@ -201,4 +202,4 @@ zombify.txt
#Momir Basic Tests
########################
momir/keldon_warlord.txt
momir/overcost.txt
momir/overcost.txt

View File

@@ -17,6 +17,8 @@ belligerent hatchling
next
#blockers
next
#first strike
next
#damage
next
#end of combat
@@ -27,4 +29,4 @@ inplay:belligerent hatchling
graveyard:shock
[PLAYER2]
life:15
[END]
[END]

View File

@@ -16,6 +16,8 @@ swamp
benalish knight
benalish knight
next
#first strike
next
#damage
next
#end
@@ -25,4 +27,4 @@ COMBATEND
graveyard:grizzly bears
[PLAYER2]
inplay:plains,mountain,swamp,benalish knight
[END]
[END]

View File

@@ -11,6 +11,7 @@ next
1250
next
next
next
1370
[ASSERT]
COMBATEND
@@ -18,4 +19,4 @@ COMBATEND
inplay:1370
[PLAYER2]
graveyard:1250
[END]
[END]

View File

@@ -2,20 +2,20 @@
[INIT]
COMBATATTACKERS
[PLAYER1]
inplay:1370
inplay:white knight
[PLAYER2]
inplay:1290
inplay:fire elemental
[DO]
1370
white knight
next
1290
fire elemental
next
next
1370
fire elemental
[ASSERT]
COMBATEND
[PLAYER1]
graveyard:1370
graveyard:white knight
[PLAYER2]
inplay:1290
[END]
inplay:fire elemental
[END]

View File

@@ -25,4 +25,4 @@ graveyard:Puppeteer
[PLAYER2]
graveyard:Drudge Skeletons
inplay:raging goblin
[END]
[END]

View File

@@ -15,7 +15,7 @@ Drudge Skeletons
next
#blockers order
dragon engine
dragon engine
Drudge Skeletons
next
#combat damage
next
@@ -27,4 +27,4 @@ graveyard:grizzly bears
[PLAYER2]
graveyard:Drudge Skeletons,raging goblin
inplay:dragon engine
[END]
[END]

View File

@@ -0,0 +1,23 @@
#Pass phases
[INIT]
FIRSTMAIN
[PLAYER1]
[PLAYER2]
[DO]
next
#combat begin
next
#attackers
next
#blockers
next
#damage
next
#combat end
[ASSERT]
COMBATEND
[PLAYER1]
life:20
[PLAYER2]
life:20
[END]

View File

@@ -19,11 +19,12 @@ class GuiCombat : public GuiLayer
DamagerDamaged* current;
enum { BLK, ATK, OK, NONE } cursor_pos;
CombatStep step;
void validateDamage();
void addOne(DefenserDamaged* blocker, CombatStep);
void removeOne(DefenserDamaged* blocker, CombatStep);
void autoaffectDamage(AttackerDamaged* attacker, CombatStep);
void remaskBlkViews(AttackerDamaged* before, AttackerDamaged* after);
void resolve();
int resolve();
public:
GuiCombat(GameObserver* go);

View File

@@ -10,7 +10,7 @@ using std::list;
class Player;
typedef enum { BLOCKERS, ORDER, FIRST_STRIKE, DAMAGE } CombatStep;
typedef enum { BLOCKERS, ORDER, FIRST_STRIKE, END_FIRST_STRIKE, DAMAGE, END_DAMAGE } CombatStep;
class Phase{
public:
int id;

View File

@@ -38,6 +38,7 @@ struct WEventZoneChange : public WEvent {
struct WEventDamage : public WEvent {
Damage * damage;
WEventDamage(Damage * damage);
virtual std::ostream& toString(std::ostream& out) const;
};
struct WEventPhaseChange : public WEvent {

View File

@@ -18,7 +18,7 @@
*/
int NextGamePhase::resolve(){
GameObserver::GetInstance()->nextGamePhase();
GameObserver::GetInstance()->userRequestNextGamePhase();
return 1;
}

View File

@@ -61,7 +61,9 @@ void DamagerDamaged::Render(CombatStep mode)
mFont->SetColor(ARGB(92,255,255,255));
break;
case FIRST_STRIKE :
case END_FIRST_STRIKE :
case DAMAGE :
case END_DAMAGE :
mFont->SetColor(ARGB(255, 255, 64, 0));
break;
}

View File

@@ -124,8 +124,10 @@ int DuelLayers::receiveEvent(WEvent * e){
PRINT_IF(WEventCreatureAttacker);
PRINT_IF(WEventCreatureBlocker);
PRINT_IF(WEventCreatureBlockerRank);
PRINT_IF(WEventCombatStepChange);
PRINT_IF(WEventEngageMana);
PRINT_IF(WEventConsumeMana);
PRINT_IF(WEventEmptyManaPool);
#endif
int used = 0;

View File

@@ -82,11 +82,11 @@ void GameObserver::nextPlayer(){
}
void GameObserver::nextGamePhase(){
Phase * cPhaseOld = phaseRing->getCurrentPhase();
if (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS)
if (DAMAGE != combatStep) { nextCombatStep(); return; }
phaseRing->forward();
Phase * cPhase = phaseRing->getCurrentPhase();
currentGamePhase = cPhase->id;
if (Constants::MTG_PHASE_COMBATDAMAGE == currentGamePhase)
nextCombatStep();
if (currentPlayer != cPhase->player) nextPlayer();
@@ -99,16 +99,14 @@ void GameObserver::nextGamePhase(){
return nextGamePhase();
}
for (int i=0; i < 2; i++){
for (int i = 0; i < 2; ++i)
players[i]->getManaPool()->init();
}
//After End of turn
if (currentGamePhase == Constants::MTG_PHASE_AFTER_EOT){
//Auto Hand cleaning, in case the player didn't do it himself
while(currentPlayer->game->hand->nb_cards > 7){
while(currentPlayer->game->hand->nb_cards > 7)
currentPlayer->game->putInGraveyard(currentPlayer->game->hand->cards[0]);
}
mLayers->stackLayer()->garbageCollect(); //clean stack history for this turn;
mLayers->actionLayer()->Update(0);
for (int i=0; i < 2; i++){
@@ -141,26 +139,24 @@ void GameObserver::nextCombatStep()
{
switch (combatStep)
{
case BLOCKERS : receiveEvent(NEW WEventCombatStepChange(combatStep = ORDER)); return;
case ORDER : receiveEvent(NEW WEventCombatStepChange(combatStep = FIRST_STRIKE)); return;
case FIRST_STRIKE : receiveEvent(NEW WEventCombatStepChange(combatStep = DAMAGE)); return;
case DAMAGE : ; // Nothing : go to next phase
case BLOCKERS : receiveEvent(NEW WEventCombatStepChange(combatStep = ORDER)); return;
case ORDER : receiveEvent(NEW WEventCombatStepChange(combatStep = FIRST_STRIKE)); return;
case FIRST_STRIKE : receiveEvent(NEW WEventCombatStepChange(combatStep = END_FIRST_STRIKE)); return;
case END_FIRST_STRIKE : receiveEvent(NEW WEventCombatStepChange(combatStep = DAMAGE)); return;
case DAMAGE : receiveEvent(NEW WEventCombatStepChange(combatStep = END_DAMAGE)); return;
case END_DAMAGE : ; // Nothing : go to next phase
}
}
void GameObserver::userRequestNextGamePhase(){
if (mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)) return;
if (getCurrentTargetChooser()) return;
// if (mLayers->combatLayer()->isDisplayed()) return;
Phase * cPhaseOld = phaseRing->getCurrentPhase();
if (cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE)
if (FIRST_STRIKE == combatStep || END_FIRST_STRIKE == combatStep || DAMAGE == combatStep) { nextCombatStep(); return; }
if (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS)
if (DAMAGE != combatStep) { nextCombatStep(); return; }
if (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS ||
opponent()->isAI() ||
options[GameOptions::phaseInterrupts[currentGamePhase]].number)
mLayers->stackLayer()->AddNextGamePhase();
else
nextGamePhase();
if (BLOCKERS == combatStep) { nextCombatStep(); return; }
nextGamePhase();
}
int GameObserver::forceShuffleLibraries(){
@@ -356,11 +352,10 @@ void GameObserver::cardClick (MTGCardInstance * card, Targetable * object){
}else{
result = targetChooser->toggleTarget(clickedPlayer);
}
if (result == TARGET_OK_FULL){
if (result == TARGET_OK_FULL)
card = cardWaitingForTargets;
}else{
else
return;
}
}
if (waitForExtraPayment){
@@ -374,6 +369,12 @@ void GameObserver::cardClick (MTGCardInstance * card, Targetable * object){
return;
}
if (ORDER == combatStep)
{
card->defenser->raiseBlockerRankOrder(card);
return;
}
if (card){
reaction = mLayers->actionLayer()->isReactingToClick(card);
if (reaction == -1) mLayers->actionLayer()->reactToClick(card);
@@ -468,4 +469,3 @@ int GameObserver::targetListIsSet(MTGCardInstance * card){
}
return (targetChooser->targetListSet());
}

View File

@@ -76,6 +76,16 @@ void GuiCombat::remaskBlkViews(AttackerDamaged* before, AttackerDamaged* after)
}
}
void GuiCombat::validateDamage()
{
switch (step)
{
case FIRST_STRIKE : resolve(); go->nextCombatStep(); break;
case DAMAGE : resolve(); go->userRequestNextGamePhase(); break;
default: cout << "COMBAT : Cannot validate damage in this phase" << endl; break;
}
}
void GuiCombat::autoaffectDamage(AttackerDamaged* attacker, CombatStep step)
{
attacker->clearDamage();
@@ -115,18 +125,20 @@ bool GuiCombat::CheckUserInput(u32 key)
{
case PSP_CTRL_CIRCLE:
if (BLK == cursor_pos)
if (ORDER == step) { activeAtk->card->raiseBlockerRankOrder(active->card); }
else
{
signed damage = activeAtk->card->stepPower(step);
for (vector<DamagerDamaged*>::iterator it = activeAtk->blockers.begin(); *it != active; ++it)
damage -= (*it)->sumDamages();
signed now = active->sumDamages();
damage -= now;
if (damage > 0) addOne(active, step);
else
for (now -= active->card->toughness; now >= 0; --now) removeOne(active, step);
}
{
if (ORDER == step) go->cardClick(active->card); // { activeAtk->card->raiseBlockerRankOrder(active->card); }
else
{
signed damage = activeAtk->card->stepPower(step);
for (vector<DamagerDamaged*>::iterator it = activeAtk->blockers.begin(); *it != active; ++it)
damage -= (*it)->sumDamages();
signed now = active->sumDamages();
damage -= now;
if (damage > 0) addOne(active, step);
else
for (now -= active->card->toughness; now >= 0; --now) removeOne(active, step);
}
}
else if (ATK == cursor_pos)
{
active = activeAtk->blockers.front();
@@ -137,10 +149,12 @@ bool GuiCombat::CheckUserInput(u32 key)
{
switch (step)
{
case BLOCKERS : assert(false); break; // that should not happen
case ORDER : go->receiveEvent(NEW WEventCombatStepChange(FIRST_STRIKE)); break;
case FIRST_STRIKE : resolve(); go->receiveEvent(NEW WEventCombatStepChange(DAMAGE)); break;
case DAMAGE : resolve(); cursor_pos = NONE; go->userRequestNextGamePhase(); break;
case BLOCKERS : assert(false); break; // that should not happen
case ORDER : go->userRequestNextGamePhase(); break;
case FIRST_STRIKE :
case DAMAGE : validateDamage(); break;
case END_FIRST_STRIKE :
case END_DAMAGE : break; // nothing;
}
}
break;
@@ -239,13 +253,17 @@ void GuiCombat::Render()
}
}
void GuiCombat::resolve()
int GuiCombat::resolve() // Returns the number of damage objects dealt this turn.
{
DamageStack* stack = NEW DamageStack();
for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
{
if ((*it)->blockers.empty())
stack->Add(NEW Damage((*it)->card, go->opponent(), (*it)->card->stepPower(step)));
{
int dmg = (*it)->card->stepPower(step);
if (dmg > 0)
stack->Add(NEW Damage((*it)->card, go->opponent(), dmg));
}
else
for (vector<DefenserDamaged*>::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q)
for (vector<Damage>::iterator d = (*q)->damages.begin(); d != (*q)->damages.end(); ++d)
@@ -254,7 +272,9 @@ void GuiCombat::resolve()
stack->Add(NEW Damage(*d));
}
go->mLayers->stackLayer()->Add(stack);
go->mLayers->stackLayer()->resolve(); // This will delete the damage stack which will in turn delete the Damage it contains
int v = stack->mCount;
if (v > 0) go->mLayers->stackLayer()->resolve(); // This will delete the damage stack which will in turn delete the Damage it contains
return v;
}
int GuiCombat::receiveEventPlus(WEvent* e)
@@ -307,9 +327,10 @@ int GuiCombat::receiveEventMinus(WEvent* e)
if (go->players[0]->game->inPlay == event->from || go->players[1]->game->inPlay == event->from)
{
for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
if ((*it)->card == event->card)
if ((*it)->card == event->card->previous)
{
AttackerDamaged* d = *it;
if (activeAtk == *it) activeAtk = NULL;
attackers.erase(it);
SAFE_DELETE(d);
return 1;
@@ -352,8 +373,11 @@ int GuiCombat::receiveEventMinus(WEvent* e)
}
return 0;
}
else if (dynamic_cast<WEventPhaseChange*>(e))
step = BLOCKERS;
else if (WEventPhaseChange* event = dynamic_cast<WEventPhaseChange*>(e))
{
if (Constants::MTG_PHASE_COMBATDAMAGE == event->to->id) step = BLOCKERS;
else cursor_pos = NONE;
}
else if (WEventCombatStepChange* event = dynamic_cast<WEventCombatStepChange*>(e))
switch (event->step)
{
@@ -379,25 +403,33 @@ int GuiCombat::receiveEventMinus(WEvent* e)
repos<AttackerDamaged>(attackers.begin(), attackers.end(), 0);
if (active)
{
active->zoom = 2.7; // We know there is at least one, so this cannot be NULL
active->zoom = 2.7;
activeAtk = static_cast<AttackerDamaged*>(active);
remaskBlkViews(NULL, static_cast<AttackerDamaged*>(active));
cursor_pos = ATK;
step = ORDER;
}
else
go->nextCombatStep();
go->userRequestNextGamePhase();
return 1;
}
case FIRST_STRIKE:
step = FIRST_STRIKE;
for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker)
if ((*attacker)->card->has(Constants::FIRSTSTRIKE) || (*attacker)->card->has(Constants::DOUBLESTRIKE)) goto DAMAGE;
cout << "FIRST STRIKE" << endl;
go->nextCombatStep();
break;
case END_FIRST_STRIKE:
step = END_FIRST_STRIKE;
for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker)
autoaffectDamage(*attacker, FIRST_STRIKE);
resolve();
go->nextCombatStep();
if (0 == resolve())
go->nextCombatStep();
else
{
cout << "ASK INTERRUPT" << endl;
go->mLayers->stackLayer()->AddNextGamePhase();
}
return 1;
case DAMAGE: DAMAGE:
step = event->step;
@@ -417,11 +449,11 @@ int GuiCombat::receiveEventMinus(WEvent* e)
cursor_pos = ATK;
}
else
{
resolve();
if (FIRST_STRIKE == step) go->nextCombatStep();
else go->userRequestNextGamePhase();
}
go->nextCombatStep();
return 1;
case END_DAMAGE:
step = END_DAMAGE;
if (resolve()) go->userRequestNextGamePhase();
return 1;
}
return 0;

View File

@@ -630,8 +630,10 @@ int MTGCardInstance::stepPower(CombatStep step)
switch (step)
{
case FIRST_STRIKE :
case END_FIRST_STRIKE :
if (has(Constants::FIRSTSTRIKE) || has(Constants::DOUBLESTRIKE)) return MAX(0, power); else return 0;
case DAMAGE :
case END_DAMAGE :
default :
if (has(Constants::FIRSTSTRIKE)) return 0; else return MAX(0, power);
}

View File

@@ -100,27 +100,15 @@ int TestSuiteAI::Act(float dt){
humanMode = 1;
return 1;
}
else if (action.compare("next")==0){
/*
if (drl->orderingIsNeeded){
drl->blockersOrderingDone();
else if (action.compare("next")==0)
g->userRequestNextGamePhase();
}else if (drl->mCount){
OutputDebugString("End of combat damage!\n");
drl->nextPlayer();
g->userRequestNextGamePhase();
}else{ */
g->userRequestNextGamePhase();
/*}
*/
}else if (action.compare("yes")==0){
else if (action.compare("yes")==0)
g->mLayers->stackLayer()->setIsInterrupting(this);
}else if (action.compare("endinterruption")==0){
else if (action.compare("endinterruption")==0)
g->mLayers->stackLayer()->endOfInterruption();
}else if(action.compare("no")==0){
if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this){
else if(action.compare("no")==0){
if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this)
g->mLayers->stackLayer()->cancelInterruptOffer();
}
}else if(action.find("choice ")!=string::npos){
OutputDebugString("TESTSUITE choice !!!\n");
int choice = atoi(action.substr(action.find("choice ") + 7).c_str());
@@ -144,27 +132,15 @@ int TestSuiteAI::Act(float dt){
sprintf(buffe, "TESTSUITE CARD ID : %i\n", mtgid);
OutputDebugString(buffe);
Interruptible * toInterrupt = suite->getActionByMTGId(mtgid);
if (toInterrupt){
g->stackObjectClicked(toInterrupt);
}else{
if (toInterrupt)
g->stackObjectClicked(toInterrupt);
else{
MTGCardInstance * card = suite->getCardByMTGId(mtgid);
if (card) {
OutputDebugString("TESTSUITE Clicking ON: ");
OutputDebugString(card->name.c_str());
OutputDebugString("\n");
/*
if (drl->mCount){
if (drl->orderingIsNeeded){
OutputDebugString(" Ordering Card\n");
drl->clickReorderBlocker(card);
}else{
OutputDebugString(" Damaging Card\n");
drl->clickDamage(card);
}
}else{*/
g->cardClick(card,card);
/* }
*/
g->cardClick(card,card);
}
}
}else{
@@ -414,7 +390,9 @@ TestSuite::TestSuite(const char * filename,MTGAllCards* _collection){
ofstream file2 (RESPATH"/test/results.html");
if (file2){
file2 << "<html><head>";
#ifdef WIN32
file2 << "<meta http-equiv=\"refresh\" content=\"10\" >";
#endif
file2 << "<STYLE type='text/css'>";
file2 << ".success {color:green}\n";
file2 << ".error {color:red}\n";

View File

@@ -34,7 +34,14 @@ std::ostream& WEvent::toString(std::ostream& out) const
}
std::ostream& WEventZoneChange::toString(std::ostream& out) const
{
return out << "EVENT " << *card << " : " << *from << " " << *to;
return out << "ZONEEVENT " << *card << " : " << *from << " -> " << *to;
}
std::ostream& WEventDamage::toString(std::ostream& out) const
{
if (MTGCardInstance* m = dynamic_cast<MTGCardInstance*>(damage->target))
return out << "DAMAGEEVENT " << damage->damage << " >> " << *m;
else
return out << "DAMAGEEVENT " << damage->damage << " >> " << damage->target;
}
std::ostream& operator<<(std::ostream& out, const WEvent& m)
{