mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 05:09:16 -08:00
Improving implementation of cards which use voting (WIP) (#7566)
* created interface for handling voting * created class for two choice votes, refactored a card to use it * refactored all cards which use two choice votes * updated VoteHandler to an abstract class to encapsulate more of its functions * refactored cards which vote for more than two things * [CNS] Implemented Brago's Representative * [CN2] Implemented Ballot Broker * [CN2] Implemented Illusion of Choice * [CNS] Implemented Grudge Keeper * added vote outcomes * updated implementation of Illusion of Choice to work correctly in multiples * added test for voting * updated implementation of extra votes * simplified vote message handling * Improved names, additional comments * Votes: fixed not working getMostVoted * Votes: added final vote results to game logs; * Votes: added additional info for the vote choices; * Votes: added vote step info in choose dialogs, added AI support example for Tyrant's Choice; Co-authored-by: Oleg Agafonov <jaydi85@gmail.com>
This commit is contained in:
parent
991f154cd7
commit
1cbbcddcc6
32 changed files with 1615 additions and 786 deletions
|
|
@ -0,0 +1,314 @@
|
|||
package org.mage.test.multiplayer;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestCommander4PlayersWithAIHelps;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class VotingTest extends CardTestCommander4PlayersWithAIHelps {
|
||||
|
||||
// Player order: A -> D -> C -> B
|
||||
|
||||
// Council’s dilemma — When Lieutenants of the Guard enters the battlefield, starting with you,
|
||||
// each player votes for strength or numbers. Put a +1/+1 counter on Lieutenants of the Guard
|
||||
// for each strength vote and create a 1/1 white Soldier creature token for each numbers vote.
|
||||
private static final String lieutenant = "Lieutenants of the Guard";
|
||||
|
||||
// While voting, you get an additional vote. (The votes can be for different choices or for the same choice.)
|
||||
private static final String rep = "Brago's Representative";
|
||||
|
||||
// While voting, you may vote an additional time. (The votes can be for different choices or for the same choice.)
|
||||
private static final String broker = "Ballot Broker";
|
||||
|
||||
// You choose how each player votes this turn.
|
||||
private static final String illusion = "Illusion of Choice";
|
||||
|
||||
// TODO: add test with broker
|
||||
// rulues:
|
||||
// The ability only affects spells and abilities that use the word “vote.” Other cards that involve choices,
|
||||
// such as Archangel of Strife, are unaffected.
|
||||
// (2016-08-23)
|
||||
|
||||
// Whenever players finish voting, each opponent who voted for a choice you didn’t vote for loses 2 life.
|
||||
private static final String keeper = "Grudge Keeper";
|
||||
|
||||
// Will of the council - Starting with you, each player votes for death or torture. If death gets more votes,
|
||||
// each opponent sacrifices a creature. If torture gets more votes or the vote is tied, each opponent loses 4 life.
|
||||
private static final String tyrant = "Tyrant's Choice";
|
||||
|
||||
private void setChoices(String choice) {
|
||||
setChoices(choice, choice, choice, choice);
|
||||
}
|
||||
|
||||
private void setChoices(String choiceA, String choiceB, String choiceC, String choiceD) {
|
||||
setChoice(playerA, choiceA);
|
||||
setChoice(playerB, choiceB);
|
||||
setChoice(playerC, choiceC);
|
||||
setChoice(playerD, choiceD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_LieutenantsOfTheGuard_1() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoices("Yes");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 6, 6);
|
||||
assertPermanentCount(playerA, "Soldier", 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_LieutenantsOfTheGuard_2() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoices("No");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 2, 2);
|
||||
assertPermanentCount(playerA, "Soldier", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_LieutenantsOfTheGuard_3() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoices("Yes", "Yes", "No", "No");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 4, 4);
|
||||
assertPermanentCount(playerA, "Soldier", 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_TyrantsChoice_AI_Normal() {
|
||||
addCard(Zone.HAND, playerA, tyrant); // {1}{B}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
|
||||
// ai play
|
||||
// opponents must have more votes so final result is sacrifice (best for opponents)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, tyrant);
|
||||
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerB);
|
||||
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerC);
|
||||
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerD);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, tyrant, 1);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
assertLife(playerC, 20);
|
||||
assertLife(playerD, 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // TODO: fix after merge, see player.isComputer
|
||||
public void test_TyrantsChoice_AI_UnderControl() {
|
||||
addCard(Zone.HAND, playerA, tyrant); // {1}{B}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
//
|
||||
addCard(Zone.HAND, playerA, illusion, 1); // {U}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
|
||||
// prepare vote control
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, illusion);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkGraveyardCount("prepare", 1, PhaseStep.PRECOMBAT_MAIN, playerA, illusion, 1);
|
||||
|
||||
// ai play
|
||||
// you control the opponents, so votes result must be lose life (best for controller)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, tyrant);
|
||||
checkStackSize("before resolve", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 1);
|
||||
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerB);
|
||||
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerC);
|
||||
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerD);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, tyrant, 1);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20 - 4);
|
||||
assertLife(playerC, 20 - 4);
|
||||
assertLife(playerD, 20 - 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_BragosRepresentative() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, rep);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoice(playerA, "Yes");
|
||||
setChoices("Yes", "Yes", "No", "No");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 5, 5);
|
||||
assertPermanentCount(playerA, "Soldier", 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_BallotBroker() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, broker);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoices("Yes", "Yes", "No", "No");
|
||||
setChoice(playerA, "Yes"); // to have an additional vote
|
||||
setChoice(playerA, "No"); // the additional vote
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 4, 4);
|
||||
assertPermanentCount(playerA, "Soldier", 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_IllusionOfChoice_Single() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 6);
|
||||
addCard(Zone.HAND, playerA, illusion);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, illusion);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoice(playerA, "Yes", 4);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 6, 6);
|
||||
assertPermanentCount(playerA, "Soldier", 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_IllusionOfChoice_WithBragosRepresentative() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerB, rep);
|
||||
addCard(Zone.HAND, playerA, illusion);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, illusion);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoice(playerA, "Yes", 5);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 7, 7);
|
||||
assertPermanentCount(playerA, "Soldier", 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_IllusionOfChoice_Double() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island");
|
||||
addCard(Zone.HAND, playerA, illusion);
|
||||
addCard(Zone.HAND, playerB, illusion);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, illusion);
|
||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, illusion);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoice(playerB, "Yes", 4);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 6, 6);
|
||||
assertPermanentCount(playerA, "Soldier", 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_GrudgeKeeper_1() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, keeper);
|
||||
addCard(Zone.BATTLEFIELD, playerB, rep);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoice(playerB, "Yes");
|
||||
setChoices("Yes", "No", "No", "No");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 4, 4);
|
||||
assertPermanentCount(playerA, "Soldier", 3);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20 - 2);
|
||||
assertLife(playerC, 20 - 2);
|
||||
assertLife(playerD, 20 - 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_GrudgeKeeper_2() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, keeper);
|
||||
addCard(Zone.BATTLEFIELD, playerA, rep);
|
||||
addCard(Zone.BATTLEFIELD, playerB, rep);
|
||||
addCard(Zone.HAND, playerA, lieutenant);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, lieutenant);
|
||||
setChoice(playerA, "No");
|
||||
setChoice(playerB, "No");
|
||||
setChoices("Yes");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, lieutenant, 6, 6);
|
||||
assertPermanentCount(playerA, "Soldier", 2);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
assertLife(playerC, 20);
|
||||
assertLife(playerD, 20);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package org.mage.test.serverside.base;
|
||||
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import org.mage.test.player.TestComputerPlayer7;
|
||||
import org.mage.test.player.TestPlayer;
|
||||
|
||||
/**
|
||||
* See more details in CardTestPlayerBaseWithAIHelps
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public abstract class CardTestCommander4PlayersWithAIHelps extends CardTestCommander4Players {
|
||||
|
||||
@Override
|
||||
protected TestPlayer createPlayer(String name, RangeOfInfluence rangeOfInfluence) {
|
||||
// use same RangeOfInfluence.ALL as CardTestCommander4Players do
|
||||
TestPlayer testPlayer = new TestPlayer(new TestComputerPlayer7(name, RangeOfInfluence.ALL, 6));
|
||||
testPlayer.setAIPlayer(false); // AI can't play it by itself, use AI commands
|
||||
return testPlayer;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,9 +5,7 @@ import org.mage.test.player.TestComputerPlayerMonteCarlo;
|
|||
import org.mage.test.player.TestPlayer;
|
||||
|
||||
/**
|
||||
* Base class but with Monte Carlo computer player to test single AI commands (it's different from full AI simulation from CardTestPlayerBaseAI):
|
||||
* 1. AI don't play normal priorities (you must use ai*** commands to play it);
|
||||
* 2. AI will choose in non strict mode (it's simulated ComputerPlayerMCTS, not simple ComputerPlayer from basic tests)
|
||||
* See more details in CardTestPlayerBaseWithAIHelps
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue