1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-10 17:00:08 -09:00
This commit is contained in:
BetaSteward 2010-09-01 03:01:43 +00:00
parent df642c2bd5
commit 3fa0e8b8f4
544 changed files with 13327 additions and 3074 deletions
Mage.Client
Mage.Common/src/mage
Mage.Deck.Constructed/src/mage/deck
Mage.Game.FreeForAll/src/mage/game
Mage.Game.TwoPlayerDuel/src/mage/game
Mage.Player.AI
nbproject
src/mage/player/ai
Mage.Player.AIMinimax
Mage.Player.Human/src/mage/player/human
Mage.Server
Mage.Sets/src/mage/sets

View file

@ -1,7 +1,10 @@
server-name=localhost server-name=localhost
port=17171 port=17171
remote-server=mage-server remote-server=mage-server
cards-resource-path=resources/images/cards/ cards-resource-path=C:\\Program Files (x86)\\Wizards of the Coast\\Magic Online III\\Graphics\\Cards\\
symbols-resource-path=resources/images/symbols/ symbols-resource-path=C:\\Program Files (x86)\\Wizards of the Coast\\Magic Online III\\Graphics\\Chat\\chat_graphic_typingicon_
resource-path=resources/images/ resource-path=C:\\Program Files (x86)\\Wizards of the Coast\\Magic Online III\\Graphics\\Cards\\Pics\\
#cards-resource-path=resources/images/cards/
#symbols-resource-path=resources/images/symbols/
#resource-path=resources/images/
card-scaling-factor=0.4 card-scaling-factor=0.4

View file

@ -20,6 +20,7 @@ debug.test.classpath=\
dist.dir=dist dist.dir=dist
dist.jar=${dist.dir}/Mage.Client.jar dist.jar=${dist.dir}/Mage.Client.jar
dist.javadoc.dir=${dist.dir}/javadoc dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes= excludes=
includes=** includes=**
jar.compress=false jar.compress=false
@ -52,7 +53,7 @@ jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
main.class=mage.client.MageFrame main.class=mage.client.MageFrame
manifest.file=manifest.mf manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF meta.inf.dir=${src.dir}/META-INF
platform.active=default_platform platform.active=JDK_1.6_21
project.license=bsd project.license=bsd
project.Mage=../Mage project.Mage=../Mage
project.Mage_Common=../Mage.Common project.Mage_Common=../Mage.Common

View file

@ -4,6 +4,7 @@
<configuration> <configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3"> <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>Mage.Client</name> <name>Mage.Client</name>
<explicit-platform explicit-source-supported="true"/>
<source-roots> <source-roots>
<root id="src.dir"/> <root id="src.dir"/>
</source-roots> </source-roots>

Binary file not shown.

View file

@ -45,7 +45,9 @@ import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.UIManager; import javax.swing.UIManager;
import mage.client.dialog.AboutDialog; import mage.client.dialog.AboutDialog;
import mage.client.dialog.CombatDialog;
import mage.client.dialog.ConnectDialog; import mage.client.dialog.ConnectDialog;
import mage.client.dialog.PickNumberDialog;
import mage.client.remote.Session; import mage.client.remote.Session;
import mage.client.util.EDTExceptionHandler; import mage.client.util.EDTExceptionHandler;
import mage.util.Logging; import mage.util.Logging;
@ -60,6 +62,8 @@ public class MageFrame extends javax.swing.JFrame {
private static Session session; private static Session session;
private ConnectDialog connectDialog; private ConnectDialog connectDialog;
private static CombatDialog combat;
private static PickNumberDialog pickNumber;
/** /**
* @return the session * @return the session
@ -96,8 +100,12 @@ public class MageFrame extends javax.swing.JFrame {
session = new Session(this); session = new Session(this);
connectDialog = new ConnectDialog(session); connectDialog = new ConnectDialog(session);
combat = new CombatDialog();
pickNumber = new PickNumberDialog();
desktopPane.add(connectDialog, JLayeredPane.POPUP_LAYER); desktopPane.add(connectDialog, JLayeredPane.POPUP_LAYER);
// connectDialog.setLocation(50, 50); desktopPane.add(combat, JLayeredPane.POPUP_LAYER);
combat.hideDialog();
desktopPane.add(pickNumber, JLayeredPane.POPUP_LAYER);
disableButtons(); disableButtons();
} }
@ -311,6 +319,14 @@ public class MageFrame extends javax.swing.JFrame {
this.deckEditorPane.setVisible(false); this.deckEditorPane.setVisible(false);
} }
public static CombatDialog getCombatDialog() {
return combat;
}
public static PickNumberDialog getPickNumberDialog() {
return pickNumber;
}
/** /**
* @param args the command line arguments * @param args the command line arguments
*/ */

View file

@ -63,6 +63,7 @@ import javax.swing.text.StyledDocument;
import mage.Constants.CardType; import mage.Constants.CardType;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.remote.Session; import mage.client.remote.Session;
import mage.client.util.Config;
import mage.client.util.ImageHelper; import mage.client.util.ImageHelper;
import mage.view.CardView; import mage.view.CardView;
@ -79,10 +80,11 @@ public class Card extends javax.swing.JPanel implements MouseMotionListener, Mou
protected Point p; protected Point p;
protected CardDimensions dimension; protected CardDimensions dimension;
protected UUID gameId; protected final UUID gameId;
protected BigCard bigCard; protected final BigCard bigCard;
protected CardView card; protected CardView card;
protected Popup popup; protected Popup popup;
protected boolean popupShowing;
protected TextPopup popupText = new TextPopup(); protected TextPopup popupText = new TextPopup();
protected BufferedImage background; protected BufferedImage background;
@ -97,7 +99,7 @@ public class Card extends javax.swing.JPanel implements MouseMotionListener, Mou
this.gameId = gameId; this.gameId = gameId;
this.card = card; this.card = card;
this.bigCard = bigCard; this.bigCard = bigCard;
small = new BufferedImage(dimension.frameWidth, dimension.frameHeight, BufferedImage.TYPE_INT_RGB); small = new BufferedImage(Config.dimensions.frameWidth, Config.dimensions.frameHeight, BufferedImage.TYPE_INT_RGB);
background = ImageHelper.getBackground(card); background = ImageHelper.getBackground(card);
StyledDocument doc = text.getStyledDocument(); StyledDocument doc = text.getStyledDocument();
@ -136,7 +138,7 @@ public class Card extends javax.swing.JPanel implements MouseMotionListener, Mou
gSmall.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); gSmall.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gSmall.setColor(Color.BLACK); gSmall.setColor(Color.BLACK);
gSmall.drawImage(ImageHelper.ScaleImage(image, dimension.frameWidth, dimension.frameHeight), 0, 0, this); gSmall.drawImage(ImageHelper.ScaleImage(image, Config.dimensions.frameWidth, Config.dimensions.frameHeight), 0, 0, this);
gImage.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE)); gImage.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE));
gImage.drawString(card.getName(), CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET); gImage.drawString(card.getName(), CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET);
@ -152,17 +154,17 @@ public class Card extends javax.swing.JPanel implements MouseMotionListener, Mou
gImage.dispose(); gImage.dispose();
gSmall.setFont(new Font("Arial", Font.PLAIN, dimension.nameFontSize)); gSmall.setFont(new Font("Arial", Font.PLAIN, Config.dimensions.nameFontSize));
gSmall.drawString(card.getName(), dimension.contentXOffset, dimension.nameYOffset); gSmall.drawString(card.getName(), Config.dimensions.contentXOffset, Config.dimensions.nameYOffset);
if (card.getCardTypes().contains(CardType.CREATURE)) { if (card.getCardTypes().contains(CardType.CREATURE)) {
gSmall.drawString(card.getPower() + "/" + card.getToughness(), dimension.powBoxTextLeft, dimension.powBoxTextTop); gSmall.drawString(card.getPower() + "/" + card.getToughness(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop);
} }
else if (card.getCardTypes().contains(CardType.PLANESWALKER)) { else if (card.getCardTypes().contains(CardType.PLANESWALKER)) {
gSmall.drawString(card.getLoyalty(), dimension.powBoxTextLeft, dimension.powBoxTextTop); gSmall.drawString(card.getLoyalty(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop);
} }
if (card.getCardTypes().size() > 0) if (card.getCardTypes().size() > 0)
gSmall.drawString(cardType, dimension.contentXOffset, dimension.typeYOffset); gSmall.drawString(cardType, Config.dimensions.contentXOffset, Config.dimensions.typeYOffset);
drawText(); drawText();
gSmall.dispose(); gSmall.dispose();
@ -187,6 +189,7 @@ public class Card extends javax.swing.JPanel implements MouseMotionListener, Mou
for (String rule: getRules()) { for (String rule: getRules()) {
sb.append("\n").append(rule); sb.append("\n").append(rule);
} }
sb.append("\n").append(card.getId());
return sb.toString(); return sb.toString();
} }
@ -272,7 +275,7 @@ public class Card extends javax.swing.JPanel implements MouseMotionListener, Mou
} else { } else {
g2.setColor(Color.BLACK); g2.setColor(Color.BLACK);
} }
g2.drawRect(0, 0, dimension.frameWidth - 1, dimension.frameHeight - 1); g2.drawRect(0, 0, Config.dimensions.frameWidth - 1, Config.dimensions.frameHeight - 1);
} }
@Override @Override
@ -301,21 +304,27 @@ public class Card extends javax.swing.JPanel implements MouseMotionListener, Mou
@Override @Override
public void mouseEntered(MouseEvent arg0) { public void mouseEntered(MouseEvent arg0) {
if (popup != null) if (!popupShowing) {
if (popup != null)
popup.hide();
PopupFactory factory = PopupFactory.getSharedInstance();
popup = factory.getPopup(this, popupText, (int) this.getLocationOnScreen().getX() + Config.dimensions.frameWidth, (int) this.getLocationOnScreen().getY() + 40);
popup.show();
//hack to get popup to resize to fit text
popup.hide(); popup.hide();
PopupFactory factory = PopupFactory.getSharedInstance(); popup = factory.getPopup(this, popupText, (int) this.getLocationOnScreen().getX() + Config.dimensions.frameWidth, (int) this.getLocationOnScreen().getY() + 40);
popup = factory.getPopup(this, popupText, (int) this.getLocationOnScreen().getX() + dimension.frameWidth, (int) this.getLocationOnScreen().getY() + 40); popup.show();
popup.show(); popupShowing = true;
//hack to get popup to resize to fit text }
popup.hide();
popup = factory.getPopup(this, popupText, (int) this.getLocationOnScreen().getX() + dimension.frameWidth, (int) this.getLocationOnScreen().getY() + 40);
popup.show();
} }
@Override @Override
public void mouseExited(MouseEvent arg0) { public void mouseExited(MouseEvent arg0) {
if (popup != null) if(getMousePosition(true) != null) return;
if (popup != null) {
popup.hide(); popup.hide();
popupShowing = false;
}
} }
@Override @Override

View file

@ -36,19 +36,19 @@ import static mage.client.util.Constants.*;
*/ */
public class CardDimensions { public class CardDimensions {
public static int frameHeight; public int frameHeight;
public static int frameWidth; public int frameWidth;
public static int symbolHeight; public int symbolHeight;
public static int symbolWidth; public int symbolWidth;
public static int contentXOffset; public int contentXOffset;
public static int nameYOffset; public int nameYOffset;
public static int typeYOffset; public int typeYOffset;
public static int textYOffset; public int textYOffset;
public static int textWidth; public int textWidth;
public static int textHeight; public int textHeight;
public static int powBoxTextTop; public int powBoxTextTop;
public static int powBoxTextLeft; public int powBoxTextLeft;
public static int nameFontSize; public int nameFontSize;
public CardDimensions(double scaleFactor) { public CardDimensions(double scaleFactor) {
frameHeight = (int)(FRAME_MAX_HEIGHT * scaleFactor); frameHeight = (int)(FRAME_MAX_HEIGHT * scaleFactor);

View file

@ -16,12 +16,12 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="400" max="32767" attributes="0"/> <EmptySpace min="0" pref="294" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="300" max="32767" attributes="0"/> <EmptySpace min="0" pref="197" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>

View file

@ -37,12 +37,17 @@ package mage.client.cards;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID; import java.util.UUID;
import mage.client.util.Config; import mage.client.util.Config;
import mage.client.util.Event; import mage.client.util.Event;
@ -54,45 +59,52 @@ import mage.view.CardsView;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class CardGrid extends javax.swing.JLayeredPane implements MouseListener, ComponentListener { public class CardGrid extends javax.swing.JLayeredPane implements MouseListener {
protected CardEventSource cardEventSource = new CardEventSource(); protected CardEventSource cardEventSource = new CardEventSource();
protected BigCard bigCard; protected BigCard bigCard;
protected UUID gameId; protected UUID gameId;
protected List<Card> cards = new ArrayList<Card>(); private Map<UUID, Card> cards = new HashMap<UUID, Card>();
public CardGrid() { public CardGrid() {
initComponents(); initComponents();
addComponentListener(this);
setPreferredSize(new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight));
} }
public void loadCards(CardsView showCards, BigCard bigCard, UUID gameId) { public void loadCards(CardsView showCards, BigCard bigCard, UUID gameId) {
this.bigCard = bigCard; this.bigCard = bigCard;
this.gameId = gameId; this.gameId = gameId;
cards.clear(); for (CardView card: showCards.values()) {
for (CardView card: showCards) { if (!cards.containsKey(card.getId())) {
Card cardImg = new Card(card, bigCard, Config.dimensions, gameId); Card cardImg = new Card(card, bigCard, Config.dimensions, gameId);
cardImg.update(card); cardImg.addMouseListener(this);
cardImg.addMouseListener(this); add(cardImg);
cards.add(cardImg); cardImg.update(card);
cards.put(card.getId(), cardImg);
}
}
for (Iterator<Entry<UUID, Card>> i = cards.entrySet().iterator(); i.hasNext();) {
Entry<UUID, Card> entry = i.next();
if (!showCards.containsKey(entry.getKey())) {
removeCard(entry.getKey());
i.remove();
}
} }
drawCards(); drawCards();
this.setVisible(true); this.setVisible(true);
} }
public void drawCards() { public void drawCards() {
removeAll();
int maxWidth = this.getParent().getWidth(); int maxWidth = this.getParent().getWidth();
int numColumns = maxWidth / Config.dimensions.frameWidth; int numColumns = maxWidth / Config.dimensions.frameWidth;
int curColumn = 0; int curColumn = 0;
int curRow = 0; int curRow = 0;
if (cards.size() > 0) { if (cards.size() > 0) {
Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight); Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight);
for (Card cardImg: cards) { List<Card> sortedCards = new ArrayList<Card>(cards.values());
Collections.sort(sortedCards, new CardComparator());
for (Card cardImg: sortedCards) {
rectangle.setLocation(curColumn * Config.dimensions.frameWidth, curRow * 20); rectangle.setLocation(curColumn * Config.dimensions.frameWidth, curRow * 20);
cardImg.setBounds(rectangle); cardImg.setBounds(rectangle);
add(cardImg);
moveToFront(cardImg); moveToFront(cardImg);
curColumn++; curColumn++;
if (curColumn == numColumns) { if (curColumn == numColumns) {
@ -104,6 +116,17 @@ public class CardGrid extends javax.swing.JLayeredPane implements MouseListener,
resizeArea(); resizeArea();
} }
private void removeCard(UUID cardId) {
for (Component comp: getComponents()) {
if (comp instanceof Card) {
if (((Card)comp).getCardId().equals(cardId)) {
remove(comp);
}
}
}
}
public void addCardEventListener(Listener<Event> listener) { public void addCardEventListener(Listener<Event> listener) {
cardEventSource.addListener(listener); cardEventSource.addListener(listener);
} }
@ -125,11 +148,11 @@ public class CardGrid extends javax.swing.JLayeredPane implements MouseListener,
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE) .addGap(0, 294, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE) .addGap(0, 197, Short.MAX_VALUE)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -157,26 +180,6 @@ public class CardGrid extends javax.swing.JLayeredPane implements MouseListener,
@Override @Override
public void mouseExited(MouseEvent e) {} public void mouseExited(MouseEvent e) {}
@Override
public void componentResized(ComponentEvent e) {
resizeArea();
}
@Override
public void componentMoved(ComponentEvent e) {
resizeArea();
}
@Override
public void componentShown(ComponentEvent e) {
resizeArea();
}
@Override
public void componentHidden(ComponentEvent e) {
resizeArea();
}
private void resizeArea() { private void resizeArea() {
Dimension area = new Dimension(0, 0); Dimension area = new Dimension(0, 0);
Dimension size = getPreferredSize(); Dimension size = getPreferredSize();
@ -198,3 +201,12 @@ public class CardGrid extends javax.swing.JLayeredPane implements MouseListener,
} }
} }
class CardComparator implements Comparator<Card> {
@Override
public int compare(Card o1, Card o2) {
return o1.card.getName().compareTo(o2.card.getName());
}
}

View file

@ -34,12 +34,16 @@
package mage.client.cards; package mage.client.cards;
import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID; import java.util.UUID;
import mage.client.util.Config; import mage.client.util.Config;
import mage.view.CardView; import mage.view.CardView;
import mage.view.CardsView; import mage.view.CardsView;
import static mage.client.util.Constants.*;
/** /**
* *
@ -47,26 +51,52 @@ import static mage.client.util.Constants.*;
*/ */
public class Cards extends javax.swing.JPanel { public class Cards extends javax.swing.JPanel {
private Map<UUID, Card> cards = new HashMap<UUID, Card>();
/** Creates new form Cards */ /** Creates new form Cards */
public Cards() { public Cards() {
initComponents(); initComponents();
cardArea.setPreferredSize(new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight));
} }
public void loadCards(CardsView cards, BigCard bigCard, UUID gameId) { public boolean loadCards(CardsView cardsView, BigCard bigCard, UUID gameId) {
cardArea.removeAll(); boolean changed = false;
for (CardView card: cards) { for (CardView card: cardsView.values()) {
Card cardImg = new Card(card, bigCard, Config.dimensions, gameId); if (!cards.containsKey(card.getId())) {
cardArea.add(cardImg); Card cardImg = new Card(card, bigCard, Config.dimensions, gameId);
cardImg.update(card); cards.put(card.getId(), cardImg);
cardArea.add(cardImg);
changed = true;
}
cards.get(card.getId()).update(card);
} }
for (Iterator<Entry<UUID, Card>> i = cards.entrySet().iterator(); i.hasNext();) {
Entry<UUID, Card> entry = i.next();
if (!cardsView.containsKey(entry.getKey())) {
removeCard(entry.getKey());
i.remove();
changed = true;
}
}
cardArea.setPreferredSize(new Dimension(cards.size() * Config.dimensions.frameWidth, Config.dimensions.frameHeight)); cardArea.setPreferredSize(new Dimension(cards.size() * Config.dimensions.frameWidth, Config.dimensions.frameHeight));
cardArea.revalidate(); cardArea.revalidate();
cardArea.repaint(); cardArea.repaint();
this.revalidate(); this.revalidate();
this.repaint(); this.repaint();
return changed;
} }
private void removeCard(UUID cardId) {
for (Component comp: cardArea.getComponents()) {
if (comp instanceof Card) {
if (((Card)comp).getCardId().equals(cardId)) {
cardArea.remove(comp);
}
}
}
}
/** This method is called from within the constructor to /** This method is called from within the constructor to
* initialize the form. * initialize the form.
* WARNING: Do NOT modify this code. The content of this method is * WARNING: Do NOT modify this code. The content of this method is

View file

@ -7,6 +7,9 @@
<LineBorder/> <LineBorder/>
</Border> </Border>
</Property> </Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight)" type="code"/>
</Property>
</Properties> </Properties>
<AuxValues> <AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>

View file

@ -44,7 +44,6 @@ import mage.client.util.Event;
import mage.client.util.Listener; import mage.client.util.Listener;
import mage.view.CardView; import mage.view.CardView;
import mage.view.CardsView; import mage.view.CardsView;
import static mage.client.util.Constants.*;
/** /**
* *
@ -57,7 +56,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener {
/** Creates new form Cards */ /** Creates new form Cards */
public CardsList() { public CardsList() {
initComponents(); initComponents();
cardArea.setPreferredSize(new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight));
} }
public void loadCards(CardsView showCards, BigCard bigCard, UUID gameId) { public void loadCards(CardsView showCards, BigCard bigCard, UUID gameId) {
@ -65,7 +63,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener {
if (showCards != null && showCards.size() > 0) { if (showCards != null && showCards.size() > 0) {
Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight); Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight);
int count = 0; int count = 0;
for (CardView card: showCards) { for (CardView card: showCards.values()) {
Card cardImg = new Card(card, bigCard, Config.dimensions, gameId); Card cardImg = new Card(card, bigCard, Config.dimensions, gameId);
cardImg.setBounds(rectangle); cardImg.setBounds(rectangle);
cardArea.add(cardImg); cardArea.add(cardImg);
@ -110,6 +108,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener {
cardArea = new javax.swing.JLayeredPane(); cardArea = new javax.swing.JLayeredPane();
setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
setPreferredSize(new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight));
setLayout(new java.awt.BorderLayout()); setLayout(new java.awt.BorderLayout());
jScrollPane1.setViewportView(cardArea); jScrollPane1.setViewportView(cardArea);
@ -131,15 +130,19 @@ public class CardsList extends javax.swing.JPanel implements MouseListener {
} }
} }
@Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
} }
@Override
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
} }
@Override
public void mouseEntered(MouseEvent e) { public void mouseEntered(MouseEvent e) {
} }
@Override
public void mouseExited(MouseEvent e) { public void mouseExited(MouseEvent e) {
} }

View file

@ -46,6 +46,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.swing.PopupFactory; import javax.swing.PopupFactory;
import mage.client.util.Config;
import mage.client.util.ImageHelper; import mage.client.util.ImageHelper;
import mage.view.CounterView; import mage.view.CounterView;
import mage.view.PermanentView; import mage.view.PermanentView;
@ -69,7 +70,7 @@ public class Permanent extends Card {
super(permanent, bigCard, dimensions, gameId); super(permanent, bigCard, dimensions, gameId);
this.setSize(this.getPreferredSize()); this.setSize(this.getPreferredSize());
this.permanent = permanent; this.permanent = permanent;
tappedImage = new BufferedImage(dimension.frameHeight, dimension.frameWidth, BufferedImage.TYPE_INT_RGB); tappedImage = new BufferedImage(Config.dimensions.frameHeight, Config.dimensions.frameWidth, BufferedImage.TYPE_INT_RGB);
} }
public UUID getPermanentId() { public UUID getPermanentId() {
@ -153,10 +154,10 @@ public class Permanent extends Card {
g2.setColor(Color.BLACK); g2.setColor(Color.BLACK);
} }
if (permanent.isTapped()) { if (permanent.isTapped()) {
g2.drawRect(0, 0, dimension.frameHeight - 1, dimension.frameWidth - 1); g2.drawRect(0, 0, Config.dimensions.frameHeight - 1, Config.dimensions.frameWidth - 1);
} }
else { else {
g2.drawRect(0, 0, dimension.frameWidth - 1, dimension.frameHeight - 1); g2.drawRect(0, 0, Config.dimensions.frameWidth - 1, Config.dimensions.frameHeight - 1);
} }
} }
@ -185,10 +186,10 @@ public class Permanent extends Card {
@Override @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
if (permanent != null && permanent.isTapped()) { if (permanent != null && permanent.isTapped()) {
return new Dimension(dimension.frameHeight, dimension.frameWidth); return new Dimension(Config.dimensions.frameHeight, Config.dimensions.frameWidth);
} }
else { else {
return new Dimension(dimension.frameWidth, dimension.frameHeight); return new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight);
} }
} }
@ -203,17 +204,20 @@ public class Permanent extends Card {
@Override @Override
public void mouseEntered(MouseEvent arg0) { public void mouseEntered(MouseEvent arg0) {
if (popup != null) if (!popupShowing) {
if (popup != null)
popup.hide();
PopupFactory factory = PopupFactory.getSharedInstance();
int x = (int) this.getLocationOnScreen().getX() + (permanent.isTapped()?Config.dimensions.frameHeight:Config.dimensions.frameWidth);
int y = (int) this.getLocationOnScreen().getY() + 40;
popup = factory.getPopup(this, popupText, x, y);
popup.show();
//hack to get popup to resize to fit text
popup.hide(); popup.hide();
PopupFactory factory = PopupFactory.getSharedInstance(); popup = factory.getPopup(this, popupText, x, y);
int x = (int) this.getLocationOnScreen().getX() + (permanent.isTapped()?dimension.frameHeight:dimension.frameWidth); popup.show();
int y = (int) this.getLocationOnScreen().getY() + 40; popupShowing = true;
popup = factory.getPopup(this, popupText, x, y); }
popup.show();
//hack to get popup to resize to fit text
popup.hide();
popup = factory.getPopup(this, popupText, x, y);
popup.show();
} }
/** This method is called from within the constructor to /** This method is called from within the constructor to

View file

@ -34,12 +34,14 @@
package mage.client.chat; package mage.client.chat;
import java.awt.Color;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.remote.Session; import mage.client.remote.Session;
import mage.util.Logging; import mage.util.Logging;
import mage.view.ChatMessage.MessageColor;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -69,7 +71,24 @@ public class ChatPanel extends javax.swing.JPanel {
session.leaveChat(chatId); session.leaveChat(chatId);
} }
public void receiveMessage(String message) { public void receiveMessage(String message, MessageColor color) {
switch (color) {
case BLACK:
this.txtConversation.setForeground(Color.BLACK);
break;
case RED:
this.txtConversation.setForeground(Color.RED);
break;
case GREEN:
this.txtConversation.setForeground(Color.GREEN);
break;
case BLUE:
this.txtConversation.setForeground(Color.BLUE);
break;
case ORANGE:
this.txtConversation.setForeground(Color.ORANGE);
break;
}
this.txtConversation.append(message + "\n"); this.txtConversation.append(message + "\n");
txtConversation.setCaretPosition(txtConversation.getText().length() - 1); txtConversation.setCaretPosition(txtConversation.getText().length() - 1);
} }

View file

@ -37,11 +37,13 @@ package mage.client.deckeditor;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.event.ComponentEvent; import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener; import java.awt.event.ComponentListener;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultComboBoxModel;
import mage.Constants.CardType; import mage.Constants.CardType;
import mage.Constants.Zone; import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
import mage.client.cards.BigCard; import mage.client.cards.BigCard;
import mage.client.cards.CardGrid; import mage.client.cards.CardGrid;
@ -56,8 +58,9 @@ import mage.view.CardsView;
*/ */
public class CardSelector extends javax.swing.JPanel implements ComponentListener { public class CardSelector extends javax.swing.JPanel implements ComponentListener {
private Cards cards = new CardsImpl(Zone.OUTSIDE); private final Set<Card> allCards = new LinkedHashSet<Card>();
private FilterCard filter = new FilterCard(); private final List<Card> cards = new ArrayList<Card>();
private final FilterCard filter = new FilterCard();
private BigCard bigCard; private BigCard bigCard;
/** Creates new form CardSelector */ /** Creates new form CardSelector */
@ -68,12 +71,11 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
public void loadCards(BigCard bigCard) { public void loadCards(BigCard bigCard) {
this.bigCard = bigCard; this.bigCard = bigCard;
this.cards.clear();
cbExpansionSet.setModel(new DefaultComboBoxModel(Sets.getInstance().toArray())); cbExpansionSet.setModel(new DefaultComboBoxModel(Sets.getInstance().toArray()));
cbExpansionSet.insertItemAt("All sets", 0); cbExpansionSet.insertItemAt("All sets", 0);
cbExpansionSet.setSelectedIndex(0); cbExpansionSet.setSelectedIndex(0);
for (ExpansionSet set: Sets.getInstance()) { for (ExpansionSet set: Sets.getInstance()) {
cards.addAll(set.createCards()); allCards.addAll(set.createCards());
} }
filter.setUseColor(true); filter.setUseColor(true);
filter.getColor().setBlack(true); filter.getColor().setBlack(true);
@ -98,8 +100,13 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
private void filterCards() { private void filterCards() {
try { try {
cards.clear();
for (Card card: allCards) {
if (filter.match(card))
cards.add(card);
}
setCursor(new Cursor(Cursor.WAIT_CURSOR)); setCursor(new Cursor(Cursor.WAIT_CURSOR));
this.cardGrid.loadCards(new CardsView(cards.getCards(filter)), bigCard, null); this.cardGrid.loadCards(new CardsView(cards), bigCard, null);
} }
finally { finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
@ -110,7 +117,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
return this.cardGrid; return this.cardGrid;
} }
public Cards getCards() { public List<Card> getCards() {
return cards; return cards;
} }

View file

@ -80,7 +80,12 @@ public class DeckEditorPanel extends javax.swing.JPanel {
@Override @Override
public void event(Event event) { public void event(Event event) {
if (event.getEventName().equals("double-click")) { if (event.getEventName().equals("double-click")) {
deck.getCards().add(createCard(cardSelector.getCards().get((UUID)event.getSource()).getClass())); for (Card card: cardSelector.getCards()) {
if (card.getId().equals((UUID)event.getSource())) {
deck.getCards().add(createCard(card.getClass()));
break;
}
}
refreshDeck(); refreshDeck();
} }
} }
@ -92,7 +97,12 @@ public class DeckEditorPanel extends javax.swing.JPanel {
@Override @Override
public void event(Event event) { public void event(Event event) {
if (event.getEventName().equals("double-click")) { if (event.getEventName().equals("double-click")) {
deck.getCards().remove((UUID)event.getSource()); for (Card card: deck.getCards()) {
if (card.getId().equals((UUID)event.getSource())) {
deck.getCards().remove(card);
break;
}
}
refreshDeck(); refreshDeck();
} }
} }
@ -272,8 +282,11 @@ public class DeckEditorPanel extends javax.swing.JPanel {
if (ret == JFileChooser.APPROVE_OPTION) { if (ret == JFileChooser.APPROVE_OPTION) {
File file = fcSelectDeck.getSelectedFile(); File file = fcSelectDeck.getSelectedFile();
try { try {
String fileName = file.getPath();
if (!fileName.endsWith(".dck"))
fileName += ".dck";
setCursor(new Cursor(Cursor.WAIT_CURSOR)); setCursor(new Cursor(Cursor.WAIT_CURSOR));
deck.getDeckCardLists().save(file.getPath()); deck.getDeckCardLists().save(fileName);
} catch (Exception ex) { } catch (Exception ex) {
Logger.getLogger(DeckEditorPanel.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(DeckEditorPanel.class.getName()).log(Level.SEVERE, null, ex);
} }

View file

@ -33,6 +33,11 @@
</Layout> </Layout>
<SubComponents> <SubComponents>
<Component class="mage.client.cards.Cards" name="cards"> <Component class="mage.client.cards.Cards" name="cards">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight + 25)" type="code"/>
</Property>
</Properties>
</Component> </Component>
</SubComponents> </SubComponents>
</Form> </Form>

View file

@ -38,9 +38,8 @@ import java.beans.PropertyVetoException;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.swing.JLayeredPane;
import mage.client.MageFrame;
import mage.client.cards.BigCard; import mage.client.cards.BigCard;
import mage.client.util.Config;
import mage.view.ExileView; import mage.view.ExileView;
/** /**
@ -57,17 +56,21 @@ public class ExileZoneDialog extends MageDialog {
public void loadCards(ExileView exile, BigCard bigCard, UUID gameId) { public void loadCards(ExileView exile, BigCard bigCard, UUID gameId) {
this.title = exile.getName(); this.title = exile.getName();
boolean changed = false;
changed = cards.loadCards(exile, bigCard, gameId);
if (exile.size() > 0) { if (exile.size() > 0) {
cards.loadCards(exile, bigCard, gameId); show();
if (getParent() != MageFrame.getDesktop() || this.isClosed) if (changed) {
MageFrame.getDesktop().add(this, JLayeredPane.POPUP_LAYER); try {
// try { this.setIcon(false);
// this.setIcon(false); } catch (PropertyVetoException ex) {
// } catch (PropertyVetoException ex) { Logger.getLogger(ExileZoneDialog.class.getName()).log(Level.SEVERE, null, ex);
// Logger.getLogger(ShowCardsDialog.class.getName()).log(Level.SEVERE, null, ex); }
// } }
}
else {
hide();
} }
this.setVisible(exile.size() > 0);
} }
/** This method is called from within the constructor to /** This method is called from within the constructor to
@ -83,6 +86,8 @@ public class ExileZoneDialog extends MageDialog {
setIconifiable(true); setIconifiable(true);
cards.setPreferredSize(new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight + 25));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(

View file

@ -22,21 +22,26 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" attributes="0">
<EmptySpace pref="310" max="32767" attributes="0"/>
<Component id="btnOK" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="btnOK" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="newPlayerPanel" alignment="0" pref="414" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
<Component id="newPlayerPanel" alignment="1" pref="438" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="newPlayerPanel" min="-2" max="-2" attributes="0"/> <Component id="newPlayerPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/> <EmptySpace pref="10" max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnOK" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnOK" alignment="3" min="-2" max="-2" attributes="0"/>

View file

@ -103,17 +103,20 @@ public class JoinTableDialog extends MageDialog {
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap(310, Short.MAX_VALUE) .addContainerGap()
.addComponent(btnOK) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(btnCancel) .addComponent(btnOK)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel))
.addComponent(newPlayerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE))
.addContainerGap()) .addContainerGap())
.addComponent(newPlayerPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 438, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(newPlayerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(newPlayerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
@ -133,7 +136,7 @@ public class JoinTableDialog extends MageDialog {
private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed
Session session = MageFrame.getSession(); Session session = MageFrame.getSession();
try { try {
joined = session.joinTable(roomId, tableId, 1, this.newPlayerPanel.getPlayerName(), DeckCardLists.load(this.newPlayerPanel.getDeckFile())); joined = session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), DeckCardLists.load(this.newPlayerPanel.getDeckFile()));
} catch (Exception ex) { } catch (Exception ex) {
handleError(ex); handleError(ex);
} }

View file

@ -24,7 +24,7 @@
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="302" max="32767" attributes="0"/> <EmptySpace min="0" pref="306" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>

View file

@ -64,6 +64,7 @@ public class MageDialog extends javax.swing.JInternalFrame {
@Override @Override
public void show() { public void show() {
super.show(); super.show();
this.toFront();
if (this.modal) { if (this.modal) {
startModal(); startModal();
} }
@ -72,6 +73,7 @@ public class MageDialog extends javax.swing.JInternalFrame {
@Override @Override
public void setVisible(boolean value) { public void setVisible(boolean value) {
super.setVisible(value); super.setVisible(value);
this.toFront();
if (modal) { if (modal) {
if (value) { if (value) {
startModal(); startModal();

View file

@ -286,18 +286,16 @@ public class NewTableDialog extends MageDialog {
(MultiplayerAttackOption)this.cbAttackOption.getSelectedItem(), (MultiplayerAttackOption)this.cbAttackOption.getSelectedItem(),
(RangeOfInfluence)this.cbRange.getSelectedItem()); (RangeOfInfluence)this.cbRange.getSelectedItem());
try { try {
if (session.joinTable(roomId, table.getTableId(), 0, this.player1Panel.getPlayerName(), DeckCardLists.load(this.player1Panel.getDeckFile()))) { if (session.joinTable(roomId, table.getTableId(), this.player1Panel.getPlayerName(), DeckCardLists.load(this.player1Panel.getDeckFile()))) {
int seatNum = 1;
for (TablePlayerPanel player: players) { for (TablePlayerPanel player: players) {
if (!player.getPlayerType().equals("Human")) { if (!player.getPlayerType().equals("Human")) {
if (!player.joinTable(roomId, table.getTableId(), seatNum)) { if (!player.joinTable(roomId, table.getTableId())) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Error joining table.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Error joining table.", "Error", JOptionPane.ERROR_MESSAGE);
session.removeTable(roomId, table.getTableId()); session.removeTable(roomId, table.getTableId());
table = null; table = null;
return; return;
} }
} }
seatNum++;
} }
this.setVisible(false); this.setVisible(false);
return; return;

View file

@ -20,23 +20,24 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace pref="13" max="32767" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0">
<Component id="btnOk" min="-2" max="-2" attributes="0"/> <Group type="102" alignment="1" attributes="0">
<Component id="btnOk" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="0" pref="146" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" pref="44" max="-2" attributes="0"/>
<Component id="spnAmount" min="-2" pref="52" max="-2" attributes="0"/> <Component id="spnAmount" min="-2" pref="52" max="-2" attributes="0"/>
</Group> <EmptySpace min="-2" pref="54" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="lblMessage" pref="121" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -44,10 +45,10 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="lblMessage" pref="30" max="32767" attributes="0"/> <Component id="jScrollPane1" pref="64" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="spnAmount" min="-2" max="-2" attributes="0"/> <Component id="spnAmount" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnOk" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnOk" alignment="3" min="-2" max="-2" attributes="0"/>
@ -81,10 +82,30 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnOkActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnOkActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Component class="javax.swing.JLabel" name="lblMessage"> <Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Properties> <Properties>
<Property name="horizontalAlignment" type="int" value="0"/> <Property name="horizontalScrollBarPolicy" type="int" value="31"/>
</Properties> </Properties>
</Component> <AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextPane" name="lblMessage">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="editable" type="boolean" value="false"/>
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="null&#x9;" type="code"/>
</Property>
<Property name="focusable" type="boolean" value="false"/>
<Property name="opaque" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents> </SubComponents>
</Form> </Form>

View file

@ -53,7 +53,9 @@ public class PickNumberDialog extends MageDialog {
public void showDialog(int min, int max, String message) { public void showDialog(int min, int max, String message) {
this.spnAmount.setModel(new SpinnerNumberModel(min, min, max, 1)); this.spnAmount.setModel(new SpinnerNumberModel(min, min, max, 1));
this.lblMessage.setText(message); this.lblMessage.setText(message);
this.btnOk.setVisible(true);
this.btnCancel.setVisible(false); this.btnCancel.setVisible(false);
this.pack();
this.setVisible(true); this.setVisible(true);
} }
@ -77,7 +79,8 @@ public class PickNumberDialog extends MageDialog {
spnAmount = new javax.swing.JSpinner(); spnAmount = new javax.swing.JSpinner();
btnCancel = new javax.swing.JButton(); btnCancel = new javax.swing.JButton();
btnOk = new javax.swing.JButton(); btnOk = new javax.swing.JButton();
lblMessage = new javax.swing.JLabel(); jScrollPane1 = new javax.swing.JScrollPane();
lblMessage = new javax.swing.JTextPane();
spnAmount.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(1), null, null, Integer.valueOf(1))); spnAmount.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(1), null, null, Integer.valueOf(1)));
@ -95,35 +98,42 @@ public class PickNumberDialog extends MageDialog {
} }
}); });
lblMessage.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
lblMessage.setBorder(null);
lblMessage.setEditable(false);
lblMessage.setCursor(null );
lblMessage.setFocusable(false);
lblMessage.setOpaque(false);
jScrollPane1.setViewportView(lblMessage);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap(13, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnOk) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnOk)
.addComponent(btnCancel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createSequentialGroup() .addComponent(btnCancel))
.addGap(44, 44, 44) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 146, Short.MAX_VALUE))
.addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap())
.addGroup(layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblMessage, javax.swing.GroupLayout.DEFAULT_SIZE, 121, Short.MAX_VALUE))) .addGap(54, 54, 54))))
.addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(lblMessage, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCancel) .addComponent(btnCancel)
.addComponent(btnOk)) .addComponent(btnOk))
@ -146,7 +156,8 @@ public class PickNumberDialog extends MageDialog {
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCancel; private javax.swing.JButton btnCancel;
private javax.swing.JButton btnOk; private javax.swing.JButton btnOk;
private javax.swing.JLabel lblMessage; private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextPane lblMessage;
private javax.swing.JSpinner spnAmount; private javax.swing.JSpinner spnAmount;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables

View file

@ -78,7 +78,7 @@ public class ShowCardsDialog extends MageDialog implements MouseListener {
private void loadCardsFew(CardsView showCards, BigCard bigCard, CardDimensions dimension, UUID gameId) { private void loadCardsFew(CardsView showCards, BigCard bigCard, CardDimensions dimension, UUID gameId) {
Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight); Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight);
for (CardView card: showCards) { for (CardView card: showCards.values()) {
Card cardImg = new Card(card, bigCard, dimension, gameId); Card cardImg = new Card(card, bigCard, dimension, gameId);
cardImg.setBounds(rectangle); cardImg.setBounds(rectangle);
cardArea.add(cardImg); cardArea.add(cardImg);
@ -95,7 +95,7 @@ public class ShowCardsDialog extends MageDialog implements MouseListener {
if (showCards != null && showCards.size() > 0) { if (showCards != null && showCards.size() > 0) {
Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight); Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight);
int count = 0; int count = 0;
for (CardView card: showCards) { for (CardView card: showCards.values()) {
Card cardImg = new Card(card, bigCard, dimension, gameId); Card cardImg = new Card(card, bigCard, dimension, gameId);
cardImg.setBounds(rectangle); cardImg.setBounds(rectangle);
cardArea.add(cardImg); cardArea.add(cardImg);

View file

@ -48,7 +48,6 @@ import mage.client.cards.BigCard;
import mage.client.cards.Permanent; import mage.client.cards.Permanent;
import mage.client.util.Config; import mage.client.util.Config;
import mage.view.PermanentView; import mage.view.PermanentView;
import static mage.client.util.Constants.*;
/** /**
* *

View file

@ -16,9 +16,9 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="lblDefender" alignment="0" pref="142" max="32767" attributes="0"/> <Component id="lblDefender" alignment="0" pref="69" max="32767" attributes="0"/>
<Component id="blockers" alignment="0" pref="142" max="32767" attributes="2"/> <Component id="blockers" alignment="0" min="-2" max="-2" attributes="2"/>
<Component id="attackers" alignment="0" pref="142" max="32767" attributes="2"/> <Component id="attackers" alignment="0" min="-2" max="-2" attributes="2"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
@ -26,22 +26,32 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="lblDefender" min="-2" max="-2" attributes="0"/> <Component id="lblDefender" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="blockers" min="-2" pref="199" max="-2" attributes="0"/> <Component id="blockers" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="attackers" min="-2" pref="199" max="-2" attributes="0"/> <Component id="attackers" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents> <SubComponents>
<Component class="mage.client.cards.Cards" name="blockers"> <Component class="mage.client.cards.Cards" name="blockers">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new java.awt.Dimension(Config.dimensions.frameWidth + 8, Config.dimensions.frameHeight + 25)" type="code"/>
</Property>
</Properties>
</Component> </Component>
<Component class="mage.client.cards.Cards" name="attackers"> <Component class="mage.client.cards.Cards" name="attackers">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new java.awt.Dimension(Config.dimensions.frameWidth + 8, Config.dimensions.frameHeight + 25)" type="code"/>
</Property>
</Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="lblDefender"> <Component class="javax.swing.JLabel" name="lblDefender">
<Properties> <Properties>
<Property name="horizontalAlignment" type="int" value="0"/> <Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="jLabel1"/> <Property name="text" type="java.lang.String" value="Defender"/>
</Properties> </Properties>
</Component> </Component>
</SubComponents> </SubComponents>

View file

@ -39,7 +39,6 @@ import java.util.UUID;
import mage.client.cards.BigCard; import mage.client.cards.BigCard;
import mage.client.util.Config; import mage.client.util.Config;
import mage.view.CombatGroupView; import mage.view.CombatGroupView;
import static mage.client.util.Constants.*;
/** /**
* *
@ -53,7 +52,6 @@ public class CombatGroup extends javax.swing.JPanel {
/** Creates new form CombatGroup */ /** Creates new form CombatGroup */
public CombatGroup() { public CombatGroup() {
initComponents(); initComponents();
// setPreferredSize(new Dimension(160, 440));
} }
public void init(UUID gameId, BigCard bigCard) { public void init(UUID gameId, BigCard bigCard) {
@ -64,9 +62,9 @@ public class CombatGroup extends javax.swing.JPanel {
public void update(CombatGroupView combatGroup) { public void update(CombatGroupView combatGroup) {
this.lblDefender.setText(combatGroup.getDefenderName()); this.lblDefender.setText(combatGroup.getDefenderName());
this.attackers.loadCards(combatGroup.getAttackers(), bigCard, gameId); this.attackers.loadCards(combatGroup.getAttackers(), bigCard, gameId);
attackers.setPreferredSize(new Dimension(Config.dimensions.frameWidth + 6, Config.dimensions.frameHeight + 6)); // attackers.setPreferredSize(new Dimension(Config.dimensions.frameWidth + 6, Config.dimensions.frameHeight + 6));
this.blockers.loadCards(combatGroup.getBlockers(), bigCard, gameId); this.blockers.loadCards(combatGroup.getBlockers(), bigCard, gameId);
blockers.setPreferredSize(new Dimension(Config.dimensions.frameWidth + 6, Config.dimensions.frameHeight + 6)); // blockers.setPreferredSize(new Dimension(Config.dimensions.frameWidth + 6, Config.dimensions.frameHeight + 6));
this.attackers.setVisible(true); this.attackers.setVisible(true);
this.blockers.setVisible(true); this.blockers.setVisible(true);
} }
@ -84,25 +82,29 @@ public class CombatGroup extends javax.swing.JPanel {
attackers = new mage.client.cards.Cards(); attackers = new mage.client.cards.Cards();
lblDefender = new javax.swing.JLabel(); lblDefender = new javax.swing.JLabel();
blockers.setPreferredSize(new java.awt.Dimension(Config.dimensions.frameWidth + 8, Config.dimensions.frameHeight + 25));
attackers.setPreferredSize(new java.awt.Dimension(Config.dimensions.frameWidth + 8, Config.dimensions.frameHeight + 25));
lblDefender.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); lblDefender.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
lblDefender.setText("jLabel1"); lblDefender.setText("Defender");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblDefender, javax.swing.GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE) .addComponent(lblDefender, javax.swing.GroupLayout.DEFAULT_SIZE, 69, Short.MAX_VALUE)
.addComponent(blockers, javax.swing.GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE) .addComponent(blockers, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(attackers, javax.swing.GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE) .addComponent(attackers, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(lblDefender) .addComponent(lblDefender)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(blockers, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(blockers, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(attackers, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(attackers, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View file

@ -108,9 +108,10 @@ public class FeedbackPanel extends javax.swing.JPanel {
break; break;
} }
this.btnSpecial.setVisible(special); this.btnSpecial.setVisible(special);
this.revalidate();
this.repaint();
if (modal) if (modal)
startModal(); startModal();
this.revalidate();
} }
public void clear() { public void clear() {

View file

@ -36,6 +36,8 @@ package mage.client.game;
import mage.client.*; import mage.client.*;
import java.util.UUID; import java.util.UUID;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
/** /**
* *
@ -46,6 +48,33 @@ public class GamePane extends MagePane {
/** Creates new form GamePane */ /** Creates new form GamePane */
public GamePane() { public GamePane() {
initComponents(); initComponents();
addInternalFrameListener(new InternalFrameListener()
{
@Override
public void internalFrameOpened(InternalFrameEvent e) { }
@Override
public void internalFrameClosing(InternalFrameEvent e) {
gamePanel.cleanUp();
}
@Override
public void internalFrameClosed(InternalFrameEvent e) { }
@Override
public void internalFrameIconified(InternalFrameEvent e) { }
@Override
public void internalFrameDeiconified(InternalFrameEvent e) { }
@Override
public void internalFrameActivated(InternalFrameEvent e) { }
@Override
public void internalFrameDeactivated(InternalFrameEvent e) { }
});
} }
public void showGame(UUID gameId, UUID playerId) { public void showGame(UUID gameId, UUID playerId) {

View file

@ -29,7 +29,7 @@
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jSplitPane1" alignment="0" pref="847" max="32767" attributes="0"/> <Component id="jSplitPane1" alignment="0" pref="798" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
@ -62,8 +62,8 @@
<Component id="pnlGameInfo" min="-2" max="-2" attributes="0"/> <Component id="pnlGameInfo" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="pnlHand" max="32767" attributes="0"/> <Component id="hand" pref="715" max="32767" attributes="0"/>
<Component id="pnlBattlefield" alignment="0" pref="715" max="32767" attributes="0"/> <Component id="pnlBattlefield" pref="715" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</Group> </Group>
@ -71,9 +71,9 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<Component id="pnlBattlefield" pref="634" max="32767" attributes="0"/> <Component id="pnlBattlefield" pref="794" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="pnlHand" min="-2" max="-2" attributes="0"/> <Component id="hand" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Component id="pnlGameInfo" alignment="0" max="32767" attributes="0"/> <Component id="pnlGameInfo" alignment="0" max="32767" attributes="0"/>
</Group> </Group>
@ -116,9 +116,7 @@
<Component id="btnConcede" min="-2" max="-2" attributes="0"/> <Component id="btnConcede" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="btnStopWatching" min="-2" max="-2" attributes="0"/> <Component id="btnStopWatching" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace pref="62" max="32767" attributes="0"/>
<Component id="btnCheat" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="19" max="32767" attributes="0"/>
</Group> </Group>
<Component id="bigCard" alignment="0" pref="256" max="32767" attributes="0"/> <Component id="bigCard" alignment="0" pref="256" max="32767" attributes="0"/>
<Component id="feedbackPanel" alignment="0" pref="256" max="32767" attributes="0"/> <Component id="feedbackPanel" alignment="0" pref="256" max="32767" attributes="0"/>
@ -160,16 +158,15 @@
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="feedbackPanel" min="-2" pref="109" max="-2" attributes="0"/> <Component id="feedbackPanel" min="-2" pref="109" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="stack" min="-2" pref="209" max="-2" attributes="0"/> <Component id="stack" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="bigCard" min="-2" max="-2" attributes="0"/> <Component id="bigCard" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="8" max="32767" attributes="0"/> <EmptySpace pref="164" max="32767" attributes="0"/>
<Component id="pnlReplay" min="-2" max="-2" attributes="0"/> <Component id="pnlReplay" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="btnConcede" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnConcede" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnStopWatching" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnStopWatching" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnCheat" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</Group> </Group>
@ -325,14 +322,11 @@
<Component class="mage.client.cards.BigCard" name="bigCard"> <Component class="mage.client.cards.BigCard" name="bigCard">
</Component> </Component>
<Component class="mage.client.cards.Cards" name="stack"> <Component class="mage.client.cards.Cards" name="stack">
</Component>
<Component class="javax.swing.JButton" name="btnCheat">
<Properties> <Properties>
<Property name="text" type="java.lang.String" value="?"/> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight + 25)" type="code"/>
</Property>
</Properties> </Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCheatActionPerformed"/>
</Events>
</Component> </Component>
<Container class="javax.swing.JPanel" name="pnlReplay"> <Container class="javax.swing.JPanel" name="pnlReplay">
@ -387,44 +381,17 @@
</Container> </Container>
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javax.swing.JPanel" name="pnlHand">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
<EtchetBorder/>
</Border>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight + 25)" type="code"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="hand" alignment="1" pref="711" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="hand" alignment="1" pref="209" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="mage.client.cards.Cards" name="hand">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight)" type="code"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="pnlBattlefield"> <Container class="javax.swing.JPanel" name="pnlBattlefield">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
</Container> </Container>
<Component class="mage.client.cards.Cards" name="hand">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight + 25)" type="code"/>
</Property>
</Properties>
</Component>
</SubComponents> </SubComponents>
</Container> </Container>
<Component class="mage.client.chat.ChatPanel" name="chatPanel"> <Component class="mage.client.chat.ChatPanel" name="chatPanel">

View file

@ -35,7 +35,6 @@
package mage.client.game; package mage.client.game;
import java.awt.GridBagConstraints; import java.awt.GridBagConstraints;
import java.util.logging.Level;
import mage.client.*; import mage.client.*;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -44,11 +43,8 @@ import java.util.logging.Logger;
import javax.swing.JLayeredPane; import javax.swing.JLayeredPane;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import mage.cards.decks.DeckCardLists;
import mage.client.dialog.CombatDialog;
import mage.client.dialog.ExileZoneDialog; import mage.client.dialog.ExileZoneDialog;
import mage.client.dialog.PickChoiceDialog; import mage.client.dialog.PickChoiceDialog;
import mage.client.dialog.PickNumberDialog;
import mage.client.dialog.ShowCardsDialog; import mage.client.dialog.ShowCardsDialog;
import mage.client.game.FeedbackPanel.FeedbackMode; import mage.client.game.FeedbackPanel.FeedbackMode;
import mage.client.remote.Session; import mage.client.remote.Session;
@ -73,14 +69,20 @@ public class GamePanel extends javax.swing.JPanel {
private UUID gameId; private UUID gameId;
private UUID playerId; private UUID playerId;
private Session session; private Session session;
private CombatDialog combat = new CombatDialog();
private PickNumberDialog pickNumber = new PickNumberDialog();
/** Creates new form GamePanel */ /** Creates new form GamePanel */
public GamePanel() { public GamePanel() {
initComponents(); initComponents();
} }
public void cleanUp() {
MageFrame.getCombatDialog().hideDialog();
MageFrame.getPickNumberDialog().hide();
for (ExileZoneDialog exile: exiles.values()) {
exile.hide();
}
}
public synchronized void showGame(UUID gameId, UUID playerId) { public synchronized void showGame(UUID gameId, UUID playerId) {
this.gameId = gameId; this.gameId = gameId;
this.playerId = playerId; this.playerId = playerId;
@ -108,7 +110,6 @@ public class GamePanel extends javax.swing.JPanel {
this.feedbackPanel.clear(); this.feedbackPanel.clear();
this.btnConcede.setVisible(false); this.btnConcede.setVisible(false);
this.btnStopWatching.setVisible(true); this.btnStopWatching.setVisible(true);
this.btnCheat.setVisible(false);
this.pnlReplay.setVisible(false); this.pnlReplay.setVisible(false);
this.setVisible(true); this.setVisible(true);
this.chatPanel.clear(); this.chatPanel.clear();
@ -124,7 +125,6 @@ public class GamePanel extends javax.swing.JPanel {
this.feedbackPanel.clear(); this.feedbackPanel.clear();
this.btnConcede.setVisible(false); this.btnConcede.setVisible(false);
this.btnStopWatching.setVisible(false); this.btnStopWatching.setVisible(false);
this.btnCheat.setVisible(false);
this.pnlReplay.setVisible(true); this.pnlReplay.setVisible(true);
this.setVisible(true); this.setVisible(true);
this.chatPanel.clear(); this.chatPanel.clear();
@ -136,16 +136,21 @@ public class GamePanel extends javax.swing.JPanel {
this.chatPanel.disconnect(); this.chatPanel.disconnect();
this.players.clear(); this.players.clear();
this.pnlBattlefield.removeAll(); this.pnlBattlefield.removeAll();
this.combat.hideDialog(); MageFrame.getCombatDialog().hideDialog();
MageFrame.getDesktop().remove(combat); // MageFrame.getDesktop().remove(combat);
this.setVisible(false); this.setVisible(false);
} }
public synchronized void init(GameView game) { public synchronized void init(GameView game) {
combat.init(gameId, bigCard); MageFrame.getCombatDialog().init(gameId, bigCard);
MageFrame.getDesktop().add(combat, JLayeredPane.POPUP_LAYER); // MageFrame.getDesktop().add(combat, JLayeredPane.POPUP_LAYER);
combat.setLocation(500, 300); MageFrame.getCombatDialog().setLocation(500, 300);
MageFrame.getDesktop().add(pickNumber, JLayeredPane.POPUP_LAYER); // MageFrame.getDesktop().add(pickNumber, JLayeredPane.POPUP_LAYER);
addPlayers(game);
updateGame(game);
}
private void addPlayers(GameView game) {
this.players.clear(); this.players.clear();
this.pnlBattlefield.removeAll(); this.pnlBattlefield.removeAll();
//arrange players in a circle with the session player at the bottom left //arrange players in a circle with the session player at the bottom left
@ -155,10 +160,12 @@ public class GamePanel extends javax.swing.JPanel {
int col = 0; int col = 0;
int row = 1; int row = 1;
int playerSeat = 0; int playerSeat = 0;
for (PlayerView player: game.getPlayers()) { if (playerId != null) {
if (playerId.equals(player.getPlayerId())) for (PlayerView player: game.getPlayers()) {
break; if (playerId.equals(player.getPlayerId()))
playerSeat++; break;
playerSeat++;
}
} }
PlayerView player = game.getPlayers().get(playerSeat); PlayerView player = game.getPlayers().get(playerSeat);
PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId); PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId);
@ -176,6 +183,8 @@ public class GamePanel extends javax.swing.JPanel {
if (oddNumber) if (oddNumber)
col++; col++;
int playerNum = playerSeat + 1; int playerNum = playerSeat + 1;
if (playerNum >= numSeats)
playerNum = 0;
while (true) { while (true) {
if (row == 1) if (row == 1)
col++; col++;
@ -202,7 +211,6 @@ public class GamePanel extends javax.swing.JPanel {
if (playerNum == playerSeat) if (playerNum == playerSeat)
break; break;
} }
updateGame(game);
} }
public synchronized void updateGame(GameView game) { public synchronized void updateGame(GameView game) {
@ -229,20 +237,23 @@ public class GamePanel extends javax.swing.JPanel {
if (!exiles.containsKey(exile.getId())) { if (!exiles.containsKey(exile.getId())) {
ExileZoneDialog newExile = new ExileZoneDialog(); ExileZoneDialog newExile = new ExileZoneDialog();
exiles.put(exile.getId(), newExile); exiles.put(exile.getId(), newExile);
MageFrame.getDesktop().add(newExile, JLayeredPane.POPUP_LAYER);
newExile.show();
} }
exiles.get(exile.getId()).loadCards(exile, bigCard, gameId); exiles.get(exile.getId()).loadCards(exile, bigCard, gameId);
} }
if (game.getCombat().size() > 0) { if (game.getCombat().size() > 0) {
combat.showDialog(game.getCombat()); MageFrame.getCombatDialog().showDialog(game.getCombat());
} }
else { else {
combat.hideDialog(); MageFrame.getCombatDialog().hideDialog();
} }
this.revalidate(); this.revalidate();
this.repaint(); this.repaint();
} }
public void ask(String question) { public void ask(String question, GameView gameView) {
updateGame(gameView);
this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, true, false); this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, true, false);
} }
@ -309,11 +320,11 @@ public class GamePanel extends javax.swing.JPanel {
} }
public void getAmount(int min, int max, String message) { public void getAmount(int min, int max, String message) {
pickNumber.showDialog(min, max, message); MageFrame.getPickNumberDialog().showDialog(min, max, message);
if (pickNumber.isCancel()) if (MageFrame.getPickNumberDialog().isCancel())
session.sendPlayerBoolean(gameId, false); session.sendPlayerBoolean(gameId, false);
else else
session.sendPlayerInteger(gameId, pickNumber.getAmount()); session.sendPlayerInteger(gameId, MageFrame.getPickNumberDialog().getAmount());
} }
public void getChoice(String message, String[] choices) { public void getChoice(String message, String[] choices) {
@ -350,14 +361,12 @@ public class GamePanel extends javax.swing.JPanel {
btnStopWatching = new javax.swing.JButton(); btnStopWatching = new javax.swing.JButton();
bigCard = new mage.client.cards.BigCard(); bigCard = new mage.client.cards.BigCard();
stack = new mage.client.cards.Cards(); stack = new mage.client.cards.Cards();
btnCheat = new javax.swing.JButton();
pnlReplay = new javax.swing.JPanel(); pnlReplay = new javax.swing.JPanel();
btnStopReplay = new javax.swing.JButton(); btnStopReplay = new javax.swing.JButton();
btnPreviousPlay = new javax.swing.JButton(); btnPreviousPlay = new javax.swing.JButton();
btnNextPlay = new javax.swing.JButton(); btnNextPlay = new javax.swing.JButton();
pnlHand = new javax.swing.JPanel();
hand = new mage.client.cards.Cards();
pnlBattlefield = new javax.swing.JPanel(); pnlBattlefield = new javax.swing.JPanel();
hand = new mage.client.cards.Cards();
chatPanel = new mage.client.chat.ChatPanel(); chatPanel = new mage.client.chat.ChatPanel();
jSplitPane1.setBorder(null); jSplitPane1.setBorder(null);
@ -420,12 +429,7 @@ public class GamePanel extends javax.swing.JPanel {
} }
}); });
btnCheat.setText("?"); stack.setPreferredSize(new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight + 25));
btnCheat.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCheatActionPerformed(evt);
}
});
btnStopReplay.setText("Stop"); btnStopReplay.setText("Stop");
btnStopReplay.addActionListener(new java.awt.event.ActionListener() { btnStopReplay.addActionListener(new java.awt.event.ActionListener() {
@ -492,9 +496,7 @@ public class GamePanel extends javax.swing.JPanel {
.addComponent(btnConcede) .addComponent(btnConcede)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnStopWatching) .addComponent(btnStopWatching)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addContainerGap(62, Short.MAX_VALUE))
.addComponent(btnCheat)
.addContainerGap(19, Short.MAX_VALUE))
.addComponent(bigCard, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) .addComponent(bigCard, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)
.addComponent(feedbackPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) .addComponent(feedbackPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)
.addComponent(stack, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) .addComponent(stack, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)
@ -528,36 +530,21 @@ public class GamePanel extends javax.swing.JPanel {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(feedbackPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(feedbackPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(stack, javax.swing.GroupLayout.PREFERRED_SIZE, 209, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(stack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 8, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 164, Short.MAX_VALUE)
.addComponent(pnlReplay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(pnlReplay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnConcede) .addComponent(btnConcede)
.addComponent(btnStopWatching) .addComponent(btnStopWatching)))
.addComponent(btnCheat)))
);
pnlHand.setBorder(javax.swing.BorderFactory.createEtchedBorder());
pnlHand.setPreferredSize(new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight + 25));
hand.setPreferredSize(new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight));
javax.swing.GroupLayout pnlHandLayout = new javax.swing.GroupLayout(pnlHand);
pnlHand.setLayout(pnlHandLayout);
pnlHandLayout.setHorizontalGroup(
pnlHandLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(hand, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 711, Short.MAX_VALUE)
);
pnlHandLayout.setVerticalGroup(
pnlHandLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(hand, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 209, Short.MAX_VALUE)
); );
pnlBattlefield.setLayout(new java.awt.GridBagLayout()); pnlBattlefield.setLayout(new java.awt.GridBagLayout());
hand.setPreferredSize(new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight + 25));
javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout); jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup( jPanel3Layout.setHorizontalGroup(
@ -566,15 +553,15 @@ public class GamePanel extends javax.swing.JPanel {
.addComponent(pnlGameInfo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(pnlGameInfo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pnlHand, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(hand, javax.swing.GroupLayout.DEFAULT_SIZE, 715, Short.MAX_VALUE)
.addComponent(pnlBattlefield, javax.swing.GroupLayout.DEFAULT_SIZE, 715, Short.MAX_VALUE))) .addComponent(pnlBattlefield, javax.swing.GroupLayout.DEFAULT_SIZE, 715, Short.MAX_VALUE)))
); );
jPanel3Layout.setVerticalGroup( jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
.addComponent(pnlBattlefield, javax.swing.GroupLayout.DEFAULT_SIZE, 634, Short.MAX_VALUE) .addComponent(pnlBattlefield, javax.swing.GroupLayout.DEFAULT_SIZE, 794, Short.MAX_VALUE)
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(pnlHand, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(hand, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(pnlGameInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnlGameInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
@ -591,7 +578,7 @@ public class GamePanel extends javax.swing.JPanel {
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 847, Short.MAX_VALUE) .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 798, Short.MAX_VALUE)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -621,18 +608,9 @@ public class GamePanel extends javax.swing.JPanel {
session.previousPlay(); session.previousPlay();
}//GEN-LAST:event_btnPreviousPlayActionPerformed }//GEN-LAST:event_btnPreviousPlayActionPerformed
private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheatActionPerformed
try {
session.cheat(gameId, DeckCardLists.load("cheat.dck"));
} catch (Exception ex) {
logger.log(Level.SEVERE, null, ex);
}
}//GEN-LAST:event_btnCheatActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private mage.client.game.AbilityPicker abilityPicker; private mage.client.game.AbilityPicker abilityPicker;
private mage.client.cards.BigCard bigCard; private mage.client.cards.BigCard bigCard;
private javax.swing.JButton btnCheat;
private javax.swing.JButton btnConcede; private javax.swing.JButton btnConcede;
private javax.swing.JButton btnNextPlay; private javax.swing.JButton btnNextPlay;
private javax.swing.JButton btnPreviousPlay; private javax.swing.JButton btnPreviousPlay;
@ -650,7 +628,6 @@ public class GamePanel extends javax.swing.JPanel {
private javax.swing.JLabel lblTurn; private javax.swing.JLabel lblTurn;
private javax.swing.JPanel pnlBattlefield; private javax.swing.JPanel pnlBattlefield;
private javax.swing.JPanel pnlGameInfo; private javax.swing.JPanel pnlGameInfo;
private javax.swing.JPanel pnlHand;
private javax.swing.JPanel pnlReplay; private javax.swing.JPanel pnlReplay;
private mage.client.cards.Cards stack; private mage.client.cards.Cards stack;
private javax.swing.JLabel txtActivePlayer; private javax.swing.JLabel txtActivePlayer;

View file

@ -25,8 +25,8 @@
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="1" pref="278" max="32767" attributes="0"/>
<Component id="jPanel1" alignment="0" max="32767" attributes="0"/> <Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="1" pref="252" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
@ -45,6 +45,7 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="manaPool" alignment="0" pref="116" max="32767" attributes="1"/> <Component id="manaPool" alignment="0" pref="116" max="32767" attributes="1"/>
<Component id="playerPanel" alignment="0" max="32767" attributes="1"/> <Component id="playerPanel" alignment="0" max="32767" attributes="1"/>
<Component id="btnCheat" alignment="0" pref="116" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
@ -53,7 +54,8 @@
<Component id="playerPanel" min="-2" max="-2" attributes="0"/> <Component id="playerPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="manaPool" min="-2" max="-2" attributes="0"/> <Component id="manaPool" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="14" max="32767" attributes="0"/> <EmptySpace pref="17" max="32767" attributes="0"/>
<Component id="btnCheat" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -63,6 +65,14 @@
</Component> </Component>
<Component class="mage.client.game.ManaPool" name="manaPool"> <Component class="mage.client.game.ManaPool" name="manaPool">
</Component> </Component>
<Component class="javax.swing.JButton" name="btnCheat">
<Properties>
<Property name="text" type="java.lang.String" value="Cheat"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCheatActionPerformed"/>
</Events>
</Component>
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javax.swing.JScrollPane" name="jScrollPane1"> <Container class="javax.swing.JScrollPane" name="jScrollPane1">

View file

@ -34,7 +34,13 @@
package mage.client.game; package mage.client.game;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.cards.decks.DeckCardLists;
import mage.client.MageFrame;
import mage.client.cards.BigCard; import mage.client.cards.BigCard;
import mage.view.PlayerView; import mage.view.PlayerView;
@ -44,7 +50,9 @@ import mage.view.PlayerView;
*/ */
public class PlayAreaPanel extends javax.swing.JPanel { public class PlayAreaPanel extends javax.swing.JPanel {
UUID playerId;
UUID gameId;
/** Creates new form PlayAreaPanel */ /** Creates new form PlayAreaPanel */
public PlayAreaPanel() { public PlayAreaPanel() {
initComponents(); initComponents();
@ -59,6 +67,14 @@ public class PlayAreaPanel extends javax.swing.JPanel {
public void init(PlayerView player, BigCard bigCard, UUID gameId) { public void init(PlayerView player, BigCard bigCard, UUID gameId) {
this.playerPanel.init(gameId, player.getPlayerId(), bigCard); this.playerPanel.init(gameId, player.getPlayerId(), bigCard);
this.battlefieldPanel.init(gameId, bigCard); this.battlefieldPanel.init(gameId, bigCard);
if (MageFrame.getSession().isTestMode()) {
this.playerId = player.getPlayerId();
this.gameId = gameId;
this.btnCheat.setVisible(true);
}
else {
this.btnCheat.setVisible(false);
}
} }
public void update(PlayerView player) { public void update(PlayerView player) {
@ -80,17 +96,26 @@ public class PlayAreaPanel extends javax.swing.JPanel {
jPanel1 = new javax.swing.JPanel(); jPanel1 = new javax.swing.JPanel();
playerPanel = new mage.client.game.PlayerPanel(); playerPanel = new mage.client.game.PlayerPanel();
manaPool = new mage.client.game.ManaPool(); manaPool = new mage.client.game.ManaPool();
btnCheat = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane(); jScrollPane1 = new javax.swing.JScrollPane();
battlefieldPanel = new mage.client.game.BattlefieldPanel(); battlefieldPanel = new mage.client.game.BattlefieldPanel();
jPanel1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); jPanel1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
btnCheat.setText("Cheat");
btnCheat.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCheatActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout); jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup( jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(manaPool, javax.swing.GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE) .addComponent(manaPool, javax.swing.GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE)
.addComponent(playerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(playerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnCheat, javax.swing.GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE)
); );
jPanel1Layout.setVerticalGroup( jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -98,7 +123,8 @@ public class PlayAreaPanel extends javax.swing.JPanel {
.addComponent(playerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(playerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(manaPool, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(manaPool, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(14, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 17, Short.MAX_VALUE)
.addComponent(btnCheat))
); );
jScrollPane1.setViewportView(battlefieldPanel); jScrollPane1.setViewportView(battlefieldPanel);
@ -114,14 +140,27 @@ public class PlayAreaPanel extends javax.swing.JPanel {
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 252, Short.MAX_VALUE)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheatActionPerformed
try {
MageFrame.getSession().cheat(gameId, playerId, DeckCardLists.load("cheat.dck"));
} catch (FileNotFoundException ex) {
Logger.getLogger(PlayAreaPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(PlayAreaPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(PlayAreaPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}//GEN-LAST:event_btnCheatActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private mage.client.game.BattlefieldPanel battlefieldPanel; private mage.client.game.BattlefieldPanel battlefieldPanel;
private javax.swing.JButton btnCheat;
private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane1;
private mage.client.game.ManaPool manaPool; private mage.client.game.ManaPool manaPool;

View file

@ -65,91 +65,90 @@ public class Client implements CallbackClient {
@Override @Override
public synchronized void processCallback(ClientCallback callback) { public synchronized void processCallback(ClientCallback callback) {
if (callback.getMessageId() > messageId) { logger.info(callback.getMessageId() + " - " + callback.getMethod());
messageId = callback.getMessageId(); if (callback.getMethod().equals("startGame")) {
logger.info(callback.getMessageId() + " - " + callback.getMethod()); UUID[] data = (UUID[]) callback.getData();
if (callback.getMethod().equals("startGame")) { gameStarted(data[0], data[1]);
UUID[] data = (UUID[]) callback.getData(); }
gameStarted(data[0], data[1]); else if (callback.getMethod().equals("replayGame")) {
replayGame();
}
else if (callback.getMethod().equals("watchGame")) {
watchGame((UUID) callback.getData());
}
else if (callback.getMethod().equals("chatMessage")) {
ChatMessage message = (ChatMessage) callback.getData();
session.getChats().get(message.getChatId()).receiveMessage(message.getMessage(), message.getColor());
}
else if (callback.getMethod().equals("replayInit")) {
session.getGame().init((GameView) callback.getData());
}
else if (callback.getMethod().equals("replayDone")) {
session.getGame().modalMessage((String) callback.getData());
session.getGame().hideGame();
}
else if (callback.getMethod().equals("replayUpdate")) {
session.getGame().updateGame((GameView) callback.getData());
}
else if (callback.getMethod().equals("gameInit")) {
session.getGame().init((GameView) callback.getData());
}
else if (callback.getMethod().equals("gameOver")) {
session.getGame().modalMessage((String) callback.getData());
session.getGame().hideGame();
}
else if (callback.getMethod().equals("gameAsk")) {
GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().ask(message.getMessage(), message.getGameView());
}
else if (callback.getMethod().equals("gameTarget")) {
GameClientMessage message = (GameClientMessage) callback.getData();
if (message.isFlag()) {
session.getGame().inform(message.getMessage(), message.getCardsView(), message.getGameView());
} else {
session.getGame().cancel(message.getMessage(), message.getCardsView(), message.getGameView());
} }
else if (callback.getMethod().equals("replayGame")) { }
replayGame(); else if (callback.getMethod().equals("gameSelect")) {
} GameClientMessage message = (GameClientMessage) callback.getData();
else if (callback.getMethod().equals("watchGame")) { session.getGame().select(message.getMessage(), message.getGameView());
watchGame((UUID) callback.getData()); }
} else if (callback.getMethod().equals("gameChooseAbility")) {
else if (callback.getMethod().equals("chatMessage")) { session.getGame().pickAbility((AbilityPickerView) callback.getData());
ChatMessage message = (ChatMessage) callback.getData(); }
session.getChats().get(message.getChatId()).receiveMessage(message.getMessage()); else if (callback.getMethod().equals("gameChoose")) {
} GameClientMessage message = (GameClientMessage) callback.getData();
else if (callback.getMethod().equals("replayInit")) { session.getGame().getChoice(message.getMessage(), message.getStrings());
session.getGame().init((GameView) callback.getData()); }
} else if (callback.getMethod().equals("gamePlayMana")) {
else if (callback.getMethod().equals("replayDone")) { GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().modalMessage((String) callback.getData()); session.getGame().playMana(message.getMessage(), message.getGameView());
session.getGame().hideGame(); }
} else if (callback.getMethod().equals("gamePlayXMana")) {
else if (callback.getMethod().equals("replayUpdate")) { GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().updateGame((GameView) callback.getData()); session.getGame().playXMana(message.getMessage(), message.getGameView());
} }
else if (callback.getMethod().equals("gameInit")) { else if (callback.getMethod().equals("gameSelectAmount")) {
session.getGame().init((GameView) callback.getData()); GameClientMessage message = (GameClientMessage) callback.getData();
} session.getGame().getAmount(message.getMin(), message.getMax(), message.getMessage());
else if (callback.getMethod().equals("gameUpdate")) { }
session.getGame().updateGame((GameView) callback.getData()); else if (callback.getMethod().equals("gameReveal")) {
} GameClientMessage message = (GameClientMessage) callback.getData();
else if (callback.getMethod().equals("gameInform")) { session.getGame().revealCards(message.getMessage(), message.getCardsView());
}
else if (callback.getMethod().equals("gameUpdate")) {
session.getGame().updateGame((GameView) callback.getData());
}
else if (callback.getMethod().equals("gameInform")) {
if (callback.getMessageId() > messageId) {
GameClientMessage message = (GameClientMessage) callback.getData(); GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().inform(message.getMessage(), null, message.getGameView()); session.getGame().inform(message.getMessage(), null, message.getGameView());
} }
else if (callback.getMethod().equals("gameOver")) { else {
session.getGame().modalMessage((String) callback.getData()); logger.warning("message out of sequence - ignoring");
session.getGame().hideGame();
}
else if (callback.getMethod().equals("gameAsk")) {
GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().updateGame(message.getGameView());
session.getGame().ask(message.getMessage());
}
else if (callback.getMethod().equals("gameTarget")) {
GameClientMessage message = (GameClientMessage) callback.getData();
if (message.isFlag()) {
session.getGame().inform(message.getMessage(), message.getCardsView(), message.getGameView());
} else {
session.getGame().cancel(message.getMessage(), message.getCardsView(), message.getGameView());
}
}
else if (callback.getMethod().equals("gameSelect")) {
GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().select(message.getMessage(), message.getGameView());
}
else if (callback.getMethod().equals("gameChooseAbility")) {
session.getGame().pickAbility((AbilityPickerView) callback.getData());
}
else if (callback.getMethod().equals("gameChoose")) {
GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().getChoice(message.getMessage(), message.getStrings());
}
else if (callback.getMethod().equals("gamePlayMana")) {
GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().playMana(message.getMessage(), message.getGameView());
}
else if (callback.getMethod().equals("gamePlayXMana")) {
GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().playXMana(message.getMessage(), message.getGameView());
}
else if (callback.getMethod().equals("gameSelectAmount")) {
GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().getAmount(message.getMin(), message.getMax(), message.getMessage());
}
else if (callback.getMethod().equals("gameReveal")) {
GameClientMessage message = (GameClientMessage) callback.getData();
session.getGame().revealCards(message.getMessage(), message.getCardsView());
} }
} }
else { messageId = callback.getMessageId();
logger.warning("message out of sequence - ignoring");
}
} }
public UUID getId() throws RemoteException { public UUID getId() throws RemoteException {

View file

@ -50,6 +50,7 @@ import mage.client.util.Config;
import mage.game.GameException; import mage.game.GameException;
import mage.interfaces.MageException; import mage.interfaces.MageException;
import mage.interfaces.Server; import mage.interfaces.Server;
import mage.interfaces.ServerState;
import mage.interfaces.callback.CallbackClientDaemon; import mage.interfaces.callback.CallbackClientDaemon;
import mage.util.Logging; import mage.util.Logging;
import mage.view.GameTypeView; import mage.view.GameTypeView;
@ -68,9 +69,10 @@ public class Session {
private Client client; private Client client;
private String userName; private String userName;
private MageFrame frame; private MageFrame frame;
private String[] playerTypes; private ServerState serverState;
private List<GameTypeView> gameTypes; // private String[] playerTypes;
private String[] deckTypes; // private List<GameTypeView> gameTypes;
// private String[] deckTypes;
private Map<UUID, ChatPanel> chats = new HashMap<UUID, ChatPanel>(); private Map<UUID, ChatPanel> chats = new HashMap<UUID, ChatPanel>();
private GamePanel game; private GamePanel game;
private CallbackClientDaemon callbackDaemon; private CallbackClientDaemon callbackDaemon;
@ -91,9 +93,7 @@ public class Session {
this.client = new Client(this, frame, userName); this.client = new Client(this, frame, userName);
sessionId = server.registerClient(userName, client.getId()); sessionId = server.registerClient(userName, client.getId());
callbackDaemon = new CallbackClientDaemon(sessionId, client, server); callbackDaemon = new CallbackClientDaemon(sessionId, client, server);
playerTypes = server.getPlayerTypes(); serverState = server.getServerState();
gameTypes = server.getGameTypes();
deckTypes = server.getDeckTypes();
logger.info("Connected to RMI server at " + serverName + ":" + port); logger.info("Connected to RMI server at " + serverName + ":" + port);
frame.setStatusText("Connected to " + serverName + ":" + port + " "); frame.setStatusText("Connected to " + serverName + ":" + port + " ");
frame.enableButtons(); frame.enableButtons();
@ -127,15 +127,19 @@ public class Session {
} }
public String[] getPlayerTypes() { public String[] getPlayerTypes() {
return playerTypes; return serverState.getPlayerTypes();
} }
public List<GameTypeView> getGameTypes() { public List<GameTypeView> getGameTypes() {
return gameTypes; return serverState.getGameTypes();
} }
public String[] getDeckTypes() { public String[] getDeckTypes() {
return deckTypes; return serverState.getDeckTypes();
}
public boolean isTestMode() {
return serverState.isTestMode();
} }
public Map<UUID, ChatPanel> getChats() { public Map<UUID, ChatPanel> getChats() {
@ -229,9 +233,9 @@ public class Session {
return false; return false;
} }
public boolean joinTable(UUID roomId, UUID tableId, int seat, String playerName, DeckCardLists deckList) { public boolean joinTable(UUID roomId, UUID tableId, String playerName, DeckCardLists deckList) {
try { try {
return server.joinTable(sessionId, roomId, tableId, seat, playerName, deckList); return server.joinTable(sessionId, roomId, tableId, playerName, deckList);
} catch (RemoteException ex) { } catch (RemoteException ex) {
handleRemoteException(ex); handleRemoteException(ex);
} catch (MageException ex) { } catch (MageException ex) {
@ -506,9 +510,9 @@ public class Session {
return false; return false;
} }
public boolean cheat(UUID gameId, DeckCardLists deckList) { public boolean cheat(UUID gameId, UUID playerId, DeckCardLists deckList) {
try { try {
server.cheat(gameId, sessionId, deckList); server.cheat(gameId, sessionId, playerId, deckList);
return true; return true;
} catch (RemoteException ex) { } catch (RemoteException ex) {
handleRemoteException(ex); handleRemoteException(ex);

View file

@ -72,9 +72,9 @@ public class TablePlayerPanel extends javax.swing.JPanel {
this.lblPlayerNum.setText("Player " + playerNum); this.lblPlayerNum.setText("Player " + playerNum);
} }
public boolean joinTable(UUID roomId, UUID tableId, int seatNum) throws FileNotFoundException, IOException, ClassNotFoundException { public boolean joinTable(UUID roomId, UUID tableId) throws FileNotFoundException, IOException, ClassNotFoundException {
if (!this.cbPlayerType.getSelectedItem().equals("Human")) { if (!this.cbPlayerType.getSelectedItem().equals("Human")) {
return session.joinTable(roomId, tableId, seatNum, this.newPlayerPanel.getPlayerName(), DeckCardLists.load(this.newPlayerPanel.getDeckFile())); return session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), DeckCardLists.load(this.newPlayerPanel.getDeckFile()));
} }
return true; return true;
} }

View file

@ -266,14 +266,12 @@ public class TablesPanel extends javax.swing.JPanel implements Observer {
session.joinTable( session.joinTable(
roomId, roomId,
table.getTableId(), table.getTableId(),
0,
"Human", "Human",
DeckCardLists.load("test.dck") DeckCardLists.load("test.dck")
); );
session.joinTable( session.joinTable(
roomId, roomId,
table.getTableId(), table.getTableId(),
1,
"Computer", "Computer",
DeckCardLists.load("test.dck") DeckCardLists.load("test.dck")
); );

View file

@ -46,17 +46,14 @@ import mage.view.TableView;
*/ */
public interface Server extends Remote, CallbackServer { public interface Server extends Remote, CallbackServer {
// public String getClientIp() throws RemoteException, MageException;
public UUID registerClient(String userName, UUID clientId) throws RemoteException, MageException; public UUID registerClient(String userName, UUID clientId) throws RemoteException, MageException;
public void deregisterClient(UUID sessionId) throws RemoteException, MageException; public void deregisterClient(UUID sessionId) throws RemoteException, MageException;
public List<GameTypeView> getGameTypes() throws RemoteException, MageException; public ServerState getServerState() throws RemoteException, MageException;
public String[] getPlayerTypes() throws RemoteException, MageException;
public String[] getDeckTypes() throws RemoteException, MageException;
//table methods //table methods
public TableView createTable(UUID sessionId, UUID roomId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) throws RemoteException, MageException; public TableView createTable(UUID sessionId, UUID roomId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) throws RemoteException, MageException;
public boolean joinTable(UUID sessionId, UUID roomId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws RemoteException, MageException, GameException; public boolean joinTable(UUID sessionId, UUID roomId, UUID tableId, String name, DeckCardLists deckList) throws RemoteException, MageException, GameException;
public boolean watchTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException; public boolean watchTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException;
public boolean replayTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException; public boolean replayTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException;
public void leaveTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException; public void leaveTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException;
@ -95,6 +92,6 @@ public interface Server extends Remote, CallbackServer {
public void previousPlay(UUID sessionId) throws RemoteException, MageException; public void previousPlay(UUID sessionId) throws RemoteException, MageException;
//test methods //test methods
public void cheat(UUID gameId, UUID sessionId, DeckCardLists deckList) throws RemoteException, MageException; public void cheat(UUID gameId, UUID sessionId, UUID playerId, DeckCardLists deckList) throws RemoteException, MageException;
} }

View file

@ -0,0 +1,69 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.interfaces;
import java.io.Serializable;
import java.util.List;
import mage.view.GameTypeView;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class ServerState implements Serializable {
private List<GameTypeView> gameTypes;
private String[] playerTypes;
private String[] deckTypes;
private boolean testMode;
public ServerState(List<GameTypeView> gameTypes, String[] playerTypes, String[] deckTypes, boolean testMode) {
this.gameTypes = gameTypes;
this.playerTypes = playerTypes;
this.deckTypes = deckTypes;
this.testMode = testMode;
}
public List<GameTypeView> getGameTypes() {
return gameTypes;
}
public String[] getPlayerTypes() {
return playerTypes;
}
public String[] getDeckTypes() {
return deckTypes;
}
public boolean isTestMode() {
return testMode;
}
}

View file

@ -78,7 +78,7 @@ public class CardView implements Serializable {
} }
protected CardView() { protected CardView() {
} }
protected List<String> formatRules(List<String> rules) { protected List<String> formatRules(List<String> rules) {

View file

@ -28,40 +28,39 @@
package mage.view; package mage.view;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import mage.MageObject; import java.util.HashMap;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.Cards; import mage.game.GameState;
import mage.game.Game;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class CardsView extends ArrayList<CardView> { public class CardsView extends HashMap<UUID, CardView> {
public CardsView() {} public CardsView() {}
public CardsView(Collection<Card> cards) { public CardsView(Collection<Card> cards) {
for (Card card: cards) { for (Card card: cards) {
this.add(new CardView(card)); this.put(card.getId(), new CardView(card));
} }
} }
public CardsView(Cards cards) { // public CardsView(Cards cards) {
if (cards != null) // if (cards != null)
for (Card card: cards.values()) { // for (Card card: cards.values()) {
this.add(new CardView(card)); // this.add(new CardView(card));
} // }
} // }
public CardsView(Collection<? extends Ability> abilities, Game game) { public CardsView(Collection<? extends Ability> abilities, GameState state) {
for (Ability ability: abilities) { for (Ability ability: abilities) {
String sourceName = game.getPermanent(ability.getSourceId()).getName(); String sourceName = state.getPermanent(ability.getSourceId()).getName();
this.add(new AbilityView(ability, sourceName)); this.put(ability.getId(), new AbilityView(ability, sourceName));
} }
} }

View file

@ -39,10 +39,16 @@ public class ChatMessage implements Serializable {
private UUID chatId; private UUID chatId;
private String message; private String message;
private MessageColor color;
public ChatMessage(UUID chatId, String message) { public enum MessageColor {
BLACK, RED, GREEN, BLUE, ORANGE;
}
public ChatMessage(UUID chatId, String message, MessageColor color) {
this.chatId = chatId; this.chatId = chatId;
this.message = message; this.message = message;
this.color = color;
} }
public String getMessage() { public String getMessage() {
@ -52,4 +58,8 @@ public class ChatMessage implements Serializable {
public UUID getChatId() { public UUID getChatId() {
return chatId; return chatId;
} }
public MessageColor getColor() {
return color;
}
} }

View file

@ -30,6 +30,7 @@ package mage.view;
import java.io.Serializable; import java.io.Serializable;
import java.util.UUID; import java.util.UUID;
import mage.game.Game;
import mage.game.GameState; import mage.game.GameState;
import mage.game.combat.CombatGroup; import mage.game.combat.CombatGroup;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -45,20 +46,24 @@ public class CombatGroupView implements Serializable {
private CardsView blockers = new CardsView(); private CardsView blockers = new CardsView();
private String defenderName; private String defenderName;
public CombatGroupView(CombatGroup combatGroup, GameState game) { public CombatGroupView(CombatGroup combatGroup, GameState state) {
Player player = game.getPlayer(combatGroup.getDefenderId()); Player player = state.getPlayer(combatGroup.getDefenderId());
if (player != null) { if (player != null) {
this.defenderName = player.getName(); this.defenderName = player.getName();
} }
else { else {
Permanent perm = game.getPermanent(combatGroup.getDefenderId()); Permanent perm = state.getPermanent(combatGroup.getDefenderId());
this.defenderName = perm.getName(); this.defenderName = perm.getName();
} }
for (UUID id: combatGroup.getAttackers()) { for (UUID id: combatGroup.getAttackers()) {
attackers.add(new PermanentView(game.getPermanent(id))); Permanent attacker = state.getPermanent(id);
if (attacker != null)
attackers.put(id, new PermanentView(attacker));
} }
for (UUID id: combatGroup.getBlockers()) { for (UUID id: combatGroup.getBlockers()) {
blockers.add(new PermanentView(game.getPermanent(id))); Permanent blocker = state.getPermanent(id);
if (blocker != null)
blockers.put(id, new PermanentView(blocker));
} }
} }

View file

@ -31,6 +31,7 @@ package mage.view;
import java.util.UUID; import java.util.UUID;
import mage.cards.Card; import mage.cards.Card;
import mage.game.ExileZone; import mage.game.ExileZone;
import mage.game.Game;
/** /**
* *
@ -41,11 +42,11 @@ public class ExileView extends CardsView {
private String name; private String name;
private UUID id; private UUID id;
public ExileView(ExileZone exileZone) { public ExileView(ExileZone exileZone, Game game) {
this.name = exileZone.getName(); this.name = exileZone.getName();
this.id = exileZone.getId(); this.id = exileZone.getId();
for (Card card: exileZone.values()) { for (Card card: exileZone.getCards(game)) {
this.add(new CardView(card)); this.put(card.getId(), new CardView(card));
} }
} }

View file

@ -35,6 +35,7 @@ import mage.Constants.PhaseStep;
import mage.Constants.TurnPhase; import mage.Constants.TurnPhase;
import mage.MageObject; import mage.MageObject;
import mage.game.ExileZone; import mage.game.ExileZone;
import mage.game.Game;
import mage.game.GameState; import mage.game.GameState;
import mage.game.combat.CombatGroup; import mage.game.combat.CombatGroup;
import mage.game.stack.Spell; import mage.game.stack.Spell;
@ -60,40 +61,40 @@ public class GameView implements Serializable {
private int turn; private int turn;
private boolean special = false; private boolean special = false;
public GameView(GameState game) { public GameView(GameState state, Game game) {
for (Player player: game.getPlayers().values()) { for (Player player: state.getPlayers().values()) {
players.add(new PlayerView(player, game)); players.add(new PlayerView(player, state, game));
} }
for (StackObject stackObject: game.getStack()) { for (StackObject stackObject: state.getStack()) {
if (stackObject instanceof StackAbility) { if (stackObject instanceof StackAbility) {
MageObject object = game.getObject(stackObject.getSourceId()); MageObject object = game.getObject(stackObject.getSourceId());
if (object != null) if (object != null)
stack.add(new StackAbilityView((StackAbility)stackObject, object.getName())); stack.put(stackObject.getId(), new StackAbilityView((StackAbility)stackObject, object.getName()));
else else
stack.add(new StackAbilityView((StackAbility)stackObject, "")); stack.put(null, new StackAbilityView((StackAbility)stackObject, ""));
} }
else { else {
stack.add(new CardView((Spell)stackObject)); stack.put(stackObject.getId(), new CardView((Spell)stackObject));
} }
} }
for (ExileZone exileZone: game.getExile().getExileZones()) { for (ExileZone exileZone: state.getExile().getExileZones()) {
exiles.add(new ExileView(exileZone)); exiles.add(new ExileView(exileZone, game));
} }
this.phase = game.getTurn().getPhaseType(); this.phase = state.getTurn().getPhaseType();
this.step = game.getTurn().getStepType(); this.step = state.getTurn().getStepType();
this.turn = game.getTurnNum(); this.turn = state.getTurnNum();
if (game.getActivePlayerId() != null) if (state.getActivePlayerId() != null)
this.activePlayerName = game.getPlayer(game.getActivePlayerId()).getName(); this.activePlayerName = state.getPlayer(state.getActivePlayerId()).getName();
else else
this.activePlayerName = ""; this.activePlayerName = "";
if (game.getPriorityPlayerId() != null) if (state.getPriorityPlayerId() != null)
this.priorityPlayerName = game.getPlayer(game.getPriorityPlayerId()).getName(); this.priorityPlayerName = state.getPlayer(state.getPriorityPlayerId()).getName();
else else
this.priorityPlayerName = ""; this.priorityPlayerName = "";
for (CombatGroup combatGroup: game.getCombat().getGroups()) { for (CombatGroup combatGroup: state.getCombat().getGroups()) {
combat.add(new CombatGroupView(combatGroup, game)); combat.add(new CombatGroupView(combatGroup, state));
} }
this.special = game.getSpecialActions().getControlledBy(game.getPriorityPlayerId()).size() > 0; this.special = state.getSpecialActions().getControlledBy(state.getPriorityPlayerId()).size() > 0;
} }
public List<PlayerView> getPlayers() { public List<PlayerView> getPlayers() {

View file

@ -33,6 +33,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import mage.cards.Card; import mage.cards.Card;
import mage.game.Game;
import mage.game.GameState; import mage.game.GameState;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
@ -54,33 +55,33 @@ public class PlayerView implements Serializable {
private CardsView graveyard = new CardsView(); private CardsView graveyard = new CardsView();
private Map<UUID, PermanentView> battlefield = new HashMap<UUID, PermanentView>(); private Map<UUID, PermanentView> battlefield = new HashMap<UUID, PermanentView>();
public PlayerView(Player player, GameState game) { public PlayerView(Player player, GameState state, Game game) {
this.playerId = player.getId(); this.playerId = player.getId();
this.name = player.getName(); this.name = player.getName();
this.life = player.getLife(); this.life = player.getLife();
this.libraryCount = player.getLibrary().size(); this.libraryCount = player.getLibrary().size();
this.handCount = player.getHand().size(); this.handCount = player.getHand().size();
this.manaPool = new ManaPoolView(player.getManaPool()); this.manaPool = new ManaPoolView(player.getManaPool());
this.isActive = (player.getId().equals(game.getActivePlayerId())); this.isActive = (player.getId().equals(state.getActivePlayerId()));
this.hasLeft = player.hasLeft(); this.hasLeft = player.hasLeft();
for (Card card: player.getGraveyard().values()) { for (Card card: player.getGraveyard().getCards(game)) {
graveyard.add(new CardView(card)); graveyard.put(card.getId(), new CardView(card));
} }
for (Permanent permanent: game.getBattlefield().getAllPermanents()) { for (Permanent permanent: state.getBattlefield().getAllPermanents()) {
if (showInBattlefield(permanent, game)) { if (showInBattlefield(permanent, state)) {
PermanentView view = new PermanentView(permanent); PermanentView view = new PermanentView(permanent);
battlefield.put(view.getId(), view); battlefield.put(view.getId(), view);
} }
} }
} }
private boolean showInBattlefield(Permanent permanent, GameState game) { private boolean showInBattlefield(Permanent permanent, GameState state) {
//show permanents controlled by player or attachments to permanents controlled by player //show permanents controlled by player or attachments to permanents controlled by player
if (permanent.getAttachedTo() == null) if (permanent.getAttachedTo() == null)
return permanent.getControllerId().equals(playerId); return permanent.getControllerId().equals(playerId);
else else
return game.getPermanent(permanent.getAttachedTo()).getControllerId().equals(playerId); return state.getPermanent(permanent.getAttachedTo()).getControllerId().equals(playerId);
} }
public int getLife() { public int getLife() {

View file

@ -58,8 +58,8 @@ public class Constructed extends DeckValidatorImpl {
List<String> basicLandNames = new ArrayList<String>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains")); List<String> basicLandNames = new ArrayList<String>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains"));
Map<String, Integer> counts = new HashMap<String, Integer>(); Map<String, Integer> counts = new HashMap<String, Integer>();
countCards(counts, deck.getCards().values()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard().values()); countCards(counts, deck.getSideboard());
for (Entry<String, Integer> entry: counts.entrySet()) { for (Entry<String, Integer> entry: counts.entrySet()) {
if (entry.getValue() > 4) { if (entry.getValue() > 4) {
if (!basicLandNames.contains(entry.getKey())) { if (!basicLandNames.contains(entry.getKey())) {

View file

@ -41,7 +41,7 @@ import mage.players.Player;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class FreeForAll extends GameImpl { public class FreeForAll extends GameImpl<FreeForAll> {
private int numPlayers; private int numPlayers;
private List<UUID> mulliganed = new ArrayList<UUID>(); private List<UUID> mulliganed = new ArrayList<UUID>();
@ -50,6 +50,14 @@ public class FreeForAll extends GameImpl {
super(attackOption, range); super(attackOption, range);
} }
public FreeForAll(final FreeForAll game) {
super(game);
this.numPlayers = game.numPlayers;
for (UUID playerId: game.mulliganed) {
mulliganed.add(playerId);
}
}
@Override @Override
public GameType getGameType() { public GameType getGameType() {
return new FreeForAllType(); return new FreeForAllType();
@ -88,11 +96,16 @@ public class FreeForAll extends GameImpl {
numCards += 1; numCards += 1;
mulliganed.add(playerId); mulliganed.add(playerId);
} }
player.getLibrary().addAll(player.getHand()); player.getLibrary().addAll(player.getHand().getCards(this));
player.getHand().clear(); player.getHand().clear();
player.shuffleLibrary(this); player.shuffleLibrary(this);
player.drawCards(numCards - 1, this); player.drawCards(numCards - 1, this);
fireInformEvent(player.getName() + " mulligans down to " + Integer.toString(numCards - 1) + " cards"); fireInformEvent(player.getName() + " mulligans down to " + Integer.toString(numCards - 1) + " cards");
} }
@Override
public FreeForAll copy() {
return new FreeForAll(this);
}
} }

View file

@ -36,12 +36,16 @@ import mage.Constants.PhaseStep;
import mage.Constants.RangeOfInfluence; import mage.Constants.RangeOfInfluence;
import mage.game.turn.TurnMod; import mage.game.turn.TurnMod;
public class TwoPlayerDuel extends GameImpl { public class TwoPlayerDuel extends GameImpl<TwoPlayerDuel> {
public TwoPlayerDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range) { public TwoPlayerDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range) {
super(MultiplayerAttackOption.LEFT, RangeOfInfluence.ALL); super(MultiplayerAttackOption.LEFT, RangeOfInfluence.ALL);
} }
public TwoPlayerDuel(final TwoPlayerDuel game) {
super(game);
}
@Override @Override
public GameType getGameType() { public GameType getGameType() {
return new TwoPlayerDuelType(); return new TwoPlayerDuelType();
@ -88,4 +92,9 @@ public class TwoPlayerDuel extends GameImpl {
return opponents; return opponents;
} }
@Override
public TwoPlayerDuel copy() {
return new TwoPlayerDuel(this);
}
} }

View file

@ -20,6 +20,7 @@ debug.test.classpath=\
dist.dir=dist dist.dir=dist
dist.jar=${dist.dir}/Mage.Player.AI.jar dist.jar=${dist.dir}/Mage.Player.AI.jar
dist.javadoc.dir=${dist.dir}/javadoc dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes= excludes=
file.reference.Mage.AI-src=src file.reference.Mage.AI-src=src
file.reference.Mage.AI-test=test file.reference.Mage.AI-test=test

View file

@ -40,14 +40,18 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.Constants.CardType; import mage.Constants.CardType;
import mage.Constants.Outcome; import mage.Constants.Outcome;
import mage.Constants.RangeOfInfluence; import mage.Constants.RangeOfInfluence;
import mage.Constants.Zone; import mage.Constants.Zone;
import mage.MageObject;
import mage.Mana; import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility; import mage.abilities.ActivatedAbility;
import mage.abilities.TriggeredAbilities; import mage.abilities.TriggeredAbilities;
import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbility;
@ -103,10 +107,10 @@ import mage.util.TreeNode;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class ComputerPlayer extends PlayerImpl implements Player { public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> implements Player {
private final static transient Logger logger = Logging.getLogger(ComputerPlayer.class.getName()); private final static transient Logger logger = Logging.getLogger(ComputerPlayer.class.getName());
private boolean abort = false; private boolean abort;
private transient Map<Mana, Card> unplayable = new TreeMap<Mana, Card>(); private transient Map<Mana, Card> unplayable = new TreeMap<Mana, Card>();
private transient List<Card> playableNonInstant = new ArrayList<Card>(); private transient List<Card> playableNonInstant = new ArrayList<Card>();
private transient List<Card> playableInstant = new ArrayList<Card>(); private transient List<Card> playableInstant = new ArrayList<Card>();
@ -121,31 +125,37 @@ public class ComputerPlayer extends PlayerImpl implements Player {
super(id); super(id);
} }
public ComputerPlayer(final ComputerPlayer player) {
super(player);
this.abort = player.abort;
}
@Override @Override
public boolean chooseMulligan(Game game) { public boolean chooseMulligan(Game game) {
logger.fine("chooseMulligan"); logger.fine("chooseMulligan");
if (hand.size() < 6) if (hand.size() < 6)
return false; return false;
List<Card> lands = hand.getCards(new FilterLandCard()); Set<Card> lands = hand.getCards(new FilterLandCard(), game);
if (lands.size() < 2 || lands.size() > hand.size() - 2) if (lands.size() < 2 || lands.size() > hand.size() - 2)
return true; return true;
return false; return false;
} }
@Override @Override
public boolean chooseTarget(Outcome outcome, Target target, Game game) { public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
logger.fine("chooseTarget: " + outcome.toString() + ":" + target.toString()); if (logger.isLoggable(Level.FINE))
logger.fine("chooseTarget: " + outcome.toString() + ":" + target.toString());
UUID opponentId = game.getOpponents(playerId).iterator().next(); UUID opponentId = game.getOpponents(playerId).iterator().next();
if (target instanceof TargetPlayer) { if (target instanceof TargetPlayer) {
if (outcome.isGood()) { if (outcome.isGood()) {
if (target.canTarget(playerId, game)) { if (target.canTarget(playerId, source, game)) {
target.addTarget(playerId, game); target.addTarget(playerId, source, game);
return true; return true;
} }
} }
else { else {
if (target.canTarget(playerId, game)) { if (target.canTarget(playerId, source, game)) {
target.addTarget(opponentId, game); target.addTarget(opponentId, source, game);
return true; return true;
} }
} }
@ -154,15 +164,15 @@ public class ComputerPlayer extends PlayerImpl implements Player {
findPlayables(game); findPlayables(game);
if (unplayable.size() > 0) { if (unplayable.size() > 0) {
for (int i = unplayable.size() - 1; i >= 0; i--) { for (int i = unplayable.size() - 1; i >= 0; i--) {
if (target.canTarget(unplayable.values().toArray(new Card[0])[i].getId(), game)) { if (target.canTarget(unplayable.values().toArray(new Card[0])[i].getId(), source, game)) {
target.addTarget(unplayable.values().toArray(new Card[0])[i].getId(), game); target.addTarget(unplayable.values().toArray(new Card[0])[i].getId(), source, game);
return true; return true;
} }
} }
} }
if (hand.size() > 0) { if (hand.size() > 0) {
if (target.canTarget(hand.keySet().toArray(new UUID[0])[0], game)) { if (target.canTarget(hand.toArray(new UUID[0])[0], source, game)) {
target.addTarget(hand.keySet().toArray(new UUID[0])[0], game); target.addTarget(hand.toArray(new UUID[0])[0], source, game);
return true; return true;
} }
} }
@ -173,8 +183,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (!outcome.isGood()) if (!outcome.isGood())
Collections.reverse(targets); Collections.reverse(targets);
for (Permanent permanent: targets) { for (Permanent permanent: targets) {
if (target.canTarget(permanent.getId(), game)) { if (target.canTarget(permanent.getId(), source, game)) {
target.addTarget(permanent.getId(), game); target.addTarget(permanent.getId(), source, game);
return true; return true;
} }
} }
@ -188,8 +198,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
targets = threats(opponentId, ((TargetPermanent)target).getFilter(), game); targets = threats(opponentId, ((TargetPermanent)target).getFilter(), game);
} }
for (Permanent permanent: targets) { for (Permanent permanent: targets) {
if (target.canTarget(permanent.getId(), game)) { if (target.canTarget(permanent.getId(), source, game)) {
target.addTarget(permanent.getId(), game); target.addTarget(permanent.getId(), source, game);
return true; return true;
} }
} }
@ -198,12 +208,13 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
@Override @Override
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Game game) { public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
logger.fine("chooseTarget: " + outcome.toString() + ":" + target.toString()); if (logger.isLoggable(Level.FINE))
logger.fine("chooseTarget: " + outcome.toString() + ":" + target.toString());
UUID opponentId = game.getOpponents(playerId).iterator().next(); UUID opponentId = game.getOpponents(playerId).iterator().next();
if (target instanceof TargetCreatureOrPlayerAmount) { if (target instanceof TargetCreatureOrPlayerAmount) {
if (game.getPlayer(opponentId).getLife() <= target.getAmountRemaining()) { if (game.getPlayer(opponentId).getLife() <= target.getAmountRemaining()) {
target.addTarget(opponentId, target.getAmountRemaining(), game); target.addTarget(opponentId, target.getAmountRemaining(), source, game);
return true; return true;
} }
List<Permanent> targets; List<Permanent> targets;
@ -214,9 +225,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
targets = threats(opponentId, new FilterCreaturePermanent(), game); targets = threats(opponentId, new FilterCreaturePermanent(), game);
} }
for (Permanent permanent: targets) { for (Permanent permanent: targets) {
if (target.canTarget(permanent.getId(), game)) { if (target.canTarget(permanent.getId(), source, game)) {
if (permanent.getToughness().getValue() <= target.getAmountRemaining()) { if (permanent.getToughness().getValue() <= target.getAmountRemaining()) {
target.addTarget(permanent.getId(), permanent.getToughness().getValue(), game); target.addTarget(permanent.getId(), permanent.getToughness().getValue(), source, game);
return true; return true;
} }
} }
@ -304,17 +315,17 @@ public class ComputerPlayer extends PlayerImpl implements Player {
protected void playLand(Game game) { protected void playLand(Game game) {
logger.fine("playLand"); logger.fine("playLand");
List<Card> lands = hand.getCards(new FilterLandCard()); Set<Card> lands = hand.getCards(new FilterLandCard(), game);
while (lands.size() > 0 && this.landsPlayed < this.landsPerTurn) { while (lands.size() > 0 && this.landsPlayed < this.landsPerTurn) {
if (lands.size() == 1) if (lands.size() == 1)
this.playLand(lands.get(0), game); this.playLand(lands.iterator().next(), game);
else { else {
playALand(lands, game); playALand(lands, game);
} }
} }
} }
protected void playALand(List<Card> lands, Game game) { protected void playALand(Set<Card> lands, Game game) {
logger.fine("playALand"); logger.fine("playALand");
//play a land that will allow us to play an unplayable //play a land that will allow us to play an unplayable
for (Mana mana: unplayable.keySet()) { for (Mana mana: unplayable.keySet()) {
@ -341,8 +352,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
} }
//play first available land //play first available land
this.playLand(lands.get(0), game); this.playLand(lands.iterator().next(), game);
lands.remove(0); lands.remove(lands.iterator().next());
} }
protected void findPlayables(Game game) { protected void findPlayables(Game game) {
@ -350,7 +361,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
playableNonInstant.clear(); playableNonInstant.clear();
unplayable.clear(); unplayable.clear();
playableAbilities.clear(); playableAbilities.clear();
List<Card> nonLands = hand.getCards(new FilterNonlandCard()); Set<Card> nonLands = hand.getCards(new FilterNonlandCard(), game);
ManaOptions available = getManaAvailable(game); ManaOptions available = getManaAvailable(game);
available.addMana(manaPool.getMana()); available.addMana(manaPool.getMana());
@ -402,7 +413,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
} }
} }
logger.fine("findPlayables: " + playableInstant.toString() + "---" + playableNonInstant.toString() + "---" + playableAbilities.toString() ); if (logger.isLoggable(Level.FINE))
logger.fine("findPlayables: " + playableInstant.toString() + "---" + playableNonInstant.toString() + "---" + playableAbilities.toString() );
} }
@Override @Override
@ -417,7 +429,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
ManaCost cost; ManaCost cost;
List<Permanent> producers; List<Permanent> producers;
if (unpaid instanceof ManaCosts) { if (unpaid instanceof ManaCosts) {
cost = ((ManaCosts)unpaid).get(0); cost = ((ManaCosts<ManaCost>)unpaid).get(0);
producers = getSortedProducers((ManaCosts)unpaid, game); producers = getSortedProducers((ManaCosts)unpaid, game);
} }
else { else {
@ -477,7 +489,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
* @param game * @param game
* @return List<Permanent> * @return List<Permanent>
*/ */
private List<Permanent> getSortedProducers(ManaCosts unpaid, Game game) { private List<Permanent> getSortedProducers(ManaCosts<ManaCost> unpaid, Game game) {
List<Permanent> unsorted = this.getAvailableManaProducers(game); List<Permanent> unsorted = this.getAvailableManaProducers(game);
Map<Permanent, Integer> scored = new HashMap<Permanent, Integer>(); Map<Permanent, Integer> scored = new HashMap<Permanent, Integer>();
for (Permanent permanent: unsorted) { for (Permanent permanent: unsorted) {
@ -490,6 +502,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
} }
} }
if (score > 0) // score mana producers that produce other types higher
score += permanent.getAbilities().getManaAbilities(Zone.BATTLEFIELD).size();
scored.put(permanent, score); scored.put(permanent, score);
} }
return sortByValue(scored); return sortByValue(scored);
@ -546,15 +560,19 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
@Override @Override
public boolean chooseTarget(Cards cards, TargetCard target, Game game) { public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) {
logger.fine("chooseTarget"); logger.fine("chooseTarget");
//TODO: improve this //TODO: improve this
//return first match //return first match
for (Card card: cards.getCards(target.getFilter())) { if (!target.doneChosing()) {
target.addTarget(card.getId(), game); for (Card card: cards.getCards(target.getFilter(), game)) {
return true; target.addTarget(card.getId(), source, game);
if (target.doneChosing())
return true;
}
return false;
} }
return false; return true;
} }
@Override @Override
@ -665,12 +683,12 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return potential; return potential;
} }
protected List<Permanent> getAvailableBlockers(Game game) { // protected List<Permanent> getAvailableBlockers(Game game) {
logger.fine("getAvailableBlockers"); // logger.fine("getAvailableBlockers");
FilterCreatureForCombat blockFilter = new FilterCreatureForCombat(); // FilterCreatureForCombat blockFilter = new FilterCreatureForCombat();
List<Permanent> blockers = game.getBattlefield().getAllActivePermanents(blockFilter, playerId); // List<Permanent> blockers = game.getBattlefield().getAllActivePermanents(blockFilter, playerId);
return blockers; // return blockers;
} // }
protected List<Permanent> getOpponentBlockers(UUID opponentId, Game game) { protected List<Permanent> getOpponentBlockers(UUID opponentId, Game game) {
logger.fine("getOpponentBlockers"); logger.fine("getOpponentBlockers");
@ -784,10 +802,24 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
protected void logState(Game game) { protected void logState(Game game) {
if (logger.isLoggable(Level.FINE))
logList("computer player hand: ", new ArrayList(hand.getCards(game)));
}
protected void logList(String message, List<MageObject> list) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("computer player hand: "); sb.append(message).append(": ");
for (Card card: hand.values()) { for (MageObject object: list) {
sb.append(card.getName()).append(","); sb.append(object.getName()).append(",");
}
logger.fine(sb.toString());
}
protected void logAbilityList(String message, List<Ability> list) {
StringBuilder sb = new StringBuilder();
sb.append(message).append(": ");
for (Ability ability: list) {
sb.append(ability.getRule()).append(",");
} }
logger.fine(sb.toString()); logger.fine(sb.toString());
} }
@ -798,7 +830,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (card.getSpellAbility().canActivate(playerId, game)) { if (card.getSpellAbility().canActivate(playerId, game)) {
for (Effect effect: card.getSpellAbility().getEffects()) { for (Effect effect: card.getSpellAbility().getEffects()) {
if (effect.getOutcome().equals(Outcome.DestroyPermanent)) { if (effect.getOutcome().equals(Outcome.DestroyPermanent)) {
if (card.getSpellAbility().getTargets().get(0).canTarget(creatureId, game)) { if (card.getSpellAbility().getTargets().get(0).canTarget(creatureId, card.getSpellAbility(), game)) {
if (this.activateAbility(card.getSpellAbility(), game)) if (this.activateAbility(card.getSpellAbility(), game))
return; return;
} }
@ -816,7 +848,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (card.getSpellAbility().canActivate(playerId, game)) { if (card.getSpellAbility().canActivate(playerId, game)) {
for (Effect effect: card.getSpellAbility().getEffects()) { for (Effect effect: card.getSpellAbility().getEffects()) {
if (effect instanceof DamageTargetEffect) { if (effect instanceof DamageTargetEffect) {
if (card.getSpellAbility().getTargets().get(0).canTarget(creatureId, game)) { if (card.getSpellAbility().getTargets().get(0).canTarget(creatureId, card.getSpellAbility(), game)) {
if (((DamageTargetEffect)effect).getAmount() > (creature.getPower().getValue() - creature.getDamage())) { if (((DamageTargetEffect)effect).getAmount() > (creature.getPower().getValue() - creature.getDamage())) {
if (this.activateAbility(card.getSpellAbility(), game)) if (this.activateAbility(card.getSpellAbility(), game))
return; return;
@ -837,5 +869,10 @@ public class ComputerPlayer extends PlayerImpl implements Player {
playableAbilities = new ArrayList<ActivatedAbility>(); playableAbilities = new ArrayList<ActivatedAbility>();
} }
@Override
public T copy() {
return (T)new ComputerPlayer(this);
}
} }

View file

@ -0,0 +1,7 @@
maxDepth=10
maxNodes=5000
evaluatorLifeFactor=2
evaluatorPermanentFactor=1
evaluatorCreatureFactor=1
evaluatorHandFactor=1
maxThinkSeconds=30

View file

@ -0,0 +1,75 @@
application.title=Mage.Player.AIMinimax
application.vendor=BetaSteward_at_googlemail.com
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/Mage.Player.AIMinimax.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
includes=**
jar.compress=false
javac.classpath=\
${reference.Mage.jar}:\
${reference.Mage_Player_AI.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.source=1.5
javac.target=1.5
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}:\
${libs.junit.classpath}:\
${libs.junit_4.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
jnlp.codebase.type=local
jnlp.descriptor=application
jnlp.enabled=false
jnlp.offline-allowed=false
jnlp.signed=false
meta.inf.dir=${src.dir}/META-INF
platform.active=default_platform
project.license=bsd
project.Mage=../Mage
project.Mage_Player_AI=../Mage.Player.AI
reference.Mage.jar=${project.Mage}/dist/Mage.jar
reference.Mage_Player_AI.jar=${project.Mage_Player_AI}/dist/Mage.Player.AI.jar
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
# or test-sys-prop.name=value to set system properties for unit tests):
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>Mage.Player.AIMinimax</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
<references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
<reference>
<foreign-project>Mage</foreign-project>
<artifact-type>jar</artifact-type>
<script>build.xml</script>
<target>jar</target>
<clean-target>clean</clean-target>
<id>jar</id>
</reference>
<reference>
<foreign-project>Mage_Player_AI</foreign-project>
<artifact-type>jar</artifact-type>
<script>build.xml</script>
<target>jar</target>
<clean-target>clean</clean-target>
<id>jar</id>
</reference>
</references>
</configuration>
</project>

View file

@ -0,0 +1,52 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.player.ai;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import mage.game.permanent.Permanent;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class Attackers extends TreeMap<Integer, List<Permanent>> {
public List<Permanent> getAttackers() {
List<Permanent> attackers = new ArrayList<Permanent>();
for (List<Permanent> l: this.values()) {
for (Permanent permanent: l) {
attackers.add(permanent);
}
}
return attackers;
}
}

View file

@ -0,0 +1,631 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.player.ai;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.Constants.Outcome;
import mage.Constants.PhaseStep;
import mage.Constants.RangeOfInfluence;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.SearchEffect;
import mage.cards.Cards;
import mage.cards.decks.Deck;
import mage.choices.Choice;
import mage.filter.FilterAbility;
import mage.game.Game;
import mage.game.combat.Combat;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.stack.StackAbility;
import mage.game.stack.StackObject;
import mage.game.turn.BeginCombatStep;
import mage.game.turn.BeginningPhase;
import mage.game.turn.CleanupStep;
import mage.game.turn.CombatDamageStep;
import mage.game.turn.CombatPhase;
import mage.game.turn.DeclareAttackersStep;
import mage.game.turn.DeclareBlockersStep;
import mage.game.turn.DrawStep;
import mage.game.turn.EndOfCombatStep;
import mage.game.turn.EndPhase;
import mage.game.turn.EndStep;
import mage.game.turn.Phase;
import mage.game.turn.PostCombatMainPhase;
import mage.game.turn.PostCombatMainStep;
import mage.game.turn.PreCombatMainPhase;
import mage.game.turn.PreCombatMainStep;
import mage.game.turn.UntapStep;
import mage.game.turn.UpkeepStep;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
import mage.util.Logging;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class ComputerPlayer2 extends ComputerPlayer<ComputerPlayer2> implements Player {
private static final transient Logger logger = Logging.getLogger(ComputerPlayer2.class.getName());
private static final ExecutorService pool = Executors.newFixedThreadPool(1);
protected int maxDepth;
protected int maxNodes;
protected LinkedList<Ability> actions = new LinkedList<Ability>();
protected List<UUID> targets = new ArrayList<UUID>();
protected List<String> choices = new ArrayList<String>();
protected Combat combat;
protected int currentScore;
protected SimulationNode root;
public ComputerPlayer2(String name, Deck deck, RangeOfInfluence range) {
super(name, deck, range);
maxDepth = Config.maxDepth;
maxNodes = Config.maxNodes;
}
public ComputerPlayer2(final ComputerPlayer2 player) {
super(player);
this.maxDepth = player.maxDepth;
this.currentScore = player.currentScore;
if (player.combat != null)
this.combat = player.combat.copy();
for (Ability ability: player.actions) {
actions.add(ability);
}
for (UUID targetId: player.targets) {
targets.add(targetId);
}
for (String choice: player.choices) {
choices.add(choice);
}
}
@Override
public ComputerPlayer2 copy() {
return new ComputerPlayer2(this);
}
@Override
public void priority(Game game) {
logState(game);
game.firePriorityEvent(playerId);
switch (game.getTurn().getStepType()) {
case UPKEEP:
case DRAW:
pass();
break;
case PRECOMBAT_MAIN:
case BEGIN_COMBAT:
case DECLARE_ATTACKERS:
case DECLARE_BLOCKERS:
case COMBAT_DAMAGE:
case END_COMBAT:
case POSTCOMBAT_MAIN:
if (actions.size() == 0) {
calculateActions(game);
}
act(game);
break;
case END_TURN:
case CLEANUP:
pass();
break;
}
}
protected void act(Game game) {
if (actions == null || actions.size() == 0)
pass();
else {
boolean usedStack = false;
while (actions.peek() != null) {
Ability ability = actions.poll();
this.activateAbility((ActivatedAbility) ability, game);
if (ability.isUsesStack())
usedStack = true;
}
if (usedStack)
pass();
}
}
protected void calculateActions(Game game) {
currentScore = GameStateEvaluator.evaluate(playerId, game);
if (!getNextAction(game)) {
Game sim = createSimulation(game);
SimulationNode.resetCount();
root = new SimulationNode(sim, maxDepth, playerId);
logger.fine("simulating actions");
addActionsTimed(new FilterAbility());
if (root.children.size() > 0) {
root = root.children.get(0);
actions = new LinkedList<Ability>(root.abilities);
combat = root.combat;
}
}
}
protected boolean getNextAction(Game game) {
if (root != null && root.children.size() > 0) {
SimulationNode test = root;
root = root.children.get(0);
while (root.children.size() > 0 && !root.playerId.equals(playerId)) {
test = root;
root = root.children.get(0);
}
logger.fine("simlating -- game value:" + game.getState().getValue() + " test value:" + test.gameValue);
if (root.playerId.equals(playerId) && root.abilities != null && game.getState().getValue() == test.gameValue) {
logger.fine("simulating -- continuing previous action chain");
actions = new LinkedList<Ability>(root.abilities);
combat = root.combat;
return true;
}
else {
return false;
}
}
return false;
}
protected int minimaxAB(SimulationNode node, FilterAbility filter, int depth, int alpha, int beta) {
UUID currentPlayerId = node.getGame().getPlayerList().get();
SimulationNode bestChild = null;
for (SimulationNode child: node.getChildren()) {
if (alpha >= beta) {
logger.fine("alpha beta pruning");
break;
}
if (SimulationNode.nodeCount > maxNodes) {
logger.fine("simulating -- reached end-state");
break;
}
int val = addActions(child, filter, depth-1, alpha, beta);
if (!currentPlayerId.equals(playerId)) {
if (val < beta) {
beta = val;
bestChild = child;
if (node.getCombat() == null)
node.setCombat(child.getCombat());
}
}
else {
if (val > alpha) {
alpha = val;
bestChild = child;
if (node.getCombat() == null)
node.setCombat(child.getCombat());
}
}
}
node.children.clear();
if (bestChild != null)
node.children.add(bestChild);
if (!currentPlayerId.equals(playerId)) {
logger.fine("returning minimax beta: " + beta);
return beta;
}
else {
logger.fine("returning minimax alpha: " + alpha);
return alpha;
}
}
protected SearchEffect getSearchEffect(StackAbility ability) {
for (Effect effect: ability.getEffects()) {
if (effect instanceof SearchEffect) {
return (SearchEffect) effect;
}
}
return null;
}
protected void resolve(SimulationNode node, int depth, Game game) {
StackObject ability = game.getStack().pop();
if (ability instanceof StackAbility) {
SearchEffect effect = getSearchEffect((StackAbility) ability);
if (effect != null && ability.getControllerId().equals(playerId)) {
Target target = effect.getTarget();
if (!target.doneChosing()) {
for (UUID targetId: target.possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) {
Game sim = game.copy();
StackAbility newAbility = (StackAbility) ability.copy();
SearchEffect newEffect = getSearchEffect((StackAbility) newAbility);
newEffect.getTarget().addTarget(targetId, newAbility, sim);
sim.getStack().push(newAbility);
SimulationNode newNode = new SimulationNode(sim, depth, ability.getControllerId());
node.children.add(newNode);
newNode.getTargets().add(targetId);
logger.fine("simulating search -- node#: " + SimulationNode.getCount() + "for player: " + sim.getPlayer(ability.getControllerId()).getName());
}
return;
}
}
}
logger.fine("simulating resolve ");
ability.resolve(game);
game.applyEffects();
game.getPlayers().resetPassed();
game.getPlayerList().setCurrent(game.getActivePlayerId());
}
protected void addActionsTimed(final FilterAbility filter) {
FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
public Integer call() throws Exception
{
return addActions(root, filter, maxDepth, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
});
pool.execute(task);
try {
task.get(Config.maxThinkSeconds, TimeUnit.SECONDS);
} catch (TimeoutException e) {
logger.fine("simulating - timed out");
task.cancel(true);
} catch (ExecutionException e) {
} catch (InterruptedException e) {
}
}
protected int addActions(SimulationNode node, FilterAbility filter, int depth, int alpha, int beta) {
Game game = node.getGame();
int val;
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return GameStateEvaluator.evaluate(playerId, game);
}
if (depth <= 0 || SimulationNode.nodeCount > maxNodes || game.isGameOver()) {
logger.fine("simulating -- reached end state");
val = GameStateEvaluator.evaluate(playerId, game);
}
else if (node.getChildren().size() > 0) {
logger.fine("simulating -- somthing added children:" + node.getChildren().size());
val = minimaxAB(node, filter, depth-1, alpha, beta);
}
else {
if (logger.isLoggable(Level.FINE))
logger.fine("simulating -- alpha: " + alpha + " beta: " + beta + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + (node.getPlayerId().equals(playerId)?"yes":"no"));
if (allPassed(game)) {
if (!game.getStack().isEmpty()) {
resolve(node, depth, game);
}
else {
// int testScore = GameStateEvaluator.evaluate(playerId, game);
// if (testScore < currentScore) {
// // if score at end of step is worse than original score don't check any further
// logger.fine("simulating -- abandoning current check, no immediate benefit");
// return testScore;
// }
game.getPlayers().resetPassed();
playNext(game, game.getActivePlayerId(), node);
}
}
if (game.isGameOver()) {
val = GameStateEvaluator.evaluate(playerId, game);
}
else if (node.getChildren().size() > 0) {
//declared attackers or blockers or triggered abilities
logger.fine("simulating -- attack/block/trigger added children:" + node.getChildren().size());
val = minimaxAB(node, filter, depth-1, alpha, beta);
}
else {
val = simulatePriority(node, game, filter, depth, alpha, beta);
}
}
if (logger.isLoggable(Level.FINE))
logger.fine("returning -- score: " + val + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + game.getPlayer(node.getPlayerId()).getName());
return val;
}
protected int simulatePriority(SimulationNode node, Game game, FilterAbility filter, int depth, int alpha, int beta) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return GameStateEvaluator.evaluate(playerId, game);
}
node.setGameValue(game.getState().getValue());
SimulatedPlayer currentPlayer = (SimulatedPlayer) game.getPlayer(game.getPlayerList().get());
SimulationNode bestNode = null;
List<Ability> allActions = currentPlayer.simulatePriority(game, filter);
if (logger.isLoggable(Level.FINE))
logger.fine("simulating -- adding " + allActions.size() + " children:" + allActions);
for (Ability action: allActions) {
Game sim = game.copy();
if (sim.getPlayer(playerId).activateAbility((ActivatedAbility) action.copy(), sim)) {
sim.applyEffects();
if (!sim.isGameOver() && action.isUsesStack()) {
// only pass if the last action uses the stack
sim.getPlayer(currentPlayer.getId()).pass();
sim.getPlayerList().getNext();
}
SimulationNode newNode = new SimulationNode(sim, action, depth, currentPlayer.getId());
if (logger.isLoggable(Level.FINE))
logger.fine("simulating -- node #:" + SimulationNode.getCount() + " actions:" + action);
sim.checkStateAndTriggered();
int val = addActions(newNode, filter, depth-1, alpha, beta);
if (!currentPlayer.getId().equals(playerId)) {
if (val < beta) {
beta = val;
bestNode = newNode;
node.setCombat(newNode.getCombat());
}
}
else {
if (val > alpha) {
alpha = val;
bestNode = newNode;
node.setCombat(newNode.getCombat());
if (node.getTargets().size() > 0)
targets = node.getTargets();
if (node.getChoices().size() > 0)
choices = node.getChoices();
}
}
if (alpha >= beta) {
logger.fine("simulating -- pruning");
break;
}
if (SimulationNode.nodeCount > maxNodes) {
logger.fine("simulating -- reached end-state");
break;
}
}
}
if (bestNode != null) {
node.children.clear();
node.children.add(bestNode);
}
if (!currentPlayer.getId().equals(playerId)) {
logger.fine("returning priority beta: " + beta);
return beta;
}
else {
logger.fine("returning priority alpha: " + alpha);
return alpha;
}
}
protected boolean allPassed(Game game) {
for (Player player: game.getPlayers().values()) {
if (!player.isPassed() && !player.hasLost() && !player.hasLeft())
return false;
}
return true;
}
@Override
public boolean choose(Outcome outcome, Choice choice, Game game) {
if (choices.size() == 0)
return super.choose(outcome, choice, game);
if (!choice.isChosen()) {
for (String achoice: choices) {
choice.setChoice(achoice);
if (choice.isChosen()) {
choices.clear();
return true;
}
}
return false;
}
return true;
}
@Override
public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) {
if (targets.size() == 0)
return super.chooseTarget(cards, target, source, game);
if (!target.doneChosing()) {
for (UUID targetId: targets) {
target.addTarget(targetId, source, game);
if (target.doneChosing()) {
targets.clear();
return true;
}
}
return false;
}
return true;
}
public void playNext(Game game, UUID activePlayerId, SimulationNode node) {
boolean skip = false;
while (true) {
Phase currentPhase = game.getPhase();
if (!skip)
currentPhase.getStep().endStep(game, activePlayerId);
game.applyEffects();
switch (currentPhase.getStep().getType()) {
case UNTAP:
game.getPhase().setStep(new UpkeepStep());
break;
case UPKEEP:
game.getPhase().setStep(new DrawStep());
break;
case DRAW:
game.getTurn().setPhase(new PreCombatMainPhase());
game.getPhase().setStep(new PreCombatMainStep());
break;
case PRECOMBAT_MAIN:
game.getTurn().setPhase(new CombatPhase());
game.getPhase().setStep(new BeginCombatStep());
break;
case BEGIN_COMBAT:
game.getPhase().setStep(new DeclareAttackersStep());
break;
case DECLARE_ATTACKERS:
game.getPhase().setStep(new DeclareBlockersStep());
break;
case DECLARE_BLOCKERS:
game.getPhase().setStep(new CombatDamageStep(true));
break;
case COMBAT_DAMAGE:
if (((CombatDamageStep)currentPhase.getStep()).getFirst())
game.getPhase().setStep(new CombatDamageStep(false));
else
game.getPhase().setStep(new EndOfCombatStep());
break;
case END_COMBAT:
game.getTurn().setPhase(new PostCombatMainPhase());
game.getPhase().setStep(new PostCombatMainStep());
break;
case POSTCOMBAT_MAIN:
game.getTurn().setPhase(new EndPhase());
game.getPhase().setStep(new EndStep());
break;
case END_TURN:
game.getPhase().setStep(new CleanupStep());
break;
case CLEANUP:
game.getPhase().getStep().beginStep(game, activePlayerId);
if (!game.checkStateAndTriggered() && !game.isGameOver()) {
game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext());
game.getTurn().setPhase(new BeginningPhase());
game.getPhase().setStep(new UntapStep());
}
}
if (!game.getStep().skipStep(game, game.getActivePlayerId())) {
if (game.getTurn().getStepType() == PhaseStep.DECLARE_ATTACKERS) {
game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_ATTACKERS_STEP_PRE, null, null, activePlayerId));
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, activePlayerId, activePlayerId))) {
for (Combat engagement: ((SimulatedPlayer)game.getPlayer(activePlayerId)).addAttackers(game)) {
Game sim = game.copy();
UUID defenderId = game.getOpponents(playerId).iterator().next();
for (CombatGroup group: engagement.getGroups()) {
for (UUID attackerId: group.getAttackers()) {
sim.getPlayer(activePlayerId).declareAttacker(attackerId, defenderId, sim);
}
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_ATTACKERS, playerId, playerId));
SimulationNode newNode = new SimulationNode(sim, node.getDepth()-1, activePlayerId);
logger.fine("simulating -- node #:" + SimulationNode.getCount() + " declare attakers");
newNode.setCombat(sim.getCombat());
node.children.add(newNode);
}
}
}
else if (game.getTurn().getStepType() == PhaseStep.DECLARE_BLOCKERS) {
game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_PRE, null, null, activePlayerId));
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, activePlayerId, activePlayerId))) {
for (UUID defenderId: game.getCombat().getDefenders()) {
//check if defender is being attacked
if (game.getCombat().isAttacked(defenderId, game)) {
for (Combat engagement: ((SimulatedPlayer)game.getPlayer(defenderId)).addBlockers(game)) {
Game sim = game.copy();
for (CombatGroup group: engagement.getGroups()) {
for (UUID blockerId: group.getBlockers()) {
group.addBlocker(blockerId, defenderId, sim);
}
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, playerId, playerId));
SimulationNode newNode = new SimulationNode(sim, node.getDepth()-1, defenderId);
logger.fine("simulating -- node #:" + SimulationNode.getCount() + " declare blockers");
newNode.setCombat(sim.getCombat());
node.children.add(newNode);
}
}
}
}
}
else {
game.getStep().beginStep(game, activePlayerId);
}
if (game.getStep().getHasPriority())
break;
}
else {
skip = true;
}
}
game.checkStateAndTriggered();
}
@Override
public void selectAttackers(Game game) {
logger.fine("selectAttackers");
if (combat != null) {
UUID opponentId = game.getCombat().getDefenders().iterator().next();
for (UUID attackerId: combat.getAttackers()) {
this.declareAttacker(attackerId, opponentId, game);
}
}
}
@Override
public void selectBlockers(Game game) {
logger.fine("selectBlockers");
if (combat != null && combat.getGroups().size() > 0) {
List<CombatGroup> groups = game.getCombat().getGroups();
for (int i = 0; i< groups.size(); i++) {
for (UUID blockerId: combat.getGroups().get(i).getBlockers()) {
this.declareBlocker(blockerId, groups.get(i).getAttackers().get(0), game);
}
}
}
}
/**
* Copies game and replaces all players in copy with simulated players
*
* @param game
* @return a new game object with simulated players
*/
protected Game createSimulation(Game game) {
Game sim = game.copy();
for (Player copyPlayer: sim.getState().getPlayers().values()) {
Player origPlayer = game.getState().getPlayers().get(copyPlayer.getId());
SimulatedPlayer newPlayer = new SimulatedPlayer(copyPlayer.getId(), copyPlayer.getId().equals(playerId));
newPlayer.restore(origPlayer);
sim.getState().getPlayers().put(copyPlayer.getId(), newPlayer);
}
return sim;
}
}

View file

@ -0,0 +1,540 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.player.ai;
import java.util.LinkedList;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.Constants.AbilityType;
import mage.Constants.PhaseStep;
import mage.Constants.RangeOfInfluence;
import mage.Constants.Zone;
import mage.abilities.Ability;
import mage.cards.decks.Deck;
import mage.filter.FilterAbility;
import mage.game.Game;
import mage.game.combat.Combat;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.turn.BeginCombatStep;
import mage.game.turn.BeginningPhase;
import mage.game.turn.CleanupStep;
import mage.game.turn.CombatDamageStep;
import mage.game.turn.CombatPhase;
import mage.game.turn.DeclareAttackersStep;
import mage.game.turn.DeclareBlockersStep;
import mage.game.turn.DrawStep;
import mage.game.turn.EndOfCombatStep;
import mage.game.turn.EndPhase;
import mage.game.turn.EndStep;
import mage.game.turn.PostCombatMainPhase;
import mage.game.turn.PostCombatMainStep;
import mage.game.turn.Step;
import mage.game.turn.UntapStep;
import mage.game.turn.UpkeepStep;
import mage.players.Player;
import mage.util.Logging;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
private static final transient Logger logger = Logging.getLogger(ComputerPlayer3.class.getName());
private static FilterAbility filterLand = new FilterAbility();
private static FilterAbility filterNotLand = new FilterAbility();
static {
filterLand.getTypes().add(AbilityType.PLAY_LAND);
filterLand.setZone(Zone.HAND);
filterNotLand.getTypes().add(AbilityType.PLAY_LAND);
filterNotLand.setZone(Zone.HAND);
filterNotLand.setNotFilter(true);
}
public ComputerPlayer3(String name, Deck deck, RangeOfInfluence range) {
super(name, deck, range);
maxDepth = Config.maxDepth;
maxNodes = Config.maxNodes;
}
public ComputerPlayer3(final ComputerPlayer3 player) {
super(player);
}
@Override
public ComputerPlayer3 copy() {
return new ComputerPlayer3(this);
}
@Override
public void priority(Game game) {
logState(game);
game.firePriorityEvent(playerId);
switch (game.getTurn().getStepType()) {
case UPKEEP:
case DRAW:
pass();
break;
case PRECOMBAT_MAIN:
if (game.getActivePlayerId().equals(playerId)) {
if (actions.size() == 0) {
calculatePreCombatActions(game);
}
act(game);
}
else
pass();
break;
case BEGIN_COMBAT:
pass();
break;
case DECLARE_ATTACKERS:
if (!game.getActivePlayerId().equals(playerId)) {
if (actions.size() == 0) {
calculatePreCombatActions(game);
}
act(game);
}
else
pass();
break;
case DECLARE_BLOCKERS:
case COMBAT_DAMAGE:
case END_COMBAT:
pass();
break;
case POSTCOMBAT_MAIN:
if (game.getActivePlayerId().equals(playerId)) {
if (actions.size() == 0) {
calculatePostCombatActions(game);
}
act(game);
}
else
pass();
break;
case END_TURN:
case CLEANUP:
pass();
break;
}
}
protected void calculatePreCombatActions(Game game) {
if (!getNextAction(game)) {
currentScore = GameStateEvaluator.evaluate(playerId, game);
Game sim = createSimulation(game);
SimulationNode.resetCount();
root = new SimulationNode(sim, maxDepth, playerId);
logger.fine("simulating pre combat actions -----------------------------------------------------------------------------------------");
addActionsTimed(new FilterAbility());
if (root.children.size() > 0) {
root = root.children.get(0);
actions = new LinkedList<Ability>(root.abilities);
combat = root.combat;
}
}
}
protected void calculatePostCombatActions(Game game) {
if (!getNextAction(game)) {
currentScore = GameStateEvaluator.evaluate(playerId, game);
Game sim = createSimulation(game);
SimulationNode.resetCount();
root = new SimulationNode(sim, maxDepth, playerId);
logger.fine("simulating post combat actions ----------------------------------------------------------------------------------------");
addActionsTimed(new FilterAbility());
if (root.children.size() > 0) {
root = root.children.get(0);
actions = new LinkedList<Ability>(root.abilities);
combat = root.combat;
}
}
}
@Override
protected int addActions(SimulationNode node, FilterAbility filter, int depth, int alpha, int beta) {
boolean stepFinished = false;
int val;
Game game = node.getGame();
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return GameStateEvaluator.evaluate(playerId, game);
}
if (depth <= 0 || SimulationNode.nodeCount > maxNodes || game.isGameOver()) {
logger.fine("simulating -- reached end state");
val = GameStateEvaluator.evaluate(playerId, game);
}
else if (node.getChildren().size() > 0) {
logger.fine("simulating -- somthing added children:" + node.getChildren().size());
val = minimaxAB(node, filter, depth-1, alpha, beta);
}
else {
if (logger.isLoggable(Level.FINE))
logger.fine("simulating -- alpha: " + alpha + " beta: " + beta + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + game.getPlayer(game.getPlayerList().get()).getName());
if (allPassed(game)) {
if (!game.getStack().isEmpty()) {
resolve(node, depth, game);
}
else {
stepFinished = true;
}
}
if (game.isGameOver()) {
val = GameStateEvaluator.evaluate(playerId, game);
}
else if (stepFinished) {
logger.fine("step finished");
int testScore = GameStateEvaluator.evaluate(playerId, game);
if (game.getActivePlayerId().equals(playerId)) {
if (testScore < currentScore) {
// if score at end of step is worse than original score don't check further
logger.fine("simulating -- abandoning check, no immediate benefit");
val = testScore;
}
else {
switch (game.getTurn().getStepType()) {
case PRECOMBAT_MAIN:
val = simulateCombat(game, node, depth-1, alpha, beta, false);
break;
case POSTCOMBAT_MAIN:
val = simulateCounterAttack(game, node, depth-1, alpha, beta);
break;
default:
val = GameStateEvaluator.evaluate(playerId, game);
break;
}
}
}
else {
if (game.getTurn().getStepType() == PhaseStep.DECLARE_ATTACKERS)
val = simulateBlockers(game, node, playerId, depth-1, alpha, beta, true);
else
val = GameStateEvaluator.evaluate(playerId, game);
}
}
else if (node.getChildren().size() > 0) {
logger.fine("simulating -- trigger added children:" + node.getChildren().size());
val = minimaxAB(node, filter, depth, alpha, beta);
}
else {
val = simulatePriority(node, game, filter, depth, alpha, beta);
}
}
if (logger.isLoggable(Level.FINE))
logger.fine("returning -- score: " + val + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + game.getPlayer(node.getPlayerId()).getName());
return val;
}
protected int simulateCombat(Game game, SimulationNode node, int depth, int alpha, int beta, boolean counter) {
Integer val = null;
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return GameStateEvaluator.evaluate(playerId, game);
}
if (game.getTurn().getStepType() != PhaseStep.DECLARE_BLOCKERS) {
game.getTurn().setPhase(new CombatPhase());
if (game.getPhase().beginPhase(game, game.getActivePlayerId())) {
simulateStep(game, new BeginCombatStep());
game.getPhase().setStep(new DeclareAttackersStep());
if (!game.getStep().skipStep(game, game.getActivePlayerId())) {
game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_ATTACKERS_STEP_PRE, null, null, game.getActivePlayerId()));
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, game.getActivePlayerId(), game.getActivePlayerId()))) {
val = simulateAttackers(game, node, game.getActivePlayerId(), depth, alpha, beta, counter);
}
}
else if (!counter) {
simulateToEnd(game);
val = simulatePostCombatMain(game, node, depth, alpha, beta);
}
}
}
else {
if (!game.getStep().skipStep(game, game.getActivePlayerId())) {
game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_PRE, null, null, game.getActivePlayerId()));
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, game.getActivePlayerId(), game.getActivePlayerId()))) {
//only suitable for two player games - only simulates blocks for 1st defender
val = simulateBlockers(game, node, game.getCombat().getDefenders().iterator().next(), depth, alpha, beta, counter);
}
}
else if (!counter) {
finishCombat(game);
val = GameStateEvaluator.evaluate(playerId, game);
// val = simulateCounterAttack(game, node, depth, alpha, beta);
}
}
if (val == null)
val = GameStateEvaluator.evaluate(playerId, game);
if (logger.isLoggable(Level.FINE))
logger.fine("returning -- combat score: " + val + " depth:" + depth + " for player:" + game.getPlayer(node.getPlayerId()).getName());
return val;
}
protected int simulateAttackers(Game game, SimulationNode node, UUID attackerId, int depth, int alpha, int beta, boolean counter) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return GameStateEvaluator.evaluate(playerId, game);
}
Integer val = null;
SimulationNode bestNode = null;
SimulatedPlayer attacker = (SimulatedPlayer) game.getPlayer(attackerId);
for (Combat engagement: attacker.addAttackers(game)) {
if (alpha >= beta) {
logger.fine("simulating -- pruning attackers");
break;
}
Game sim = game.copy();
UUID defenderId = game.getOpponents(playerId).iterator().next();
for (CombatGroup group: engagement.getGroups()) {
for (UUID attackId: group.getAttackers()) {
sim.getPlayer(attackerId).declareAttacker(attackId, defenderId, sim);
}
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_ATTACKERS, playerId, playerId));
SimulationNode newNode = new SimulationNode(sim, depth, game.getActivePlayerId());
if (logger.isLoggable(Level.FINE))
logger.fine("simulating attack -- node#: " + SimulationNode.getCount());
sim.checkStateAndTriggered();
while (!sim.getStack().isEmpty()) {
sim.getStack().resolve(sim);
logger.fine("resolving triggered abilities");
sim.applyEffects();
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_ATTACKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId()));
Combat simCombat = sim.getCombat().copy();
sim.getPhase().setStep(new DeclareBlockersStep());
val = simulateCombat(sim, newNode, depth-1, alpha, beta, counter);
if (!attackerId.equals(playerId)) {
if (val < beta) {
beta = val;
bestNode = newNode;
node.setCombat(simCombat);
}
}
else {
if (val > alpha) {
alpha = val;
bestNode = newNode;
node.setCombat(simCombat);
}
}
}
if (val == null)
val = GameStateEvaluator.evaluate(playerId, game);
if (bestNode != null) {
node.children.clear();
node.children.add(bestNode);
}
if (logger.isLoggable(Level.FINE))
logger.fine("returning -- combat attacker score: " + val + " depth:" + depth + " for player:" + game.getPlayer(node.getPlayerId()).getName());
return val;
}
protected int simulateBlockers(Game game, SimulationNode node, UUID defenderId, int depth, int alpha, int beta, boolean counter) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return GameStateEvaluator.evaluate(playerId, game);
}
Integer val = null;
SimulationNode bestNode = null;
//check if defender is being attacked
if (game.getCombat().isAttacked(defenderId, game)) {
SimulatedPlayer defender = (SimulatedPlayer) game.getPlayer(defenderId);
for (Combat engagement: defender.addBlockers(game)) {
if (alpha >= beta) {
logger.fine("simulating -- pruning blockers");
break;
}
Game sim = game.copy();
for (CombatGroup group: engagement.getGroups()) {
UUID attackerId = group.getAttackers().get(0);
for (UUID blockerId: group.getBlockers()) {
sim.getPlayer(defenderId).declareBlocker(blockerId, attackerId, sim);
}
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, playerId, playerId));
SimulationNode newNode = new SimulationNode(sim, depth, defenderId);
if (logger.isLoggable(Level.FINE))
logger.fine("simulating block -- node#: " + SimulationNode.getCount());
sim.checkStateAndTriggered();
while (!sim.getStack().isEmpty()) {
sim.getStack().resolve(sim);
logger.fine("resolving triggered abilities");
sim.applyEffects();
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId()));
Combat simCombat = sim.getCombat().copy();
finishCombat(sim);
if (!counter) {
int testScore = GameStateEvaluator.evaluate(playerId, sim);
if (testScore < currentScore) {
// if score at end of combat is worse than original score don't check counterattack
logger.fine("simulating -- abandoning counterattack check, no immediate benefit");
val = testScore;
}
else
val = simulatePostCombatMain(sim, newNode, depth-1, alpha, beta);
}
else
val = GameStateEvaluator.evaluate(playerId, sim);
if (!defenderId.equals(playerId)) {
if (val < beta) {
beta = val;
bestNode = newNode;
node.setCombat(simCombat);
}
}
else {
if (val > alpha) {
alpha = val;
bestNode = newNode;
node.setCombat(simCombat);
}
}
}
}
if (val == null)
val = GameStateEvaluator.evaluate(playerId, game);
if (bestNode != null) {
node.children.clear();
node.children.add(bestNode);
}
if (logger.isLoggable(Level.FINE))
logger.fine("returning -- combat blocker score: " + val + " depth:" + depth + " for player:" + game.getPlayer(node.getPlayerId()).getName());
return val;
}
protected int simulateCounterAttack(Game game, SimulationNode node, int depth, int alpha, int beta) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return GameStateEvaluator.evaluate(playerId, game);
}
Integer val = null;
if (!game.isGameOver()) {
logger.fine("simulating -- counter attack");
simulateToEnd(game);
game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext());
game.getTurn().setPhase(new BeginningPhase());
if (game.getPhase().beginPhase(game, game.getActivePlayerId())) {
simulateStep(game, new UntapStep());
simulateStep(game, new UpkeepStep());
simulateStep(game, new DrawStep());
game.getPhase().endPhase(game, game.getActivePlayerId());
}
val = simulateCombat(game, node, depth-1, alpha, beta, true);
if (logger.isLoggable(Level.FINE))
logger.fine("returning -- counter attack score: " + val + " depth:" + depth + " for player:" + game.getPlayer(node.getPlayerId()).getName());
}
if (val == null)
val = GameStateEvaluator.evaluate(playerId, game);
return val;
}
protected void simulateStep(Game game, Step step) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return;
}
if (!game.isGameOver()) {
game.getPhase().setStep(step);
if (!step.skipStep(game, game.getActivePlayerId())) {
step.beginStep(game, game.getActivePlayerId());
game.checkStateAndTriggered();
while (!game.getStack().isEmpty()) {
game.getStack().resolve(game);
game.applyEffects();
}
step.endStep(game, game.getActivePlayerId());
}
}
}
protected void finishCombat(Game game) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return;
}
simulateStep(game, new CombatDamageStep(true));
simulateStep(game, new CombatDamageStep(false));
simulateStep(game, new EndOfCombatStep());
}
protected int simulatePostCombatMain(Game game, SimulationNode node, int depth, int alpha, int beta) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return GameStateEvaluator.evaluate(playerId, game);
}
logger.fine("simulating -- post combat main");
game.getTurn().setPhase(new PostCombatMainPhase());
if (game.getPhase().beginPhase(game, game.getActivePlayerId())) {
game.getPhase().setStep(new PostCombatMainStep());
game.getStep().beginStep(game, playerId);
game.getPlayers().resetPassed();
return addActions(node, new FilterAbility(), depth, alpha, beta);
}
return simulateCounterAttack(game, node, depth, alpha, beta);
}
protected void simulateToEnd(Game game) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.fine("interrupted");
return;
}
if (!game.isGameOver()) {
game.getTurn().getPhase().endPhase(game, game.getActivePlayerId());
game.getTurn().setPhase(new EndPhase());
if (game.getTurn().getPhase().beginPhase(game, game.getActivePlayerId())) {
simulateStep(game, new EndStep());
simulateStep(game, new CleanupStep());
}
}
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.player.ai;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.util.Logging;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class Config {
private final static Logger logger = Logging.getLogger(Config.class.getName());
public static final int maxDepth;
public static final int maxNodes;
public static final int evaluatorLifeFactor;
public static final int evaluatorPermanentFactor;
public static final int evaluatorCreatureFactor;
public static final int evaluatorHandFactor;
public static final int maxThinkSeconds;
static {
Properties p = new Properties();
try {
File file = new File(Config.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
p.load(new FileInputStream(new File(file.getParent() + File.separator + "AIMinimax.properties")));
} catch (IOException ex) {
logger.log(Level.SEVERE, null, ex);
} catch (URISyntaxException ex) {
Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, ex);
}
maxDepth = Integer.parseInt(p.getProperty("maxDepth"));
maxNodes = Integer.parseInt(p.getProperty("maxNodes"));
evaluatorLifeFactor = Integer.parseInt(p.getProperty("evaluatorLifeFactor"));
evaluatorPermanentFactor = Integer.parseInt(p.getProperty("evaluatorPermanentFactor"));
evaluatorCreatureFactor = Integer.parseInt(p.getProperty("evaluatorCreatureFactor"));
evaluatorHandFactor = Integer.parseInt(p.getProperty("evaluatorHandFactor"));
maxThinkSeconds = Integer.parseInt(p.getProperty("maxThinkSeconds"));
}
}

View file

@ -0,0 +1,102 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package mage.player.ai;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.Constants.CardType;
import mage.Constants.Zone;
import mage.abilities.ActivatedAbility;
import mage.abilities.keyword.DoubleStrikeAbility;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.mana.ManaAbility;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.Logging;
/**
*
* @author BetaSteward_at_googlemail.com
*
* this evaluator is only good for two player games
*
*/
public class GameStateEvaluator {
private final static transient Logger logger = Logging.getLogger(GameStateEvaluator.class.getName());
private static final int LIFE_FACTOR = Config.evaluatorLifeFactor;
private static final int PERMANENT_FACTOR = Config.evaluatorPermanentFactor;
private static final int CREATURE_FACTOR = Config.evaluatorCreatureFactor;
private static final int HAND_FACTOR = Config.evaluatorHandFactor;
public static int evaluate(UUID playerId, Game game) {
Player player = game.getPlayer(playerId);
Player opponent = game.getPlayer(game.getOpponents(playerId).iterator().next());
if (game.isGameOver()) {
if (player.hasLost() || opponent.hasWon())
return Integer.MIN_VALUE;
if (opponent.hasLost() || player.hasWon())
return Integer.MAX_VALUE;
}
int lifeScore = (player.getLife() - opponent.getLife()) * LIFE_FACTOR;
int permanentScore = 0;
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(playerId)) {
permanentScore += evaluatePermanent(permanent, game);
}
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(opponent.getId())) {
permanentScore -= evaluatePermanent(permanent, game);
}
permanentScore *= PERMANENT_FACTOR;
int handScore = 0;
handScore = 7 - opponent.getHand().size();
handScore = Math.min(7, player.getHand().size());
handScore *= HAND_FACTOR;
int score = lifeScore + permanentScore + handScore;
if (logger.isLoggable(Level.FINE))
logger.fine("game state evaluated to- lifeScore:" + lifeScore + " permanentScore:" + permanentScore + " handScore:" + handScore + " total:" + score);
return score;
}
public static int evaluatePermanent(Permanent permanent, Game game) {
int value = permanent.isTapped()?1:2;
if (permanent.getCardType().contains(CardType.CREATURE)) {
value += evaluateCreature(permanent, game) * CREATURE_FACTOR;
}
value += permanent.getAbilities().getManaAbilities(Zone.BATTLEFIELD).size();
for (ActivatedAbility ability: permanent.getAbilities().getActivatedAbilities(Zone.BATTLEFIELD)) {
if (!(ability instanceof ManaAbility) && ability.canActivate(ability.getControllerId(), game))
value += ability.getEffects().getOutcomeTotal();
}
value += permanent.getAbilities().getStaticAbilities(Zone.BATTLEFIELD).getOutcomeTotal();
value += permanent.getAbilities().getTriggeredAbilities(Zone.BATTLEFIELD).getOutcomeTotal();
value += permanent.getManaCost().convertedManaCost();
//TODO: add a difficulty to calculation to ManaCost - sort permanents by difficulty for casting when evaluating game states
return value;
}
public static int evaluateCreature(Permanent creature, Game game) {
int value = 0;
value += creature.getPower().getValue();
value += creature.getToughness().getValue();
// if (creature.canAttack(game))
// value += creature.getPower().getValue();
// if (!creature.isTapped())
// value += 2;
value += creature.getAbilities().getEvasionAbilities().getOutcomeTotal();
value += creature.getAbilities().getProtectionAbilities().getOutcomeTotal();
value += creature.getAbilities().containsKey(FirstStrikeAbility.getInstance().getId())?1:0;
value += creature.getAbilities().containsKey(DoubleStrikeAbility.getInstance().getId())?2:0;
value += creature.getAbilities().containsKey(TrampleAbility.getInstance().getId())?1:0;
return value;
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.player.ai;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.game.Game;
import mage.util.Logging;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class SimulateBlockWorker implements Callable {
private final static Logger logger = Logging.getLogger(SimulationWorker.class.getName());
private SimulationNode node;
private ComputerPlayer3 player;
public SimulateBlockWorker(ComputerPlayer3 player, SimulationNode node) {
this.player = player;
this.node = node;
}
@Override
public Object call() {
try {
// player.simulateBlock(node);
} catch (Exception ex) {
logger.log(Level.SEVERE, null, ex);
}
return null;
}
}

View file

@ -0,0 +1,68 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.player.ai;
import java.util.List;
import mage.abilities.Ability;
import mage.game.Game;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class SimulatedAction {
private Game game;
private List<Ability> abilities;
public SimulatedAction(Game game, List<Ability> abilities) {
this.game = game;
this.abilities = abilities;
}
public Game getGame() {
return this.game;
}
public List<Ability> getAbilities() {
return this.abilities;
}
@Override
public String toString() {
return this.abilities.toString();
}
public boolean usesStack() {
if (abilities != null && abilities.size() > 0) {
return abilities.get(abilities.size() -1).isUsesStack();
}
return true;
}
}

View file

@ -0,0 +1,250 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.player.ai;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.PassAbility;
import mage.abilities.mana.ManaOptions;
import mage.choices.Choice;
import mage.filter.FilterAbility;
import mage.game.Game;
import mage.game.combat.Combat;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.target.Target;
import mage.util.Copier;
import mage.util.Logging;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class SimulatedPlayer extends ComputerPlayer<SimulatedPlayer> {
private final static transient Logger logger = Logging.getLogger(SimulatedPlayer.class.getName());
private boolean isSimulatedPlayer;
private FilterAbility filter;
private transient ConcurrentLinkedQueue<Ability> allActions;
private static PassAbility pass = new PassAbility();
public SimulatedPlayer(UUID id, boolean isSimulatedPlayer) {
super(id);
pass.setControllerId(playerId);
this.isSimulatedPlayer = isSimulatedPlayer;
}
public SimulatedPlayer(final SimulatedPlayer player) {
super(player);
this.isSimulatedPlayer = player.isSimulatedPlayer;
if (player.filter != null)
this.filter = player.filter.copy();
}
@Override
public SimulatedPlayer copy() {
return new SimulatedPlayer(this);
}
public List<Ability> simulatePriority(Game game, FilterAbility filter) {
allActions = new ConcurrentLinkedQueue<Ability>();
Game sim = game.copy();
this.filter = filter;
simulateOptions(sim, pass);
ArrayList<Ability> list = new ArrayList<Ability>(allActions);
Collections.reverse(list);
return list;
}
protected void simulateOptions(Game game, Ability previousActions) {
allActions.add(previousActions);
ManaOptions available = getManaAvailable(game);
available.addMana(manaPool.getMana());
List<Ability> playables = game.getPlayer(playerId).getPlayable(game, filter, available, isSimulatedPlayer);
for (Ability ability: playables) {
List<Ability> options = game.getPlayer(playerId).getPlayableOptions(ability, game);
if (options.size() == 0) {
allActions.add(ability);
// simulateAction(game, previousActions, ability);
}
else {
// ExecutorService simulationExecutor = Executors.newFixedThreadPool(4);
for (Ability option: options) {
allActions.add(option);
// SimulationWorker worker = new SimulationWorker(game, this, previousActions, option);
// simulationExecutor.submit(worker);
}
// simulationExecutor.shutdown();
// while(!simulationExecutor.isTerminated()) {}
}
}
}
// protected void simulateAction(Game game, SimulatedAction previousActions, Ability action) {
// List<Ability> actions = new ArrayList<Ability>(previousActions.getAbilities());
// actions.add(action);
// Game sim = game.copy();
// if (sim.getPlayer(playerId).activateAbility((ActivatedAbility) action.copy(), sim)) {
// sim.applyEffects();
// sim.getPlayers().resetPassed();
// allActions.add(new SimulatedAction(sim, actions));
// }
// }
public List<Combat> addAttackers(Game game) {
Map<Integer, Combat> engagements = new HashMap<Integer, Combat>();
//useful only for two player games - will only attack first opponent
UUID defenderId = game.getOpponents(playerId).iterator().next();
List<Permanent> attackersList = super.getAvailableAttackers(game);
//use binary digits to calculate powerset of attackers
int powerElements = (int) Math.pow(2, attackersList.size());
StringBuilder binary = new StringBuilder();
for (int i = powerElements - 1; i >= 0; i--) {
Game sim = game.copy();
binary.setLength(0);
binary.append(Integer.toBinaryString(i));
while (binary.length() < attackersList.size()) {
binary.insert(0, "0");
}
for (int j = 0; j < attackersList.size(); j++) {
if (binary.charAt(j) == '1')
sim.getCombat().declareAttacker(attackersList.get(j).getId(), defenderId, sim);
}
if (engagements.put(sim.getCombat().getValue(sim), sim.getCombat()) != null) {
logger.fine("simulating -- found redundant attack combination");
}
else if (logger.isLoggable(Level.FINE)) {
logger.fine("simulating -- attack:" + sim.getCombat().getGroups().size());
}
}
return new ArrayList<Combat>(engagements.values());
}
public List<Combat> addBlockers(Game game) {
Map<Integer, Combat> engagements = new HashMap<Integer, Combat>();
int numGroups = game.getCombat().getGroups().size();
if (numGroups == 0) return new ArrayList<Combat>();
//add a node with no blockers
Game sim = game.copy();
engagements.put(sim.getCombat().getValue(sim), sim.getCombat());
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, playerId, playerId));
List<Permanent> blockers = getAvailableBlockers(game);
addBlocker(game, blockers, engagements);
return new ArrayList<Combat>(engagements.values());
}
protected void addBlocker(Game game, List<Permanent> blockers, Map<Integer, Combat> engagements) {
if (blockers.size() == 0)
return;
int numGroups = game.getCombat().getGroups().size();
//try to block each attacker with each potential blocker
Permanent blocker = blockers.get(0);
if (logger.isLoggable(Level.FINE))
logger.fine("simulating -- block:" + blocker);
List<Permanent> remaining = remove(blockers, blocker);
for (int i = 0; i < numGroups; i++) {
if (game.getCombat().getGroups().get(i).canBlock(blocker, game)) {
Game sim = game.copy();
sim.getCombat().getGroups().get(i).addBlocker(blocker.getId(), playerId, sim);
if (engagements.put(sim.getCombat().getValue(sim), sim.getCombat()) != null)
logger.fine("simulating -- found redundant block combination");
addBlocker(sim, remaining, engagements); // and recurse minus the used blocker
}
}
addBlocker(game, remaining, engagements);
}
@Override
public boolean triggerAbility(TriggeredAbility source, Game game) {
Ability ability = source.copy();
List<Ability> options = getPlayableOptions(ability, game);
if (options.size() == 0) {
if (logger.isLoggable(Level.FINE))
logger.fine("simulating -- triggered ability:" + ability);
game.getStack().push(new StackAbility(ability, playerId));
ability.activate(game, false);
game.applyEffects();
game.getPlayers().resetPassed();
}
else {
SimulationNode parent = (SimulationNode) game.getCustomData();
int depth = parent.getDepth() - 1;
if (depth == 0) return true;
logger.fine("simulating -- triggered ability - adding children:" + options.size());
for (Ability option: options) {
addAbilityNode(parent, option, depth, game);
}
}
return true;
}
protected void addAbilityNode(SimulationNode parent, Ability ability, int depth, Game game) {
Game sim = game.copy();
sim.getStack().push(new StackAbility(ability, playerId));
ability.activate(sim, false);
sim.applyEffects();
SimulationNode newNode = new SimulationNode(sim, depth, playerId);
logger.fine("simulating -- node #:" + SimulationNode.getCount() + " triggered ability option");
for (Target target: ability.getTargets()) {
for (UUID targetId: target.getTargets()) {
newNode.getTargets().add(targetId);
}
}
for (Choice choice: ability.getChoices()) {
newNode.getChoices().add(choice.getChoice());
}
parent.children.add(newNode);
}
@Override
public void priority(Game game) {
//should never get here
}
}

View file

@ -0,0 +1,127 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.player.ai;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.game.Game;
import mage.game.combat.Combat;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class SimulationNode implements Serializable {
protected static int nodeCount;
protected Game game;
protected int gameValue;
protected List<Ability> abilities;
protected int depth;
protected List<SimulationNode> children = new ArrayList<SimulationNode>();
protected List<UUID> targets = new ArrayList<UUID>();
protected List<String> choices = new ArrayList<String>();
protected UUID playerId;
protected Combat combat;
public SimulationNode(Game game, int depth, UUID playerId) {
this.game = game;
this.depth = depth;
this.playerId = playerId;
game.setCustomData(this);
nodeCount++;
}
public SimulationNode(Game game, List<Ability> abilities, int depth, UUID playerId) {
this(game, depth, playerId);
this.abilities = abilities;
}
public SimulationNode(Game game, Ability ability, int depth, UUID playerId) {
this(game, depth, playerId);
this.abilities = new ArrayList<Ability>();
abilities.add(ability);
}
public static void resetCount() {
nodeCount = 0;
}
public static int getCount() {
return nodeCount;
}
public Game getGame() {
return this.game;
}
public int getGameValue() {
return this.gameValue;
}
public void setGameValue(int value) {
this.gameValue = value;
}
public List<Ability> getAbilities() {
return this.abilities;
}
public List<SimulationNode> getChildren() {
return this.children;
}
public int getDepth() {
return this.depth;
}
public UUID getPlayerId() {
return this.playerId;
}
public Combat getCombat() {
return this.combat;
}
public void setCombat(Combat combat) {
this.combat = combat;
}
public List<UUID> getTargets() {
return this.targets;
}
public List<String> getChoices() {
return this.choices;
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.player.ai;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.abilities.Ability;
import mage.game.Game;
import mage.util.Logging;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class SimulationWorker implements Callable {
private final static Logger logger = Logging.getLogger(SimulationWorker.class.getName());
private Game game;
private SimulatedAction previousActions;
private Ability action;
private SimulatedPlayer player;
public SimulationWorker(Game game, SimulatedPlayer player, SimulatedAction previousActions, Ability action) {
this.game = game;
this.player = player;
this.previousActions = previousActions;
this.action = action;
}
@Override
public Object call() {
try {
// player.simulateAction(game, previousActions, action);
} catch (Exception ex) {
logger.log(Level.SEVERE, null, ex);
}
return null;
}
}

View file

@ -43,6 +43,7 @@ import mage.Constants.RangeOfInfluence;
import mage.Constants.TargetController; import mage.Constants.TargetController;
import mage.Constants.Zone; import mage.Constants.Zone;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility; import mage.abilities.ActivatedAbility;
import mage.abilities.SpecialAction; import mage.abilities.SpecialAction;
import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCost;
@ -63,11 +64,11 @@ import mage.target.common.TargetDefender;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class HumanPlayer extends PlayerImpl { public class HumanPlayer extends PlayerImpl<HumanPlayer> {
final transient PlayerResponse response = new PlayerResponse(); final transient PlayerResponse response = new PlayerResponse();
private boolean abort = false; private boolean abort;
protected transient TargetPermanent targetCombat = new TargetPermanent(new FilterCreatureForCombat(), TargetController.YOU); protected transient TargetPermanent targetCombat = new TargetPermanent(new FilterCreatureForCombat(), TargetController.YOU);
@ -76,6 +77,11 @@ public class HumanPlayer extends PlayerImpl {
human = true; human = true;
} }
public HumanPlayer(final HumanPlayer player) {
super(player);
this.abort = player.abort;
}
protected void waitForResponse() { protected void waitForResponse() {
response.clear(); response.clear();
synchronized(response) { synchronized(response) {
@ -135,23 +141,27 @@ public class HumanPlayer extends PlayerImpl {
@Override @Override
public boolean choose(Outcome outcome, Choice choice, Game game) { public boolean choose(Outcome outcome, Choice choice, Game game) {
game.fireChooseEvent(playerId, choice);
while (!abort) { while (!abort) {
waitForStringResponse(); game.fireChooseEvent(playerId, choice);
choice.setChoice(response.getString()); waitForResponse();
return true; if (response.getString() != null) {
choice.setChoice(response.getString());
return true;
} else if (!choice.isRequired()) {
return false;
}
} }
return false; return false;
} }
@Override @Override
public boolean chooseTarget(Outcome outcome, Target target, Game game) { public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
game.fireSelectTargetEvent(playerId, target.getMessage(), target.isRequired());
while (!abort) { while (!abort) {
game.fireSelectTargetEvent(playerId, target.getMessage(), target.isRequired());
waitForResponse(); waitForResponse();
if (response.getUUID() != null) { if (response.getUUID() != null) {
if (target.canTarget(response.getUUID(), game)) { if (target.canTarget(response.getUUID(), source, game)) {
target.addTarget(response.getUUID(), game); target.addTarget(response.getUUID(), source, game);
return true; return true;
} }
} else if (!target.isRequired()) { } else if (!target.isRequired()) {
@ -162,13 +172,13 @@ public class HumanPlayer extends PlayerImpl {
} }
@Override @Override
public boolean chooseTarget(Cards cards, TargetCard target, Game game) { public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) {
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired());
while (!abort) { while (!abort) {
waitForResponse(); waitForResponse();
if (response.getUUID() != null) { if (response.getUUID() != null) {
if (target.canTarget(response.getUUID(), cards, game)) { if (target.canTarget(response.getUUID(), cards, game)) {
target.addTarget(response.getUUID(), game); target.addTarget(response.getUUID(), source, game);
return true; return true;
} }
} else if (!target.isRequired()) { } else if (!target.isRequired()) {
@ -180,15 +190,15 @@ public class HumanPlayer extends PlayerImpl {
@Override @Override
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Game game) { public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), target.isRequired()); game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), target.isRequired());
while (!abort) { while (!abort) {
waitForResponse(); waitForResponse();
if (response.getUUID() != null) { if (response.getUUID() != null) {
if (target.canTarget(response.getUUID(), game)) { if (target.canTarget(response.getUUID(), source, game)) {
UUID targetId = response.getUUID(); UUID targetId = response.getUUID();
int amountSelected = getAmount(1, target.getAmountRemaining(), "Select amount", game); int amountSelected = getAmount(1, target.getAmountRemaining(), "Select amount", game);
target.addTarget(targetId, amountSelected, game); target.addTarget(targetId, amountSelected, source, game);
return true; return true;
} }
} else if (!target.isRequired()) { } else if (!target.isRequired()) {
@ -313,7 +323,7 @@ public class HumanPlayer extends PlayerImpl {
if (response.getBoolean() != null) { if (response.getBoolean() != null) {
return; return;
} else if (response.getUUID() != null) { } else if (response.getUUID() != null) {
if (targetCombat.canTarget(playerId, response.getUUID(), game)) { if (targetCombat.canTarget(playerId, response.getUUID(), null, game)) {
selectDefender(game.getCombat().getDefenders(), response.getUUID(), game); selectDefender(game.getCombat().getDefenders(), response.getUUID(), game);
} }
} }
@ -321,11 +331,17 @@ public class HumanPlayer extends PlayerImpl {
} }
protected boolean selectDefender(Set<UUID> defenders, UUID attackerId, Game game) { protected boolean selectDefender(Set<UUID> defenders, UUID attackerId, Game game) {
TargetDefender target = new TargetDefender(defenders, attackerId); if (defenders.size() == 1) {
if (chooseTarget(Outcome.Damage, target, game)) { declareAttacker(attackerId, defenders.iterator().next(), game);
declareAttacker(attackerId, response.getUUID(), game);
return true; return true;
} }
else {
TargetDefender target = new TargetDefender(defenders, attackerId);
if (chooseTarget(Outcome.Damage, target, null, game)) {
declareAttacker(attackerId, response.getUUID(), game);
return true;
}
}
return false; return false;
} }
@ -338,7 +354,7 @@ public class HumanPlayer extends PlayerImpl {
if (response.getBoolean() != null) { if (response.getBoolean() != null) {
return; return;
} else if (response.getUUID() != null) { } else if (response.getUUID() != null) {
if (targetCombat.canTarget(playerId, response.getUUID(), game)) { if (targetCombat.canTarget(playerId, response.getUUID(), null, game)) {
selectCombatGroup(response.getUUID(), game); selectCombatGroup(response.getUUID(), game);
} }
} }
@ -361,7 +377,7 @@ public class HumanPlayer extends PlayerImpl {
int remainingDamage = damage; int remainingDamage = damage;
while (remainingDamage > 0) { while (remainingDamage > 0) {
Target target = new TargetCreatureOrPlayer(); Target target = new TargetCreatureOrPlayer();
chooseTarget(Outcome.Damage, target, game); chooseTarget(Outcome.Damage, target, null, game);
if (targets.size() == 0 || targets.contains(target.getFirstTarget())) { if (targets.size() == 0 || targets.contains(target.getFirstTarget())) {
int damageAmount = getAmount(0, remainingDamage, "Select amount", game); int damageAmount = getAmount(0, remainingDamage, "Select amount", game);
Permanent permanent = game.getPermanent(target.getFirstTarget()); Permanent permanent = game.getPermanent(target.getFirstTarget());
@ -449,4 +465,9 @@ public class HumanPlayer extends PlayerImpl {
} }
} }
@Override
public HumanPlayer copy() {
return new HumanPlayer(this);
}
} }

View file

@ -5,6 +5,8 @@
<playerTypes> <playerTypes>
<playerType name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/> <playerType name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/>
<playerType name="Computer - default" jar="Mage.Player.AI.jar" className="mage.player.ai.ComputerPlayer"/> <playerType name="Computer - default" jar="Mage.Player.AI.jar" className="mage.player.ai.ComputerPlayer"/>
<playerType name="Computer - minimax" jar="Mage.Player.AIMinimax.jar" className="mage.player.ai.ComputerPlayer2"/>
<playerType name="Computer - minimax hybrid" jar="Mage.Player.AIMinimax.jar" className="mage.player.ai.ComputerPlayer3"/>
</playerTypes> </playerTypes>
<gameTypes> <gameTypes>
<gameType name="Two Player Duel" jar="Mage.Game.TwoPlayerDuel.jar" className="mage.game.TwoPlayerDuel" typeName="mage.game.TwoPlayerDuelType"/> <gameType name="Two Player Duel" jar="Mage.Game.TwoPlayerDuel.jar" className="mage.game.TwoPlayerDuel" typeName="mage.game.TwoPlayerDuelType"/>

View file

@ -20,6 +20,7 @@ debug.test.classpath=\
dist.dir=dist dist.dir=dist
dist.jar=${dist.dir}/Mage.Server.jar dist.jar=${dist.dir}/Mage.Server.jar
dist.javadoc.dir=${dist.dir}/javadoc dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes= excludes=
includes=** includes=**
jar.compress=false jar.compress=false
@ -27,7 +28,9 @@ javac.classpath=\
${reference.Mage.jar}:\ ${reference.Mage.jar}:\
${reference.Mage_Common.jar}:\ ${reference.Mage_Common.jar}:\
${reference.Mage_Sets.jar}:\ ${reference.Mage_Sets.jar}:\
${reference.Mage_Player_AI.jar} ${reference.Mage_Player_AI.jar}:\
${reference.Mage_Player_Human.jar}:\
${reference.Mage_Player_AIMinimax.jar}
# Space-separated list of extra javac options # Space-separated list of extra javac options
javac.compilerargs= javac.compilerargs=
javac.deprecation=false javac.deprecation=false
@ -56,15 +59,19 @@ jaxbwiz.xjcrun.classpath=${libs.jaxb.classpath}
main.class=mage.server.Main main.class=mage.server.Main
manifest.file=manifest.mf manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF meta.inf.dir=${src.dir}/META-INF
platform.active=default_platform platform.active=JDK_1.6_21
project.license=bsd project.license=bsd
project.Mage=../Mage project.Mage=../Mage
project.Mage_Common=../Mage.Common project.Mage_Common=../Mage.Common
project.Mage_Player_AI=../Mage.Player.AI project.Mage_Player_AI=../Mage.Player.AI
project.Mage_Player_AIMinimax=../Mage.Player.AIMinimax
project.Mage_Player_Human=../Mage.Player.Human
project.Mage_Sets=../Mage.Sets project.Mage_Sets=../Mage.Sets
reference.Mage.jar=${project.Mage}/dist/Mage.jar reference.Mage.jar=${project.Mage}/dist/Mage.jar
reference.Mage_Common.jar=${project.Mage_Common}/dist/Mage.Common.jar reference.Mage_Common.jar=${project.Mage_Common}/dist/Mage.Common.jar
reference.Mage_Player_AI.jar=${project.Mage_Player_AI}/dist/Mage.Player.AI.jar reference.Mage_Player_AI.jar=${project.Mage_Player_AI}/dist/Mage.Player.AI.jar
reference.Mage_Player_AIMinimax.jar=${project.Mage_Player_AIMinimax}/dist/Mage.Player.AIMinimax.jar
reference.Mage_Player_Human.jar=${project.Mage_Player_Human}/dist/Mage.Player.Human.jar
reference.Mage_Sets.jar=${project.Mage_Sets}/dist/Mage.Sets.jar reference.Mage_Sets.jar=${project.Mage_Sets}/dist/Mage.Sets.jar
run-sys-prop.java.endorsed.dirs=${jaxbwiz.endorsed.dirs} run-sys-prop.java.endorsed.dirs=${jaxbwiz.endorsed.dirs}
run.classpath=\ run.classpath=\

View file

@ -9,6 +9,7 @@
</buildExtensions> </buildExtensions>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3"> <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>Mage.Server</name> <name>Mage.Server</name>
<explicit-platform explicit-source-supported="true"/>
<source-roots> <source-roots>
<root id="src.dir"/> <root id="src.dir"/>
</source-roots> </source-roots>
@ -41,6 +42,22 @@
<clean-target>clean</clean-target> <clean-target>clean</clean-target>
<id>jar</id> <id>jar</id>
</reference> </reference>
<reference>
<foreign-project>Mage_Player_AIMinimax</foreign-project>
<artifact-type>jar</artifact-type>
<script>build.xml</script>
<target>jar</target>
<clean-target>clean</clean-target>
<id>jar</id>
</reference>
<reference>
<foreign-project>Mage_Player_Human</foreign-project>
<artifact-type>jar</artifact-type>
<script>build.xml</script>
<target>jar</target>
<clean-target>clean</clean-target>
<id>jar</id>
</reference>
<reference> <reference>
<foreign-project>Mage_Sets</foreign-project> <foreign-project>Mage_Sets</foreign-project>
<artifact-type>jar</artifact-type> <artifact-type>jar</artifact-type>

View file

@ -0,0 +1,7 @@
maxDepth=10
maxNodes=5000
evaluatorLifeFactor=2
evaluatorPermanentFactor=1
evaluatorCreatureFactor=1
evaluatorHandFactor=1
maxThinkSeconds=30

Binary file not shown.

View file

@ -3,13 +3,16 @@
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd"> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd">
<server serverAddress="localhost" serverName="mage-server" port="17171" maxGameThreads="10" maxSecondsIdle="600"/> <server serverAddress="localhost" serverName="mage-server" port="17171" maxGameThreads="10" maxSecondsIdle="600"/>
<playerTypes> <playerTypes>
<plugin name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/> <playerType name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/>
<plugin name="Computer - default" jar="Mage.Player.AI.jar" className="mage.player.ai.ComputerPlayer"/> <playerType name="Computer - default" jar="Mage.Player.AI.jar" className="mage.player.ai.ComputerPlayer"/>
<playerType name="Computer - minimax" jar="Mage.Player.AIMinimax.jar" className="mage.player.ai.ComputerPlayer2"/>
<playerType name="Computer - minimax hybrid" jar="Mage.Player.AIMinimax.jar" className="mage.player.ai.ComputerPlayer3"/>
</playerTypes> </playerTypes>
<gameTypes> <gameTypes>
<plugin name="Two Player Duel" jar="Mage.Game.TwoPlayerDuel.jar" className="mage.game.TwoPlayerGame"/> <gameType name="Two Player Duel" jar="Mage.Game.TwoPlayerDuel.jar" className="mage.game.TwoPlayerDuel" typeName="mage.game.TwoPlayerDuelType"/>
<gameType name="Free For All" jar="Mage.Game.FreeForAll.jar" className="mage.game.FreeForAll" typeName="mage.game.FreeForAllType"/>
</gameTypes> </gameTypes>
<deckTypes> <deckTypes>
<plugin name="Constructed" jar="Mage.Deck.Constructed.jar" className="mage.deck.Constructed"/> <deckType name="Constructed" jar="Mage.Deck.Constructed.jar" className="mage.deck.Constructed"/>
</deckTypes> </deckTypes>
</config> </config>

View file

@ -30,6 +30,7 @@ package mage.server;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import mage.view.ChatMessage.MessageColor;
/** /**
* *
@ -65,8 +66,8 @@ public class ChatManager {
chatSessions.remove(chatId); chatSessions.remove(chatId);
} }
public void broadcast(UUID chatId, String userName, String message) { public void broadcast(UUID chatId, String userName, String message, MessageColor color) {
chatSessions.get(chatId).broadcast(userName, message); chatSessions.get(chatId).broadcast(userName, message, color);
} }
void removeSession(UUID sessionId) { void removeSession(UUID sessionId) {

View file

@ -39,6 +39,7 @@ import java.util.logging.Logger;
import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallback;
import mage.util.Logging; import mage.util.Logging;
import mage.view.ChatMessage; import mage.view.ChatMessage;
import mage.view.ChatMessage.MessageColor;
/** /**
* *
@ -59,7 +60,7 @@ public class ChatSession {
public void join(String userName, UUID sessionId) { public void join(String userName, UUID sessionId) {
clients.put(sessionId, userName); clients.put(sessionId, userName);
broadcast(userName, " has joined"); broadcast(userName, " has joined", MessageColor.BLACK);
logger.info(userName + " joined chat " + chatId); logger.info(userName + " joined chat " + chatId);
} }
@ -67,18 +68,18 @@ public class ChatSession {
if (clients.containsKey(sessionId)) { if (clients.containsKey(sessionId)) {
String userName = clients.get(sessionId); String userName = clients.get(sessionId);
clients.remove(sessionId); clients.remove(sessionId);
broadcast(userName, " has left"); broadcast(userName, " has left", MessageColor.BLACK);
logger.info(userName + " has left chat " + chatId); logger.info(userName + " has left chat " + chatId);
} }
} }
public void broadcast(String userName, String message) { public void broadcast(String userName, String message, MessageColor color) {
Calendar cal = new GregorianCalendar(); Calendar cal = new GregorianCalendar();
final String msg = timeFormatter.format(cal.getTime()) + " " + userName + ":" + message; final String msg = timeFormatter.format(cal.getTime()) + " " + userName + ":" + message;
for (UUID sessionId: clients.keySet()) { for (UUID sessionId: clients.keySet()) {
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("chatMessage", new ChatMessage(chatId, msg))); session.fireCallback(new ClientCallback("chatMessage", new ChatMessage(chatId, msg, color)));
else else
kill(sessionId); kill(sessionId);
} }

View file

@ -43,6 +43,7 @@ import mage.cards.decks.DeckCardLists;
import mage.game.GameException; import mage.game.GameException;
import mage.interfaces.MageException; import mage.interfaces.MageException;
import mage.interfaces.Server; import mage.interfaces.Server;
import mage.interfaces.ServerState;
import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallback;
import mage.server.game.DeckValidatorFactory; import mage.server.game.DeckValidatorFactory;
import mage.server.game.GameFactory; import mage.server.game.GameFactory;
@ -52,6 +53,7 @@ import mage.server.game.PlayerFactory;
import mage.server.game.ReplayManager; import mage.server.game.ReplayManager;
import mage.server.game.TableManager; import mage.server.game.TableManager;
import mage.util.Logging; import mage.util.Logging;
import mage.view.ChatMessage.MessageColor;
import mage.view.GameTypeView; import mage.view.GameTypeView;
import mage.view.TableView; import mage.view.TableView;
@ -126,9 +128,9 @@ public class ServerImpl extends RemoteServer implements Server {
} }
@Override @Override
public boolean joinTable(UUID sessionId, UUID roomId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws MageException, GameException { public boolean joinTable(UUID sessionId, UUID roomId, UUID tableId, String name, DeckCardLists deckList) throws MageException, GameException {
try { try {
boolean ret = GamesRoomManager.getInstance().getRoom(roomId).joinTable(sessionId, tableId, seatNum, name, deckList); boolean ret = GamesRoomManager.getInstance().getRoom(roomId).joinTable(sessionId, tableId, name, deckList);
logger.info("Session " + sessionId + " joined table " + tableId); logger.info("Session " + sessionId + " joined table " + tableId);
return ret; return ret;
} }
@ -186,7 +188,7 @@ public class ServerImpl extends RemoteServer implements Server {
@Override @Override
public void sendChatMessage(UUID chatId, String userName, String message) throws MageException { public void sendChatMessage(UUID chatId, String userName, String message) throws MageException {
try { try {
ChatManager.getInstance().broadcast(chatId, userName, message); ChatManager.getInstance().broadcast(chatId, userName, message, MessageColor.BLUE);
} }
catch (Exception ex) { catch (Exception ex) {
handleException(ex); handleException(ex);
@ -431,9 +433,13 @@ public class ServerImpl extends RemoteServer implements Server {
} }
@Override @Override
public List<GameTypeView> getGameTypes() throws MageException { public ServerState getServerState() throws RemoteException, MageException {
try { try {
return GameFactory.getInstance().getGameTypes(); return new ServerState(
GameFactory.getInstance().getGameTypes(),
PlayerFactory.getInstance().getPlayerTypes().toArray(new String[0]),
DeckValidatorFactory.getInstance().getDeckTypes().toArray(new String[0]),
testMode);
} }
catch (Exception ex) { catch (Exception ex) {
handleException(ex); handleException(ex);
@ -441,33 +447,44 @@ public class ServerImpl extends RemoteServer implements Server {
return null; return null;
} }
@Override // @Override
public String[] getPlayerTypes() throws MageException { // public List<GameTypeView> getGameTypes() throws MageException {
try { // try {
return PlayerFactory.getInstance().getPlayerTypes().toArray(new String[0]); // return GameFactory.getInstance().getGameTypes();
} // }
catch (Exception ex) { // catch (Exception ex) {
handleException(ex); // handleException(ex);
} // }
return null; // return null;
} // }
//
// @Override
// public String[] getPlayerTypes() throws MageException {
// try {
// return PlayerFactory.getInstance().getPlayerTypes().toArray(new String[0]);
// }
// catch (Exception ex) {
// handleException(ex);
// }
// return null;
// }
//
// @Override
// public String[] getDeckTypes() throws MageException {
// try {
// return DeckValidatorFactory.getInstance().getDeckTypes().toArray(new String[0]);
// }
// catch (Exception ex) {
// handleException(ex);
// }
// return null;
// }
@Override @Override
public String[] getDeckTypes() throws MageException { public void cheat(UUID gameId, UUID sessionId, UUID playerId, DeckCardLists deckList) throws MageException {
try {
return DeckValidatorFactory.getInstance().getDeckTypes().toArray(new String[0]);
}
catch (Exception ex) {
handleException(ex);
}
return null;
}
@Override
public void cheat(UUID gameId, UUID sessionId, DeckCardLists deckList) throws MageException {
try { try {
if (testMode) if (testMode)
GameManager.getInstance().cheat(gameId, sessionId, deckList); GameManager.getInstance().cheat(gameId, sessionId, playerId, deckList);
} }
catch (Exception ex) { catch (Exception ex) {
handleException(ex); handleException(ex);

View file

@ -77,10 +77,11 @@ public class Session {
return null; return null;
} }
public void fireCallback(ClientCallback call) { public synchronized void fireCallback(ClientCallback call) {
try { try {
call.setMessageId(messageId++); call.setMessageId(messageId++);
logger.info(sessionId + " - " + call.getMessageId() + " - " + call.getMethod()); if (logger.isLoggable(Level.FINE))
logger.fine(sessionId + " - " + call.getMessageId() + " - " + call.getMethod());
callback.setCallback(call); callback.setCallback(call);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);

View file

@ -50,6 +50,7 @@ import mage.players.Player;
import mage.util.Logging; import mage.util.Logging;
import mage.view.AbilityPickerView; import mage.view.AbilityPickerView;
import mage.view.CardsView; import mage.view.CardsView;
import mage.view.ChatMessage.MessageColor;
import mage.view.GameView; import mage.view.GameView;
/** /**
@ -90,7 +91,7 @@ public class GameController implements GameCallback {
updateGame(); updateGame();
break; break;
case INFO: case INFO:
ChatManager.getInstance().broadcast(chatId, "", event.getMessage()); ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK);
logger.finest(game.getId() + " " + event.getMessage()); logger.finest(game.getId() + " " + event.getMessage());
break; break;
case REVEAL: case REVEAL:
@ -152,7 +153,7 @@ public class GameController implements GameCallback {
gameSessions.put(playerId, gameSession); gameSessions.put(playerId, gameSession);
logger.info("player " + playerId + " has joined game " + game.getId()); logger.info("player " + playerId + " has joined game " + game.getId());
// gameSession.init(getGameView(playerId)); // gameSession.init(getGameView(playerId));
ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(playerId).getName() + " has joined the game"); ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(playerId).getName() + " has joined the game", MessageColor.BLACK);
if (allJoined()) { if (allJoined()) {
startGame(); startGame();
} }
@ -181,12 +182,12 @@ public class GameController implements GameCallback {
GameWatcher gameWatcher = new GameWatcher(sessionId, game.getId()); GameWatcher gameWatcher = new GameWatcher(sessionId, game.getId());
watchers.put(sessionId, gameWatcher); watchers.put(sessionId, gameWatcher);
gameWatcher.init(getGameView()); gameWatcher.init(getGameView());
ChatManager.getInstance().broadcast(chatId, "", " has started watching"); ChatManager.getInstance().broadcast(chatId, "", " has started watching", MessageColor.BLACK);
} }
public void stopWatching(UUID sessionId) { public void stopWatching(UUID sessionId) {
watchers.remove(sessionId); watchers.remove(sessionId);
ChatManager.getInstance().broadcast(chatId, "", " has stopped watching"); ChatManager.getInstance().broadcast(chatId, "", " has stopped watching", MessageColor.BLACK);
} }
public void concede(UUID sessionId) { public void concede(UUID sessionId) {
@ -197,11 +198,11 @@ public class GameController implements GameCallback {
game.quit(getPlayerId(sessionId)); game.quit(getPlayerId(sessionId));
} }
public void cheat(UUID sessionId, DeckCardLists deckList) { public void cheat(UUID sessionId, UUID playerId, DeckCardLists deckList) {
Player player = game.getPlayer(getPlayerId(sessionId)); Player player = game.getPlayer(playerId);
Deck deck = Deck.load(deckList); Deck deck = Deck.load(deckList);
deck.setOwnerId(player.getId()); game.loadCards(deck.getCards(), playerId);
for (Card card: deck.getCards().values()) { for (Card card: deck.getCards()) {
player.putOntoBattlefield(card, game); player.putOntoBattlefield(card, game);
} }
updateGame(); updateGame();
@ -222,7 +223,7 @@ public class GameController implements GameCallback {
public void timeout(UUID sessionId) { public void timeout(UUID sessionId) {
if (sessionPlayerMap.containsKey(sessionId)) { if (sessionPlayerMap.containsKey(sessionId)) {
ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(sessionPlayerMap.get(sessionId)).getName() + " has timed out. Auto concede."); ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(sessionPlayerMap.get(sessionId)).getName() + " has timed out. Auto concede.", MessageColor.BLACK);
concede(sessionId); concede(sessionId);
} }
} }
@ -272,68 +273,72 @@ public class GameController implements GameCallback {
} }
private synchronized void ask(UUID playerId, String question) { private synchronized void ask(UUID playerId, String question) {
informOthers(playerId);
if (gameSessions.containsKey(playerId)) if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).ask(question, getGameView(playerId)); gameSessions.get(playerId).ask(question, getGameView(playerId));
informOthers(playerId);
} }
private synchronized void chooseAbility(UUID playerId, Collection<? extends Ability> choices) { private synchronized void chooseAbility(UUID playerId, Collection<? extends Ability> choices) {
informOthers(playerId);
if (gameSessions.containsKey(playerId)) if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).chooseAbility(new AbilityPickerView(choices)); gameSessions.get(playerId).chooseAbility(new AbilityPickerView(choices));
informOthers(playerId);
} }
private synchronized void choose(UUID playerId, String message, String[] choices) { private synchronized void choose(UUID playerId, String message, String[] choices) {
informOthers(playerId);
if (gameSessions.containsKey(playerId)) if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).choose(message, choices); gameSessions.get(playerId).choose(message, choices);
informOthers(playerId);
} }
private synchronized void target(UUID playerId, String question, Cards cards, boolean required) { private synchronized void target(UUID playerId, String question, Cards cards, boolean required) {
if (gameSessions.containsKey(playerId)) {
if (cards != null)
gameSessions.get(playerId).target(question, new CardsView(cards.getCards(game)), required, getGameView(playerId));
else
gameSessions.get(playerId).target(question, new CardsView(), required, getGameView(playerId));
}
informOthers(playerId); informOthers(playerId);
if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).target(question, new CardsView(cards), required, getGameView(playerId));
} }
private synchronized void target(UUID playerId, String question, Collection<? extends Ability> abilities, boolean required) { private synchronized void target(UUID playerId, String question, Collection<? extends Ability> abilities, boolean required) {
informOthers(playerId);
if (gameSessions.containsKey(playerId)) if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).target(question, new CardsView(abilities, game), required, getGameView(playerId)); gameSessions.get(playerId).target(question, new CardsView(abilities, game.getState()), required, getGameView(playerId));
informOthers(playerId);
} }
private synchronized void select(UUID playerId, String message) { private synchronized void select(UUID playerId, String message) {
informOthers(playerId);
if (gameSessions.containsKey(playerId)) if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).select(message, getGameView(playerId)); gameSessions.get(playerId).select(message, getGameView(playerId));
informOthers(playerId);
} }
private synchronized void playMana(UUID playerId, String message) { private synchronized void playMana(UUID playerId, String message) {
informOthers(playerId);
if (gameSessions.containsKey(playerId)) if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).playMana(message, getGameView(playerId)); gameSessions.get(playerId).playMana(message, getGameView(playerId));
informOthers(playerId);
} }
private synchronized void playXMana(UUID playerId, String message) { private synchronized void playXMana(UUID playerId, String message) {
informOthers(playerId);
if (gameSessions.containsKey(playerId)) if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).playXMana(message, getGameView(playerId)); gameSessions.get(playerId).playXMana(message, getGameView(playerId));
informOthers(playerId);
} }
private synchronized void amount(UUID playerId, String message, int min, int max) { private synchronized void amount(UUID playerId, String message, int min, int max) {
informOthers(playerId);
if (gameSessions.containsKey(playerId)) if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).getAmount(message, min, max); gameSessions.get(playerId).getAmount(message, min, max);
informOthers(playerId);
} }
private synchronized void revealCards(String name, Cards cards) { private synchronized void revealCards(String name, Cards cards) {
for (GameSession session: gameSessions.values()) { for (GameSession session: gameSessions.values()) {
session.revealCards(name, new CardsView(cards)); session.revealCards(name, new CardsView(cards.getCards(game)));
} }
} }
private synchronized void lookAtCards(UUID playerId, String name, Cards cards) { private synchronized void lookAtCards(UUID playerId, String name, Cards cards) {
if (gameSessions.containsKey(playerId)) if (gameSessions.containsKey(playerId))
gameSessions.get(playerId).revealCards(name, new CardsView(cards)); gameSessions.get(playerId).revealCards(name, new CardsView(cards.getCards(game)));
} }
private void informOthers(UUID playerId) { private void informOthers(UUID playerId) {
@ -349,12 +354,12 @@ public class GameController implements GameCallback {
} }
private GameView getGameView() { private GameView getGameView() {
return new GameView(game.getState()); return new GameView(game.getState(), game);
} }
private GameView getGameView(UUID playerId) { private GameView getGameView(UUID playerId) {
GameView gameView = new GameView(game.getState()); GameView gameView = new GameView(game.getState(), game);
gameView.setHand(new CardsView(game.getPlayer(playerId).getHand())); gameView.setHand(new CardsView(game.getPlayer(playerId).getHand().getCards(game)));
return gameView; return gameView;
} }

View file

@ -108,8 +108,8 @@ public class GameManager {
// return gameControllers.get(gameId).createReplay(); // return gameControllers.get(gameId).createReplay();
// } // }
public void cheat(UUID gameId, UUID sessionId, DeckCardLists deckList) { public void cheat(UUID gameId, UUID sessionId, UUID playerId, DeckCardLists deckList) {
gameControllers.get(gameId).cheat(sessionId, deckList); gameControllers.get(gameId).cheat(sessionId, playerId, deckList);
} }
void timeout(UUID gameId, UUID sessionId) { void timeout(UUID gameId, UUID sessionId) {

View file

@ -37,10 +37,12 @@ import mage.game.*;
public class GameReplay { public class GameReplay {
private GameStates savedGame; private GameStates savedGame;
private Game game;
private int stateIndex; private int stateIndex;
public GameReplay(GameStates savedGame) { public GameReplay(Game game) {
this.savedGame = savedGame; this.savedGame = game.getGameStates();
this.game = game;
} }
public void start() { public void start() {
@ -61,4 +63,7 @@ public class GameReplay {
return null; return null;
} }
public Game getGame() {
return this.game;
}
} }

View file

@ -63,6 +63,7 @@ public class GameSession extends GameWatcher {
public void ask(final String question, final GameView gameView) { public void ask(final String question, final GameView gameView) {
if (!killed) { if (!killed) {
setupTimeout();
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("gameAsk", new GameClientMessage(gameView, question))); session.fireCallback(new ClientCallback("gameAsk", new GameClientMessage(gameView, question)));
@ -71,6 +72,7 @@ public class GameSession extends GameWatcher {
public void target(final String question, final CardsView cardView, final boolean required, final GameView gameView) { public void target(final String question, final CardsView cardView, final boolean required, final GameView gameView) {
if (!killed) { if (!killed) {
setupTimeout();
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("gameTarget", new GameClientMessage(gameView, question, cardView, required))); session.fireCallback(new ClientCallback("gameTarget", new GameClientMessage(gameView, question, cardView, required)));
@ -79,6 +81,7 @@ public class GameSession extends GameWatcher {
public void select(final String message, final GameView gameView) { public void select(final String message, final GameView gameView) {
if (!killed) { if (!killed) {
setupTimeout();
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("gameSelect", new GameClientMessage(gameView, message))); session.fireCallback(new ClientCallback("gameSelect", new GameClientMessage(gameView, message)));
@ -87,6 +90,7 @@ public class GameSession extends GameWatcher {
public void chooseAbility(final AbilityPickerView abilities) { public void chooseAbility(final AbilityPickerView abilities) {
if (!killed) { if (!killed) {
setupTimeout();
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("gameChooseAbility", abilities)); session.fireCallback(new ClientCallback("gameChooseAbility", abilities));
@ -95,6 +99,7 @@ public class GameSession extends GameWatcher {
public void choose(final String message, final String[] choices) { public void choose(final String message, final String[] choices) {
if (!killed) { if (!killed) {
setupTimeout();
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("gameChoose", new GameClientMessage(choices, message))); session.fireCallback(new ClientCallback("gameChoose", new GameClientMessage(choices, message)));
@ -103,6 +108,7 @@ public class GameSession extends GameWatcher {
public void playMana(final String message, final GameView gameView) { public void playMana(final String message, final GameView gameView) {
if (!killed) { if (!killed) {
setupTimeout();
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("gamePlayMana", new GameClientMessage(gameView, message))); session.fireCallback(new ClientCallback("gamePlayMana", new GameClientMessage(gameView, message)));
@ -111,6 +117,7 @@ public class GameSession extends GameWatcher {
public void playXMana(final String message, final GameView gameView) { public void playXMana(final String message, final GameView gameView) {
if (!killed) { if (!killed) {
setupTimeout();
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("gamePlayXMana", new GameClientMessage(gameView, message))); session.fireCallback(new ClientCallback("gamePlayXMana", new GameClientMessage(gameView, message)));
@ -119,6 +126,7 @@ public class GameSession extends GameWatcher {
public void getAmount(final String message, final int min, final int max) { public void getAmount(final String message, final int min, final int max) {
if (!killed) { if (!killed) {
setupTimeout();
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("gameSelectAmount", new GameClientMessage(message, min, max))); session.fireCallback(new ClientCallback("gameSelectAmount", new GameClientMessage(message, min, max)));

View file

@ -43,7 +43,7 @@ import mage.view.TableView;
public interface GamesRoom extends Room { public interface GamesRoom extends Room {
public List<TableView> getTables(); public List<TableView> getTables();
public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws GameException; public boolean joinTable(UUID sessionId, UUID tableId, String name, DeckCardLists deckList) throws GameException;
public TableView createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range); public TableView createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range);
public void removeTable(UUID sessionId, UUID tableId); public void removeTable(UUID sessionId, UUID tableId);
public TableView getTable(UUID tableId); public TableView getTable(UUID tableId);

View file

@ -62,9 +62,9 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
} }
@Override @Override
public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws GameException { public boolean joinTable(UUID sessionId, UUID tableId, String name, DeckCardLists deckList) throws GameException {
if (tables.containsKey(tableId)) { if (tables.containsKey(tableId)) {
return TableManager.getInstance().joinTable(sessionId, tableId, seatNum, name, deckList); return TableManager.getInstance().joinTable(sessionId, tableId, name, deckList);
} else { } else {
return false; return false;
} }

View file

@ -30,6 +30,7 @@ package mage.server.game;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
@ -48,7 +49,7 @@ public class PlayerFactory {
private final static PlayerFactory INSTANCE = new PlayerFactory(); private final static PlayerFactory INSTANCE = new PlayerFactory();
private final static Logger logger = Logging.getLogger(PlayerFactory.class.getName()); private final static Logger logger = Logging.getLogger(PlayerFactory.class.getName());
private Map<String, Class> playerTypes = new HashMap<String, Class>(); private Map<String, Class> playerTypes = new LinkedHashMap<String, Class>();
public static PlayerFactory getInstance() { public static PlayerFactory getInstance() {
return INSTANCE; return INSTANCE;

View file

@ -30,6 +30,7 @@ package mage.server.game;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.game.Game;
import mage.game.GameState; import mage.game.GameState;
import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallback;
import mage.server.Session; import mage.server.Session;
@ -45,19 +46,19 @@ public class ReplaySession implements GameCallback {
private final static Logger logger = Logging.getLogger(ReplaySession.class.getName()); private final static Logger logger = Logging.getLogger(ReplaySession.class.getName());
private GameReplay game; private GameReplay replay;
protected UUID sessionId; protected UUID sessionId;
ReplaySession(UUID tableId, UUID sessionId) { ReplaySession(UUID tableId, UUID sessionId) {
this.game = TableManager.getInstance().createReplay(tableId); this.replay = TableManager.getInstance().createReplay(tableId);
this.sessionId = sessionId; this.sessionId = sessionId;
} }
public void replay() { public void replay() {
game.start(); replay.start();
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("replayInit", new GameView(game.next()))); session.fireCallback(new ClientCallback("replayInit", new GameView(replay.next(), replay.getGame())));
} }
public void stop() { public void stop() {
@ -65,11 +66,11 @@ public class ReplaySession implements GameCallback {
} }
public synchronized void next() { public synchronized void next() {
updateGame(game.next()); updateGame(replay.next(), replay.getGame());
} }
public synchronized void previous() { public synchronized void previous() {
updateGame(game.previous()); updateGame(replay.previous(), replay.getGame());
} }
@Override @Override
@ -79,14 +80,14 @@ public class ReplaySession implements GameCallback {
session.fireCallback(new ClientCallback("replayDone", result)); session.fireCallback(new ClientCallback("replayDone", result));
} }
private void updateGame(final GameState state) { private void updateGame(final GameState state, Game game) {
if (state == null) { if (state == null) {
gameResult("game ended"); gameResult("game ended");
} }
else { else {
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) if (session != null)
session.fireCallback(new ClientCallback("replayUpdate", new GameView(state))); session.fireCallback(new ClientCallback("replayUpdate", new GameView(state, game)));
} }
} }

View file

@ -86,21 +86,26 @@ public class TableController {
table = new Table(gameType, DeckValidatorFactory.getInstance().createDeckValidator(deckType), playerTypes); table = new Table(gameType, DeckValidatorFactory.getInstance().createDeckValidator(deckType), playerTypes);
} }
public synchronized boolean joinTable(UUID sessionId, int seatNum, String name, DeckCardLists deckList) throws GameException { public synchronized boolean joinTable(UUID sessionId, String name, DeckCardLists deckList) throws GameException {
if (table.getState() != TableState.WAITING) { if (table.getState() != TableState.WAITING) {
return false; return false;
} }
Seat seat = table.getSeats()[seatNum]; Seat seat = table.getNextAvailableSeat();
if (seat == null) {
throw new GameException("No available seats.");
}
Deck deck = Deck.load(deckList); Deck deck = Deck.load(deckList);
if (!Main.server.isTestMode() && !validDeck(deck)) { if (!Main.server.isTestMode() && !validDeck(deck)) {
throw new GameException(name + " has an invalid deck for this format"); throw new GameException(name + " has an invalid deck for this format");
} }
Player player = createPlayer(name, deck, seat.getPlayerType()); Player player = createPlayer(name, deck, seat.getPlayerType());
table.joinTable(player, seatNum); game.loadCards(deck.getCards(), player.getId());
game.loadCards(deck.getSideboard(), player.getId());
table.joinTable(player, seat);
logger.info("player joined " + player.getId()); logger.info("player joined " + player.getId());
//only add human players to sessionPlayerMap //only add human players to sessionPlayerMap
if (table.getSeats()[seatNum].getPlayer().isHuman()) { if (seat.getPlayer().isHuman()) {
sessionPlayerMap.put(sessionId, player.getId()); sessionPlayerMap.put(sessionId, player.getId());
} }
@ -183,11 +188,11 @@ public class TableController {
private void saveGame() { private void saveGame() {
try { try {
//use buffering
OutputStream file = new FileOutputStream("saved/" + game.getId().toString() + ".game"); OutputStream file = new FileOutputStream("saved/" + game.getId().toString() + ".game");
OutputStream buffer = new BufferedOutputStream(file); OutputStream buffer = new BufferedOutputStream(file);
ObjectOutput output = new ObjectOutputStream(new GZIPOutputStream(buffer)); ObjectOutput output = new ObjectOutputStream(new GZIPOutputStream(buffer));
try { try {
output.writeObject(game);
output.writeObject(game.getGameStates()); output.writeObject(game.getGameStates());
} }
finally { finally {
@ -200,17 +205,16 @@ public class TableController {
} }
} }
private GameStates loadGame() { private Game loadGame() {
try{ try{
//use buffering
InputStream file = new FileInputStream("saved/" + gameId.toString() + ".game"); InputStream file = new FileInputStream("saved/" + gameId.toString() + ".game");
InputStream buffer = new BufferedInputStream(file); InputStream buffer = new BufferedInputStream(file);
ObjectInput input = new CopierObjectInputStream(Main.classLoader, new GZIPInputStream(buffer)); ObjectInput input = new CopierObjectInputStream(Main.classLoader, new GZIPInputStream(buffer));
//ObjectInput input = new ObjectInputStream(buffer);
try { try {
//deserialize the List Game game = (Game)input.readObject();
GameStates gameStates = (GameStates)input.readObject(); GameStates states = (GameStates)input.readObject();
return gameStates; game.loadGameStates(states);
return game;
} }
finally { finally {
input.close(); input.close();

View file

@ -71,8 +71,8 @@ public class TableManager {
return tables.values(); return tables.values();
} }
public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws GameException { public boolean joinTable(UUID sessionId, UUID tableId, String name, DeckCardLists deckList) throws GameException {
return controllers.get(tableId).joinTable(sessionId, seatNum, name, deckList); return controllers.get(tableId).joinTable(sessionId, name, deckList);
} }
public void removeSession(UUID sessionId) { public void removeSession(UUID sessionId) {

View file

@ -0,0 +1,102 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets;
import mage.sets.magic2011.*;
import mage.cards.ExpansionSet;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class Magic2011 extends ExpansionSet {
private static final Magic2011 fINSTANCE = new Magic2011();
public static Magic2011 getInstance() {
return fINSTANCE;
}
private Magic2011() {
this.name = "Magic 2011";
this.cards.add(AcidicSlime.class);
this.cards.add(ActOfTreason.class);
this.cards.add(AetherAdept.class);
this.cards.add(AirServant.class);
this.cards.add(AjaniGoldmane.class);
// this.cards.add(AlluringSiren.class);
// this.cards.add(AngelsFeather.class);
// this.cards.add(AngelsMercy.class);
// this.cards.add(AntQueen.class);
// this.cards.add(ArmoredAscension.class);
// this.cards.add(Assassinate.class);
// this.cards.add(AwakenerDruid.class);
// this.cards.add(BallLightning.class);
// this.cards.add(BaneslayerAngel.class);
// this.cards.add(BirdsOfParadise.class);
// this.cards.add(BerserkersOfBloodRidge.class);
// this.cards.add(BlackKnight.class);
// this.cards.add(BlindingMage.class);
// this.cards.add(BogWraith.class);
// this.cards.add(BogardanHellkite.class);
// this.cards.add(Cancel.class);
// this.cards.add(CelestialPurge.class);
// this.cards.add(DiabolicTutor.class);
// this.cards.add(DoomBlade.class);
// this.cards.add(DragonskullSummit.class);
// this.cards.add(Earthquake.class);
// this.cards.add(EliteVanguard.class);
// this.cards.add(Flashfreeze.class);
// this.cards.add(GargoyleCastle.class);
// this.cards.add(GarrukWildspeaker.class);
// this.cards.add(GiantGrowth.class);
// this.cards.add(GlacialFortress.class);
// this.cards.add(GreatSableStag.class);
// this.cards.add(HonorOfThePure.class);
// this.cards.add(HowlingMine.class);
// this.cards.add(JaceBeleren.class);
// this.cards.add(LlanowarElves.class);
// this.cards.add(LightningBolt.class);
// this.cards.add(MasterOfTheWildHunt.class);
// this.cards.add(MightOfOaks.class);
// this.cards.add(MindRot.class);
// this.cards.add(Naturalize.class);
// this.cards.add(Overrun.class);
// this.cards.add(RampantGrowth.class);
// this.cards.add(MindSpring.class);
// this.cards.add(Negate.class);
// this.cards.add(RootboundCrag.class);
// this.cards.add(RoyalAssassin.class);
// this.cards.add(SafePassage.class);
// this.cards.add(SunpetalGrove.class);
// this.cards.add(TerramorphicExpanse.class);
// this.cards.add(TimeWarp.class);
// this.cards.add(WhiteKnight.class);
}
}

View file

@ -47,7 +47,11 @@ public class RiseOfTheEldrazi extends ExpansionSet {
this.name = "Rise Of The Eldrazi"; this.name = "Rise Of The Eldrazi";
this.cards.add(Deprive.class); this.cards.add(Deprive.class);
this.cards.add(GideonJura.class); this.cards.add(GideonJura.class);
this.cards.add(JoragaTreespeaker.class);
this.cards.add(KarganDragonlord.class); this.cards.add(KarganDragonlord.class);
this.cards.add(KozileksPredator.class);
this.cards.add(NestInvader.class);
this.cards.add(Vengevine.class);
this.cards.add(WallOfOmens.class); this.cards.add(WallOfOmens.class);
} }

View file

@ -47,6 +47,7 @@ public class Sets extends ArrayList<ExpansionSet> {
this.add(AlaraReborn.getInstance()); this.add(AlaraReborn.getInstance());
this.add(Conflux.getInstance()); this.add(Conflux.getInstance());
this.add(Magic2010.getInstance()); this.add(Magic2010.getInstance());
this.add(Magic2011.getInstance());
this.add(Planechase.getInstance()); this.add(Planechase.getInstance());
this.add(RiseOfTheEldrazi.getInstance()); this.add(RiseOfTheEldrazi.getInstance());
this.add(ShardsOfAlara.getInstance()); this.add(ShardsOfAlara.getInstance());

View file

@ -45,10 +45,13 @@ public class Worldwake extends ExpansionSet {
private Worldwake() { private Worldwake() {
this.name = "Worldwake"; this.name = "Worldwake";
this.cards.add(ArborElf.class);
this.cards.add(BasiliskCollar.class); this.cards.add(BasiliskCollar.class);
this.cards.add(CelestialColonnade.class); this.cards.add(CelestialColonnade.class);
this.cards.add(DreadStatuary.class);
this.cards.add(EverflowingChalice.class); this.cards.add(EverflowingChalice.class);
this.cards.add(JaceTheMindSculptor.class); this.cards.add(JaceTheMindSculptor.class);
this.cards.add(KhalniGarden.class);
this.cards.add(LavaclawReaches.class); this.cards.add(LavaclawReaches.class);
this.cards.add(RagingRavine.class); this.cards.add(RagingRavine.class);
this.cards.add(SearingBlaze.class); this.cards.add(SearingBlaze.class);
@ -56,6 +59,7 @@ public class Worldwake extends ExpansionSet {
this.cards.add(StirringWildwood.class); this.cards.add(StirringWildwood.class);
this.cards.add(StoneforgeMystic.class); this.cards.add(StoneforgeMystic.class);
this.cards.add(TectonicEdge.class); this.cards.add(TectonicEdge.class);
this.cards.add(WolfbriarElemental.class);
} }
} }

View file

@ -45,12 +45,16 @@ public class Zendikar extends ExpansionSet {
private Zendikar() { private Zendikar() {
this.name = "Zendikar"; this.name = "Zendikar";
this.cards.add(AdventuringGear.class);
this.cards.add(AetherFigment.class);
this.cards.add(ArchiveTrap.class); this.cards.add(ArchiveTrap.class);
this.cards.add(AridMesa.class); this.cards.add(AridMesa.class);
this.cards.add(BeastmasterAscension.class);
this.cards.add(BraveTheElements.class); this.cards.add(BraveTheElements.class);
this.cards.add(BurstLightning.class); this.cards.add(BurstLightning.class);
this.cards.add(ConquerorsPledge.class); this.cards.add(ConquerorsPledge.class);
this.cards.add(DayOfJudgment.class); this.cards.add(DayOfJudgment.class);
this.cards.add(EldraziMonument.class);
this.cards.add(EmeriaAngel.class); this.cards.add(EmeriaAngel.class);
this.cards.add(GoblinGuide.class); this.cards.add(GoblinGuide.class);
this.cards.add(GoblinRuinblaster.class); this.cards.add(GoblinRuinblaster.class);
@ -60,6 +64,7 @@ public class Zendikar extends ExpansionSet {
this.cards.add(MistyRainforest.class); this.cards.add(MistyRainforest.class);
this.cards.add(OranRiefTheVastwood.class); this.cards.add(OranRiefTheVastwood.class);
this.cards.add(RampagingBaloths.class); this.cards.add(RampagingBaloths.class);
this.cards.add(RiverBoa.class);
this.cards.add(ScaldingTarn.class); this.cards.add(ScaldingTarn.class);
this.cards.add(ScuteMob.class); this.cards.add(ScuteMob.class);
this.cards.add(SpreadingSeas.class); this.cards.add(SpreadingSeas.class);

View file

@ -32,6 +32,7 @@ import java.util.UUID;
import mage.Constants.CardType; import mage.Constants.CardType;
import mage.Constants.Outcome; import mage.Constants.Outcome;
import mage.Constants.Zone; import mage.Constants.Zone;
import mage.MageObjectImpl;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.BoostEquippedEffect; import mage.abilities.effects.common.BoostEquippedEffect;
@ -46,12 +47,11 @@ import mage.sets.AlaraReborn;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class BehemothSledge extends CardImpl { public class BehemothSledge extends CardImpl<BehemothSledge> {
public BehemothSledge(UUID ownerId) { public BehemothSledge(UUID ownerId) {
super(ownerId, "Behemoth Sledge", new CardType[]{CardType.ARTIFACT}, "{1}{G}{W}"); super(ownerId, "Behemoth Sledge", new CardType[]{CardType.ARTIFACT}, "{1}{G}{W}");
this.expansionSetId = AlaraReborn.getInstance().getId(); this.expansionSetId = AlaraReborn.getInstance().getId();
this.art = "120963_typ_reg_sty_010.jpg";
this.subtype.add("Equipment"); this.subtype.add("Equipment");
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3))); this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(LifelinkAbility.getInstance()))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(LifelinkAbility.getInstance())));
@ -59,4 +59,18 @@ public class BehemothSledge extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2)));
} }
protected BehemothSledge(BehemothSledge me) {
super(me);
}
@Override
public BehemothSledge copy() {
return new BehemothSledge(this);
}
@Override
public String getArt() {
return "120963_typ_reg_sty_010.jpg";
}
} }

View file

@ -40,17 +40,30 @@ import mage.target.common.TargetCreaturePermanent;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class BituminousBlast extends CardImpl { public class BituminousBlast extends CardImpl<BituminousBlast> {
public BituminousBlast(UUID ownerId) { public BituminousBlast(UUID ownerId) {
super(ownerId, "Bituminous Blast", new CardType[]{CardType.INSTANT}, "{3}{B}{R}"); super(ownerId, "Bituminous Blast", new CardType[]{CardType.INSTANT}, "{3}{B}{R}");
this.expansionSetId = AlaraReborn.getInstance().getId(); this.expansionSetId = AlaraReborn.getInstance().getId();
this.color.setBlack(true); this.color.setBlack(true);
this.color.setRed(true); this.color.setRed(true);
this.art = "121045_typ_reg_sty_010.jpg";
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new DamageTargetEffect(4)); this.getSpellAbility().addEffect(new DamageTargetEffect(4));
this.addAbility(new CascadeAbility()); this.addAbility(new CascadeAbility());
} }
public BituminousBlast(final BituminousBlast card) {
super(card);
}
@Override
public BituminousBlast copy() {
return new BituminousBlast(this);
}
@Override
public String getArt() {
return "121045_typ_reg_sty_010.jpg";
}
} }

View file

@ -40,7 +40,7 @@ import mage.sets.AlaraReborn;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class BloodbraidElf extends CardImpl { public class BloodbraidElf extends CardImpl<BloodbraidElf> {
public BloodbraidElf(UUID ownerId) { public BloodbraidElf(UUID ownerId) {
super(ownerId, "Bloodbraid Elf", new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); super(ownerId, "Bloodbraid Elf", new CardType[]{CardType.CREATURE}, "{2}{R}{G}");
@ -49,10 +49,23 @@ public class BloodbraidElf extends CardImpl {
this.color.setGreen(true); this.color.setGreen(true);
this.subtype.add("Elf"); this.subtype.add("Elf");
this.subtype.add("Berserker"); this.subtype.add("Berserker");
this.art = "121042_typ_reg_sty_010.jpg";
this.power = new MageInt(3); this.power = new MageInt(3);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
this.addAbility(HasteAbility.getInstance()); this.addAbility(HasteAbility.getInstance());
this.addAbility(new CascadeAbility()); this.addAbility(new CascadeAbility());
} }
public BloodbraidElf(final BloodbraidElf card) {
super(card);
}
@Override
public BloodbraidElf copy() {
return new BloodbraidElf(this);
}
@Override
public String getArt() {
return "121042_typ_reg_sty_010.jpg";
}
} }

Some files were not shown because too many files have changed in this diff Show more